diff --git a/.clang-format b/.clang-format index b641a647431..7460950e71b 100644 --- a/.clang-format +++ b/.clang-format @@ -3,6 +3,7 @@ Language: Cpp BasedOnStyle: Google DerivePointerAlignment: false PointerAlignment: Left +IncludeBlocks: Preserve --- Language: ObjC BasedOnStyle: Google diff --git a/.clang-tidy b/.clang-tidy index 752b25eef70..8714bad3bc1 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,37 +1,122 @@ --- -# Disable abseil-no-namespace: https://bugs.llvm.org/show_bug.cgi?id=47947 +# Note on checks are disabled on purpose +# +# - abseil-no-namespace +# https://bugs.llvm.org/show_bug.cgi?id=47947 +# +# - bugprone-reserved-identifier +# Some macros need to be defined for portability purpose; e.g. _BSD_SOURCE. +# +# - google-upgrade-googletest-case +# This requires googletest 1.10 which is higher than ones installed on many linux distributions. +# +# - modernize-redundant-void-arg +# Some source should be strictly C99 and func(void) should be used. +# +# Note on checks which will be enabled in future. These are good to have but +# it's not activated yet due to the existing issues with the checks. +# Once those issues are clear, these checks can be enabled later. +# +# - bugprone-branch-clone +# - bugprone-infinite-loop +# - bugprone-narrowing-conversions +# - bugprone-not-null-terminated-result +# - bugprone-signed-char-misuse +# - bugprone-sizeof-expression +# - bugprone-too-small-loop-variable +# - clang-diagnostic-deprecated-declarations +# - clang-diagnostic-unused-function +# - google-readability-avoid-underscore-in-googletest-name +# - google-runtime-int +# - google-runtime-references +# - modernize-avoid-bind +# - modernize-deprecated-headers +# - modernize-loop-convert +# - modernize-pass-by-value +# - modernize-raw-string-literal +# - modernize-return-braced-init-list +# - modernize-use-auto +# - modernize-use-default-member-init +# - modernize-use-emplace +# - modernize-use-equals-default +# - modernize-use-equals-delete +# - modernize-use-using +# - performance-no-automatic-move +# - performance-unnecessary-copy-initialization +# - performance-unnecessary-value-param +# - readability-else-after-return +# - readability-implicit-bool-conversion +# - readability-redundant-declaration +# - readability-static-definition-in-anonymous-namespace +# Checks: '-*, abseil-*, -abseil-no-namespace, bugprone-*, + -bugprone-branch-clone, + -bugprone-infinite-loop, -bugprone-narrowing-conversions, + -bugprone-not-null-terminated-result, + -bugprone-reserved-identifier, + -bugprone-signed-char-misuse, + -bugprone-sizeof-expression, -bugprone-too-small-loop-variable, - performance-*, - -performance-unnecessary-copy-initialization, - -performance-unnecessary-value-param, google-*, + -google-readability-avoid-underscore-in-googletest-name, -google-runtime-int, -google-runtime-references, + -google-upgrade-googletest-case, + performance-*, + -performance-no-automatic-move, + -performance-unnecessary-copy-initialization, + -performance-unnecessary-value-param, + clang-diagnostic-deprecated-register, + clang-diagnostic-expansion-to-defined, + clang-diagnostic-ignored-attributes, + clang-diagnostic-non-pod-varargs, + clang-diagnostic-shadow-field, + clang-diagnostic-shift-sign-overflow, + clang-diagnostic-tautological-undefined-compare, + clang-diagnostic-thread-safety*, + clang-diagnostic-undefined-bool-conversion, + clang-diagnostic-unreachable-code, + clang-diagnostic-unreachable-code-loop-increment, + clang-diagnostic-unused-const-variable, + clang-diagnostic-unused-lambda-capture, + clang-diagnostic-unused-local-typedef, + clang-diagnostic-unused-private-field, + clang-diagnostic-user-defined-warnings, misc-definitions-in-headers, misc-static-assert, misc-unconventional-assign-operator, misc-uniqueptr-reset-release, misc-unused-alias-decls, misc-unused-using-decls, + modernize-make-shared, modernize-make-unique, - -modernize-redundant-void-arg, modernize-replace-auto-ptr, + modernize-replace-random-shuffle, modernize-shrink-to-fit, + modernize-unary-static-assert, modernize-use-bool-literals, + modernize-use-noexcept, modernize-use-nullptr, modernize-use-override, + modernize-use-transparent-functors, + readability-const-return-type, readability-container-size-empty, + readability-delete-null-pointer, readability-deleted-default, readability-function-size, readability-inconsistent-declaration-parameter-name, + readability-misleading-indentation, + readability-misplaced-array-index, readability-redundant-control-flow, + readability-redundant-function-ptr-dereference, readability-redundant-smartptr-get, - readability-string-compare' + readability-simplify-boolean-expr, + readability-string-compare, + readability-uniqueptr-delete-release' WarningsAsErrors: '*' CheckOptions: - key: readability-function-size.StatementThreshold diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 41f81be1db6..e69dc0bd3ba 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Report a bug about: Create a report to help us improve labels: kind/bug, priority/P2 -assignees: markdroth +assignees: nicolasnoble --- diff --git a/.github/ISSUE_TEMPLATE/cleanup_request.md b/.github/ISSUE_TEMPLATE/cleanup_request.md index 7da478019fc..c9a6d3f911d 100644 --- a/.github/ISSUE_TEMPLATE/cleanup_request.md +++ b/.github/ISSUE_TEMPLATE/cleanup_request.md @@ -2,7 +2,7 @@ name: Request a cleanup about: Suggest a cleanup in our repository labels: kind/internal cleanup, priority/P2 -assignees: markdroth +assignees: nicolasnoble --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 00599d145d8..e3137998ae0 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Request a feature about: Suggest an idea for this project labels: kind/enhancement, priority/P2 -assignees: markdroth +assignees: nicolasnoble --- diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md index 5dc067381f9..cfde18bec27 100644 --- a/.github/ISSUE_TEMPLATE/question.md +++ b/.github/ISSUE_TEMPLATE/question.md @@ -2,7 +2,7 @@ name: Ask a question about: Ask a question labels: kind/question, priority/P3 -assignees: markdroth +assignees: nicolasnoble --- diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a85cfad9c7a..57af6c21597 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,4 +8,4 @@ If you know who should review your pull request, please remove the mentioning be --> -@markdroth +@nicolasnoble diff --git a/BUILD b/BUILD index 42210ae7199..ba5613b7244 100644 --- a/BUILD +++ b/BUILD @@ -85,11 +85,11 @@ config_setting( python_config_settings() # This should be updated along with build_handwritten.yaml -g_stands_for = "gilded" # @unused +g_stands_for = "guadalupe_river_park_conservancy" # @unused -core_version = "15.0.0" # @unused +core_version = "16.0.0" # @unused -version = "1.37.0-dev" # @unused +version = "1.38.0-dev" # @unused GPR_PUBLIC_HDRS = [ "include/grpc/support/alloc.h", @@ -127,6 +127,13 @@ GRPC_PUBLIC_HDRS = [ "include/grpc/support/workaround_list.h", ] +GRPC_PUBLIC_EVENT_ENGINE_HDRS = [ + "include/grpc/event_engine/channel_args.h", + "include/grpc/event_engine/event_engine.h", + "include/grpc/event_engine/port.h", + "include/grpc/event_engine/slice_allocator.h", +] + GRPC_SECURE_PUBLIC_HDRS = [ "include/grpc/grpc_security.h", ] @@ -357,6 +364,29 @@ grpc_cc_library( grpc_cc_library( name = "grpc++", + hdrs = [ + "src/cpp/client/secure_credentials.h", + "src/cpp/common/secure_auth_context.h", + "src/cpp/common/tls_credentials_options_util.h", + "src/cpp/server/secure_server_credentials.h", + ], + language = "c++", + public_hdrs = GRPCXX_PUBLIC_HDRS, + select_deps = { + "grpc_no_xds": [], + "//conditions:default": [ + "grpc++_xds_client", + "grpc++_xds_server", + ], + }, + standalone = True, + deps = [ + "grpc++_internals", + ], +) + +grpc_cc_library( + name = "grpc++_internals", srcs = [ "src/cpp/client/insecure_credentials.cc", "src/cpp/client/secure_credentials.cc", @@ -382,14 +412,6 @@ grpc_cc_library( ], language = "c++", public_hdrs = GRPCXX_PUBLIC_HDRS, - select_deps = { - "grpc_no_xds": [], - "//conditions:default": [ - "grpc++_xds_client", - "grpc++_xds_server", - ], - }, - standalone = True, deps = [ "gpr", "grpc", @@ -411,7 +433,7 @@ grpc_cc_library( ], language = "c++", deps = [ - "grpc++_base", + "grpc++_internals", ], ) @@ -428,7 +450,7 @@ grpc_cc_library( "include/grpcpp/xds_server_builder.h", ], deps = [ - "grpc++_base", + "grpc++_internals", ], ) @@ -569,6 +591,7 @@ grpc_cc_library( "src/core/lib/gprpp/mpscq.cc", "src/core/lib/gprpp/stat_posix.cc", "src/core/lib/gprpp/stat_windows.cc", + "src/core/lib/gprpp/status_helper.cc", "src/core/lib/gprpp/thd_posix.cc", "src/core/lib/gprpp/thd_windows.cc", "src/core/lib/gprpp/time_util.cc", @@ -604,6 +627,7 @@ grpc_cc_library( "src/core/lib/gprpp/memory.h", "src/core/lib/gprpp/mpscq.h", "src/core/lib/gprpp/stat.h", + "src/core/lib/gprpp/status_helper.h", "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/gprpp/time_util.h", @@ -622,6 +646,8 @@ grpc_cc_library( language = "c++", public_hdrs = GPR_PUBLIC_HDRS, deps = [ + "debug_location", + "google_api_upb", "gpr_codegen", "grpc_codegen", ], @@ -730,6 +756,8 @@ grpc_cc_library( grpc_cc_library( name = "grpc_base_c", srcs = [ + "src/core/lib/address_utils/parse_address.cc", + "src/core/lib/address_utils/sockaddr_utils.cc", "src/core/lib/avl/avl.cc", "src/core/lib/backoff/backoff.cc", "src/core/lib/channel/channel_args.cc", @@ -751,6 +779,8 @@ grpc_cc_library( "src/core/lib/compression/stream_compression_identity.cc", "src/core/lib/debug/stats.cc", "src/core/lib/debug/stats_data.cc", + "src/core/lib/event_engine/slice_allocator.cc", + "src/core/lib/event_engine/sockaddr.cc", "src/core/lib/http/format_request.cc", "src/core/lib/http/httpcli.cc", "src/core/lib/http/parser.cc", @@ -795,7 +825,6 @@ grpc_cc_library( "src/core/lib/iomgr/is_epollexclusive_available.cc", "src/core/lib/iomgr/load_file.cc", "src/core/lib/iomgr/lockfree_event.cc", - "src/core/lib/iomgr/parse_address.cc", "src/core/lib/iomgr/polling_entity.cc", "src/core/lib/iomgr/pollset.cc", "src/core/lib/iomgr/pollset_custom.cc", @@ -809,7 +838,6 @@ grpc_cc_library( "src/core/lib/iomgr/resolve_address_posix.cc", "src/core/lib/iomgr/resolve_address_windows.cc", "src/core/lib/iomgr/resource_quota.cc", - "src/core/lib/iomgr/sockaddr_utils.cc", "src/core/lib/iomgr/socket_factory_posix.cc", "src/core/lib/iomgr/socket_mutator.cc", "src/core/lib/iomgr/socket_utils_common_posix.cc", @@ -892,6 +920,8 @@ grpc_cc_library( "src/core/lib/uri/uri_parser.cc", ], hdrs = [ + "src/core/lib/address_utils/parse_address.h", + "src/core/lib/address_utils/sockaddr_utils.h", "src/core/lib/avl/avl.h", "src/core/lib/backoff/backoff.h", "src/core/lib/channel/channel_args.h", @@ -951,7 +981,6 @@ grpc_cc_library( "src/core/lib/iomgr/load_file.h", "src/core/lib/iomgr/lockfree_event.h", "src/core/lib/iomgr/nameser.h", - "src/core/lib/iomgr/parse_address.h", "src/core/lib/iomgr/polling_entity.h", "src/core/lib/iomgr/pollset.h", "src/core/lib/iomgr/pollset_custom.h", @@ -968,7 +997,6 @@ grpc_cc_library( "src/core/lib/iomgr/sockaddr.h", "src/core/lib/iomgr/sockaddr_custom.h", "src/core/lib/iomgr/sockaddr_posix.h", - "src/core/lib/iomgr/sockaddr_utils.h", "src/core/lib/iomgr/sockaddr_windows.h", "src/core/lib/iomgr/socket_factory_posix.h", "src/core/lib/iomgr/socket_mutator.h", @@ -1041,10 +1069,9 @@ grpc_cc_library( "absl/container:flat_hash_map", ], language = "c++", - public_hdrs = GRPC_PUBLIC_HDRS, + public_hdrs = GRPC_PUBLIC_HDRS + GRPC_PUBLIC_EVENT_ENGINE_HDRS, deps = [ "dual_ref_counted", - "eventmanager_libuv", "gpr_base", "grpc_codegen", "grpc_trace", @@ -1089,6 +1116,7 @@ grpc_cc_library( "grpc_transport_chttp2_client_insecure", "grpc_transport_chttp2_server_insecure", "grpc_transport_inproc", + "grpc_fault_injection_filter", "grpc_workaround_cronet_compression_filter", "grpc_server_backward_compatibility", ], @@ -1118,6 +1146,8 @@ grpc_cc_library( "src/core/ext/filters/client_channel/resolver.cc", "src/core/ext/filters/client_channel/resolver_registry.cc", "src/core/ext/filters/client_channel/resolver_result_parsing.cc", + "src/core/ext/filters/client_channel/retry_filter.cc", + "src/core/ext/filters/client_channel/retry_service_config.cc", "src/core/ext/filters/client_channel/retry_throttle.cc", "src/core/ext/filters/client_channel/server_address.cc", "src/core/ext/filters/client_channel/service_config.cc", @@ -1150,6 +1180,8 @@ grpc_cc_library( "src/core/ext/filters/client_channel/resolver_factory.h", "src/core/ext/filters/client_channel/resolver_registry.h", "src/core/ext/filters/client_channel/resolver_result_parsing.h", + "src/core/ext/filters/client_channel/retry_filter.h", + "src/core/ext/filters/client_channel/retry_service_config.h", "src/core/ext/filters/client_channel/retry_throttle.h", "src/core/ext/filters/client_channel/server_address.h", "src/core/ext/filters/client_channel/service_config.h", @@ -1244,6 +1276,23 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc_fault_injection_filter", + srcs = [ + "src/core/ext/filters/fault_injection/fault_injection_filter.cc", + "src/core/ext/filters/fault_injection/service_config_parser.cc", + ], + hdrs = [ + "src/core/ext/filters/fault_injection/fault_injection_filter.h", + "src/core/ext/filters/fault_injection/service_config_parser.h", + ], + language = "c++", + deps = [ + "grpc_base", + "grpc_client_channel", + ], +) + grpc_cc_library( name = "grpc_http_filters", srcs = [ @@ -1380,6 +1429,7 @@ grpc_cc_library( "src/core/ext/xds/xds_certificate_provider.cc", "src/core/ext/xds/xds_client.cc", "src/core/ext/xds/xds_client_stats.cc", + "src/core/ext/xds/xds_http_fault_filter.cc", "src/core/ext/xds/xds_http_filters.cc", "src/core/lib/security/credentials/xds/xds_credentials.cc", ], @@ -1394,6 +1444,7 @@ grpc_cc_library( "src/core/ext/xds/xds_channel_args.h", "src/core/ext/xds/xds_client.h", "src/core/ext/xds/xds_client_stats.h", + "src/core/ext/xds/xds_http_fault_filter.h", "src/core/ext/xds/xds_http_filters.h", "src/core/lib/security/credentials/xds/xds_credentials.h", ], @@ -1401,15 +1452,17 @@ grpc_cc_library( "absl/functional:bind_front", "upb_lib", "upb_textformat_lib", + "upb_json_lib", "re2", ], language = "c++", deps = [ "envoy_ads_upb", "envoy_ads_upbdefs", - "grpc_authorization_engine", "grpc_base", "grpc_client_channel", + "grpc_fault_injection_filter", + "grpc_matchers", "grpc_secure", "grpc_transport_chttp2_client_secure", "udpa_type_upb", @@ -1574,6 +1627,22 @@ grpc_cc_library( ], ) +grpc_cc_library( + name = "grpc_lb_policy_ring_hash", + srcs = [ + "src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc", + ], + hdrs = [ + "src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h", + ], + language = "c++", + deps = [ + "grpc_base", + "grpc_client_channel", + "grpc_lb_subchannel_list", + ], +) + grpc_cc_library( name = "grpc_lb_policy_round_robin", srcs = [ @@ -1826,10 +1895,14 @@ grpc_cc_library( srcs = [ "src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc", ], + external_deps = [ + "xxhash", + ], language = "c++", deps = [ "grpc_base", "grpc_client_channel", + "grpc_lb_policy_ring_hash", "grpc_xds_client", ], ) @@ -1969,21 +2042,75 @@ grpc_cc_library( ], ) +# This target depends on RE2 and should not be linked into grpc by default for binary-size reasons. grpc_cc_library( - name = "grpc_authorization_engine", + name = "grpc_matchers", + srcs = [ + "src/core/lib/matchers/matchers.cc", + ], + hdrs = [ + "src/core/lib/matchers/matchers.h", + ], + external_deps = [ + "re2", + ], + language = "c++", + deps = [ + "grpc_base", + ], +) + +# This target pulls in a dependency on RE2 and should not be linked into grpc by default for binary-size reasons. +grpc_cc_library( + name = "grpc_rbac_engine", srcs = [ - "src/core/lib/security/authorization/authorization_engine.cc", "src/core/lib/security/authorization/evaluate_args.cc", + "src/core/lib/security/authorization/grpc_authorization_engine.cc", "src/core/lib/security/authorization/matchers.cc", + "src/core/lib/security/authorization/rbac_policy.cc", ], hdrs = [ "src/core/lib/security/authorization/authorization_engine.h", "src/core/lib/security/authorization/evaluate_args.h", + "src/core/lib/security/authorization/grpc_authorization_engine.h", "src/core/lib/security/authorization/matchers.h", + "src/core/lib/security/authorization/rbac_policy.h", + ], + language = "c++", + deps = [ + "grpc_base", + "grpc_matchers", + "grpc_secure", + ], +) + +# This target pulls in a dependency on RE2 and should not be linked into grpc by default for binary-size reasons. +grpc_cc_library( + name = "grpc_authorization_provider", + srcs = [ + "src/core/lib/security/authorization/rbac_translator.cc", + ], + hdrs = [ + "src/core/lib/security/authorization/rbac_translator.h", + ], + language = "c++", + deps = [ + "grpc_matchers", + "grpc_rbac_engine", + ], +) + +# This target pulls in a dependency on RE2 and should not be linked into grpc by default for binary-size reasons. +grpc_cc_library( + name = "grpc_cel_engine", + srcs = [ + "src/core/lib/security/authorization/cel_authorization_engine.cc", + ], + hdrs = [ + "src/core/lib/security/authorization/cel_authorization_engine.h", ], external_deps = [ "absl/container:flat_hash_set", - "re2", ], language = "c++", deps = [ @@ -1991,7 +2118,7 @@ grpc_cc_library( "google_api_upb", "grpc_base", "grpc_mock_cel", - "grpc_secure", + "grpc_rbac_engine", ], ) @@ -2346,13 +2473,13 @@ grpc_cc_library( "include/grpc++/impl/codegen/async_stream.h", "include/grpc++/impl/codegen/async_unary_call.h", "include/grpc++/impl/codegen/byte_buffer.h", - "include/grpc++/impl/codegen/call.h", "include/grpc++/impl/codegen/call_hook.h", + "include/grpc++/impl/codegen/call.h", "include/grpc++/impl/codegen/channel_interface.h", "include/grpc++/impl/codegen/client_context.h", "include/grpc++/impl/codegen/client_unary_call.h", - "include/grpc++/impl/codegen/completion_queue.h", "include/grpc++/impl/codegen/completion_queue_tag.h", + "include/grpc++/impl/codegen/completion_queue.h", "include/grpc++/impl/codegen/config.h", "include/grpc++/impl/codegen/core_codegen_interface.h", "include/grpc++/impl/codegen/create_auth_context.h", @@ -2367,8 +2494,8 @@ grpc_cc_library( "include/grpc++/impl/codegen/server_interface.h", "include/grpc++/impl/codegen/service_type.h", "include/grpc++/impl/codegen/slice.h", - "include/grpc++/impl/codegen/status.h", "include/grpc++/impl/codegen/status_code_enum.h", + "include/grpc++/impl/codegen/status.h", "include/grpc++/impl/codegen/string_ref.h", "include/grpc++/impl/codegen/stub_options.h", "include/grpc++/impl/codegen/sync_stream.h", @@ -2377,42 +2504,43 @@ grpc_cc_library( "include/grpcpp/impl/codegen/async_stream.h", "include/grpcpp/impl/codegen/async_unary_call.h", "include/grpcpp/impl/codegen/byte_buffer.h", - "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/call_hook.h", - "include/grpcpp/impl/codegen/call_op_set.h", "include/grpcpp/impl/codegen/call_op_set_interface.h", + "include/grpcpp/impl/codegen/call_op_set.h", + "include/grpcpp/impl/codegen/call.h", "include/grpcpp/impl/codegen/callback_common.h", "include/grpcpp/impl/codegen/channel_interface.h", "include/grpcpp/impl/codegen/client_callback.h", "include/grpcpp/impl/codegen/client_context.h", "include/grpcpp/impl/codegen/client_interceptor.h", "include/grpcpp/impl/codegen/client_unary_call.h", - "include/grpcpp/impl/codegen/completion_queue.h", "include/grpcpp/impl/codegen/completion_queue_tag.h", + "include/grpcpp/impl/codegen/completion_queue.h", "include/grpcpp/impl/codegen/config.h", "include/grpcpp/impl/codegen/core_codegen_interface.h", "include/grpcpp/impl/codegen/create_auth_context.h", "include/grpcpp/impl/codegen/delegating_channel.h", "include/grpcpp/impl/codegen/grpc_library.h", "include/grpcpp/impl/codegen/intercepted_channel.h", - "include/grpcpp/impl/codegen/interceptor.h", "include/grpcpp/impl/codegen/interceptor_common.h", + "include/grpcpp/impl/codegen/interceptor.h", "include/grpcpp/impl/codegen/message_allocator.h", "include/grpcpp/impl/codegen/metadata_map.h", + "include/grpcpp/impl/codegen/method_handler_impl.h", "include/grpcpp/impl/codegen/method_handler.h", "include/grpcpp/impl/codegen/rpc_method.h", "include/grpcpp/impl/codegen/rpc_service_method.h", "include/grpcpp/impl/codegen/security/auth_context.h", "include/grpcpp/impl/codegen/serialization_traits.h", - "include/grpcpp/impl/codegen/server_callback.h", "include/grpcpp/impl/codegen/server_callback_handlers.h", + "include/grpcpp/impl/codegen/server_callback.h", "include/grpcpp/impl/codegen/server_context.h", "include/grpcpp/impl/codegen/server_interceptor.h", "include/grpcpp/impl/codegen/server_interface.h", "include/grpcpp/impl/codegen/service_type.h", "include/grpcpp/impl/codegen/slice.h", - "include/grpcpp/impl/codegen/status.h", "include/grpcpp/impl/codegen/status_code_enum.h", + "include/grpcpp/impl/codegen/status.h", "include/grpcpp/impl/codegen/string_ref.h", "include/grpcpp/impl/codegen/stub_options.h", "include/grpcpp/impl/codegen/sync_stream.h", @@ -2506,6 +2634,50 @@ grpc_cc_library( alwayslink = 1, ) +grpc_cc_library( + name = "grpcpp_csds", + srcs = [ + "src/cpp/server/csds/csds.cc", + ], + hdrs = [ + "src/cpp/server/csds/csds.h", + ], + language = "c++", + deps = [ + ":grpc++_internals", + "//src/proto/grpc/testing/xds/v3:csds_proto", + ], + alwayslink = 1, +) + +grpc_cc_library( + name = "grpcpp_admin", + srcs = [ + "src/cpp/server/admin/admin_services.cc", + ], + hdrs = [], + defines = select({ + "grpc_no_xds": ["GRPC_NO_XDS"], + "//conditions:default": [], + }), + external_deps = [ + "absl/memory", + ], + language = "c++", + public_hdrs = [ + "include/grpcpp/ext/admin_services.h", + ], + select_deps = { + "grpc_no_xds": [], + "//conditions:default": ["//:grpcpp_csds"], + }, + deps = [ + ":grpc++", + ":grpcpp_channelz", + ], + alwayslink = 1, +) + grpc_cc_library( name = "grpc++_test", srcs = [ @@ -2584,6 +2756,7 @@ grpc_cc_library( "absl-time", "opencensus-trace", "opencensus-trace-context_util", + "opencensus-trace-propagation", "opencensus-stats", "opencensus-context", ], @@ -2640,7 +2813,9 @@ grpc_cc_library( grpc_cc_library( name = "envoy_ads_upb", srcs = [ + "src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c", "src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c", + "src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c", "src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c", "src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c", "src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c", @@ -2652,12 +2827,16 @@ grpc_cc_library( "src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c", "src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c", "src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c", + "src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c", + "src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c", "src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c", "src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c", "src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c", "src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c", "src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c", "src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c", + "src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c", + "src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c", "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c", "src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c", "src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c", @@ -2672,9 +2851,12 @@ grpc_cc_library( "src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c", "src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c", "src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c", + "src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c", ], hdrs = [ + "src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h", "src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h", + "src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h", "src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h", "src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h", "src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.h", @@ -2686,12 +2868,16 @@ grpc_cc_library( "src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h", "src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h", "src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h", + "src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h", + "src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h", "src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h", "src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h", "src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h", "src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h", "src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h", "src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h", + "src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h", + "src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h", "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h", "src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h", "src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h", @@ -2706,6 +2892,7 @@ grpc_cc_library( "src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.h", "src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h", "src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h", + "src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h", ], external_deps = [ "upb_lib", @@ -2726,7 +2913,9 @@ grpc_cc_library( grpc_cc_library( name = "envoy_ads_upbdefs", srcs = [ + "src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c", @@ -2738,11 +2927,15 @@ grpc_cc_library( "src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c", @@ -2757,9 +2950,12 @@ grpc_cc_library( "src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c", ], hdrs = [ + "src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.h", @@ -2771,11 +2967,15 @@ grpc_cc_library( "src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h", @@ -2790,6 +2990,7 @@ grpc_cc_library( "src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h", ], external_deps = [ "upb_lib", @@ -2948,10 +3149,12 @@ grpc_cc_library( name = "envoy_type_upb", srcs = [ "src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c", + "src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c", + "src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c", "src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c", "src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c", @@ -2962,10 +3165,12 @@ grpc_cc_library( ], hdrs = [ "src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h", + "src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h", + "src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h", "src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.h", "src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.h", @@ -2991,10 +3196,12 @@ grpc_cc_library( name = "envoy_type_upbdefs", srcs = [ "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c", @@ -3005,10 +3212,12 @@ grpc_cc_library( ], hdrs = [ "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.h", @@ -3418,25 +3627,3 @@ filegroup( ], visibility = ["//visibility:public"], ) - -# Base classes of EventManagerInterface -grpc_cc_library( - name = "eventmanager_interface", - hdrs = [ - "src/core/lib/iomgr/poller/eventmanager_interface.h", - ], -) - -# Libuv-based EventManager implementation -grpc_cc_library( - name = "eventmanager_libuv", - srcs = [ - "src/core/lib/iomgr/poller/eventmanager_libuv.cc", - ], - hdrs = [ - "src/core/lib/iomgr/poller/eventmanager_libuv.h", - ], - deps = [ - "gpr_base", - ], -) diff --git a/BUILD.gn b/BUILD.gn index 89ab85273fd..2a2889d4811 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -97,6 +97,28 @@ config("grpc_config") { "include/grpc/support/sync_windows.h", "include/grpc/support/thd_id.h", "include/grpc/support/time.h", + "src/core/ext/upb-generated/google/api/annotations.upb.c", + "src/core/ext/upb-generated/google/api/annotations.upb.h", + "src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c", + "src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h", + "src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c", + "src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h", + "src/core/ext/upb-generated/google/api/http.upb.c", + "src/core/ext/upb-generated/google/api/http.upb.h", + "src/core/ext/upb-generated/google/protobuf/any.upb.c", + "src/core/ext/upb-generated/google/protobuf/any.upb.h", + "src/core/ext/upb-generated/google/protobuf/duration.upb.c", + "src/core/ext/upb-generated/google/protobuf/duration.upb.h", + "src/core/ext/upb-generated/google/protobuf/empty.upb.c", + "src/core/ext/upb-generated/google/protobuf/empty.upb.h", + "src/core/ext/upb-generated/google/protobuf/struct.upb.c", + "src/core/ext/upb-generated/google/protobuf/struct.upb.h", + "src/core/ext/upb-generated/google/protobuf/timestamp.upb.c", + "src/core/ext/upb-generated/google/protobuf/timestamp.upb.h", + "src/core/ext/upb-generated/google/protobuf/wrappers.upb.c", + "src/core/ext/upb-generated/google/protobuf/wrappers.upb.h", + "src/core/ext/upb-generated/google/rpc/status.upb.c", + "src/core/ext/upb-generated/google/rpc/status.upb.h", "src/core/lib/gpr/alloc.cc", "src/core/lib/gpr/alloc.h", "src/core/lib/gpr/arena.h", @@ -147,6 +169,7 @@ config("grpc_config") { "src/core/lib/gprpp/arena.cc", "src/core/lib/gprpp/arena.h", "src/core/lib/gprpp/atomic.h", + "src/core/lib/gprpp/debug_location.h", "src/core/lib/gprpp/examine_stack.cc", "src/core/lib/gprpp/examine_stack.h", "src/core/lib/gprpp/fork.cc", @@ -165,6 +188,8 @@ config("grpc_config") { "src/core/lib/gprpp/stat.h", "src/core/lib/gprpp/stat_posix.cc", "src/core/lib/gprpp/stat_windows.cc", + "src/core/lib/gprpp/status_helper.cc", + "src/core/lib/gprpp/status_helper.h", "src/core/lib/gprpp/sync.h", "src/core/lib/gprpp/thd.h", "src/core/lib/gprpp/thd_posix.cc", @@ -176,14 +201,15 @@ config("grpc_config") { "src/core/lib/profiling/timers.h", ] deps = [ - ":absl/types:optional", - ":absl/time:time", - ":absl/synchronization:synchronization", - ":absl/strings:strings", - ":absl/strings:str_format", - ":absl/status:status", - ":absl/memory:memory", ":absl/base:base", + ":absl/memory:memory", + ":absl/status:status", + ":absl/strings:str_format", + ":absl/strings:strings", + ":absl/synchronization:synchronization", + ":absl/time:time", + ":absl/types:optional", + ":upb", ] public_configs = [ @@ -199,6 +225,10 @@ config("grpc_config") { "include/grpc/byte_buffer_reader.h", "include/grpc/census.h", "include/grpc/compression.h", + "include/grpc/event_engine/channel_args.h", + "include/grpc/event_engine/event_engine.h", + "include/grpc/event_engine/port.h", + "include/grpc/event_engine/slice_allocator.h", "include/grpc/fork.h", "include/grpc/grpc.h", "include/grpc/grpc_posix.h", @@ -255,6 +285,8 @@ config("grpc_config") { "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", "src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc", "src/core/ext/filters/client_channel/lb_policy/priority/priority.cc", + "src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc", + "src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h", "src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc", "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h", "src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc", @@ -298,6 +330,10 @@ config("grpc_config") { "src/core/ext/filters/client_channel/resolver_registry.h", "src/core/ext/filters/client_channel/resolver_result_parsing.cc", "src/core/ext/filters/client_channel/resolver_result_parsing.h", + "src/core/ext/filters/client_channel/retry_filter.cc", + "src/core/ext/filters/client_channel/retry_filter.h", + "src/core/ext/filters/client_channel/retry_service_config.cc", + "src/core/ext/filters/client_channel/retry_service_config.h", "src/core/ext/filters/client_channel/retry_throttle.cc", "src/core/ext/filters/client_channel/retry_throttle.h", "src/core/ext/filters/client_channel/server_address.cc", @@ -316,6 +352,10 @@ config("grpc_config") { "src/core/ext/filters/client_idle/client_idle_filter.cc", "src/core/ext/filters/deadline/deadline_filter.cc", "src/core/ext/filters/deadline/deadline_filter.h", + "src/core/ext/filters/fault_injection/fault_injection_filter.cc", + "src/core/ext/filters/fault_injection/fault_injection_filter.h", + "src/core/ext/filters/fault_injection/service_config_parser.cc", + "src/core/ext/filters/fault_injection/service_config_parser.h", "src/core/ext/filters/http/client/http_client_filter.cc", "src/core/ext/filters/http/client/http_client_filter.h", "src/core/ext/filters/http/client_authority_filter.cc", @@ -396,12 +436,16 @@ config("grpc_config") { "src/core/ext/transport/inproc/inproc_plugin.cc", "src/core/ext/transport/inproc/inproc_transport.cc", "src/core/ext/transport/inproc/inproc_transport.h", + "src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c", + "src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h", "src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c", "src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h", "src/core/ext/upb-generated/envoy/annotations/resource.upb.c", "src/core/ext/upb-generated/envoy/annotations/resource.upb.h", "src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c", "src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h", + "src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c", + "src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h", "src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c", "src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h", "src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c", @@ -450,6 +494,10 @@ config("grpc_config") { "src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h", "src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c", "src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h", + "src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c", + "src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h", + "src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c", + "src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h", "src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c", "src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h", "src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c", @@ -462,6 +510,10 @@ config("grpc_config") { "src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h", "src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c", "src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h", + "src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c", + "src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h", + "src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c", + "src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h", "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c", "src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h", "src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c", @@ -490,8 +542,12 @@ config("grpc_config") { "src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h", "src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c", "src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h", + "src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c", + "src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h", + "src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c", + "src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c", @@ -500,6 +556,8 @@ config("grpc_config") { "src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h", + "src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c", + "src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h", "src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c", "src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h", "src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c", @@ -514,28 +572,6 @@ config("grpc_config") { "src/core/ext/upb-generated/envoy/type/v3/range.upb.h", "src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.c", "src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.h", - "src/core/ext/upb-generated/google/api/annotations.upb.c", - "src/core/ext/upb-generated/google/api/annotations.upb.h", - "src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c", - "src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h", - "src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c", - "src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h", - "src/core/ext/upb-generated/google/api/http.upb.c", - "src/core/ext/upb-generated/google/api/http.upb.h", - "src/core/ext/upb-generated/google/protobuf/any.upb.c", - "src/core/ext/upb-generated/google/protobuf/any.upb.h", - "src/core/ext/upb-generated/google/protobuf/duration.upb.c", - "src/core/ext/upb-generated/google/protobuf/duration.upb.h", - "src/core/ext/upb-generated/google/protobuf/empty.upb.c", - "src/core/ext/upb-generated/google/protobuf/empty.upb.h", - "src/core/ext/upb-generated/google/protobuf/struct.upb.c", - "src/core/ext/upb-generated/google/protobuf/struct.upb.h", - "src/core/ext/upb-generated/google/protobuf/timestamp.upb.c", - "src/core/ext/upb-generated/google/protobuf/timestamp.upb.h", - "src/core/ext/upb-generated/google/protobuf/wrappers.upb.c", - "src/core/ext/upb-generated/google/protobuf/wrappers.upb.h", - "src/core/ext/upb-generated/google/rpc/status.upb.c", - "src/core/ext/upb-generated/google/rpc/status.upb.h", "src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c", "src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h", "src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c", @@ -574,12 +610,16 @@ config("grpc_config") { "src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h", "src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c", "src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h", + "src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c", @@ -628,6 +668,10 @@ config("grpc_config") { "src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c", @@ -638,6 +682,10 @@ config("grpc_config") { "src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c", @@ -666,8 +714,12 @@ config("grpc_config") { "src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c", @@ -676,6 +728,8 @@ config("grpc_config") { "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c", + "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c", "src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h", "src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c", @@ -752,9 +806,15 @@ config("grpc_config") { "src/core/ext/xds/xds_client.h", "src/core/ext/xds/xds_client_stats.cc", "src/core/ext/xds/xds_client_stats.h", + "src/core/ext/xds/xds_http_fault_filter.cc", + "src/core/ext/xds/xds_http_fault_filter.h", "src/core/ext/xds/xds_http_filters.cc", "src/core/ext/xds/xds_http_filters.h", "src/core/ext/xds/xds_server_config_fetcher.cc", + "src/core/lib/address_utils/parse_address.cc", + "src/core/lib/address_utils/parse_address.h", + "src/core/lib/address_utils/sockaddr_utils.cc", + "src/core/lib/address_utils/sockaddr_utils.h", "src/core/lib/avl/avl.cc", "src/core/lib/avl/avl.h", "src/core/lib/backoff/backoff.cc", @@ -801,8 +861,9 @@ config("grpc_config") { "src/core/lib/debug/stats_data.h", "src/core/lib/debug/trace.cc", "src/core/lib/debug/trace.h", + "src/core/lib/event_engine/slice_allocator.cc", + "src/core/lib/event_engine/sockaddr.cc", "src/core/lib/gprpp/atomic.h", - "src/core/lib/gprpp/debug_location.h", "src/core/lib/gprpp/dual_ref_counted.h", "src/core/lib/gprpp/orphanable.h", "src/core/lib/gprpp/ref_counted.h", @@ -888,10 +949,6 @@ config("grpc_config") { "src/core/lib/iomgr/lockfree_event.cc", "src/core/lib/iomgr/lockfree_event.h", "src/core/lib/iomgr/nameser.h", - "src/core/lib/iomgr/parse_address.cc", - "src/core/lib/iomgr/parse_address.h", - "src/core/lib/iomgr/poller/eventmanager_libuv.cc", - "src/core/lib/iomgr/poller/eventmanager_libuv.h", "src/core/lib/iomgr/polling_entity.cc", "src/core/lib/iomgr/polling_entity.h", "src/core/lib/iomgr/pollset.cc", @@ -921,8 +978,6 @@ config("grpc_config") { "src/core/lib/iomgr/sockaddr.h", "src/core/lib/iomgr/sockaddr_custom.h", "src/core/lib/iomgr/sockaddr_posix.h", - "src/core/lib/iomgr/sockaddr_utils.cc", - "src/core/lib/iomgr/sockaddr_utils.h", "src/core/lib/iomgr/sockaddr_windows.h", "src/core/lib/iomgr/socket_factory_posix.cc", "src/core/lib/iomgr/socket_factory_posix.h", @@ -992,18 +1047,8 @@ config("grpc_config") { "src/core/lib/json/json_util.cc", "src/core/lib/json/json_util.h", "src/core/lib/json/json_writer.cc", - "src/core/lib/security/authorization/authorization_engine.cc", - "src/core/lib/security/authorization/authorization_engine.h", - "src/core/lib/security/authorization/evaluate_args.cc", - "src/core/lib/security/authorization/evaluate_args.h", - "src/core/lib/security/authorization/matchers.cc", - "src/core/lib/security/authorization/matchers.h", - "src/core/lib/security/authorization/mock_cel/activation.h", - "src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h", - "src/core/lib/security/authorization/mock_cel/cel_expression.h", - "src/core/lib/security/authorization/mock_cel/cel_value.h", - "src/core/lib/security/authorization/mock_cel/evaluator_core.h", - "src/core/lib/security/authorization/mock_cel/flat_expr_builder.h", + "src/core/lib/matchers/matchers.cc", + "src/core/lib/matchers/matchers.h", "src/core/lib/security/context/security_context.cc", "src/core/lib/security/context/security_context.h", "src/core/lib/security/credentials/alts/alts_credentials.cc", @@ -1229,21 +1274,17 @@ config("grpc_config") { "src/core/tsi/transport_security_grpc.cc", "src/core/tsi/transport_security_grpc.h", "src/core/tsi/transport_security_interface.h", + "third_party/xxhash/xxhash.h", ] deps = [ - "//third_party/boringssl", "//third_party/zlib", + ":absl/container:flat_hash_map", + ":absl/container:inlined_vector", + ":absl/functional:bind_front", + ":absl/status:statusor", ":gpr", + "//third_party/boringssl", ":address_sorting", - ":upb", - ":absl/types:optional", - ":absl/strings:strings", - ":absl/status:statusor", - ":absl/status:status", - ":absl/functional:bind_front", - ":absl/container:inlined_vector", - ":absl/container:flat_hash_set", - ":absl/container:flat_hash_map", "//third_party/cares", ":address_sorting", ] @@ -1381,6 +1422,7 @@ config("grpc_config") { "include/grpcpp/impl/codegen/message_allocator.h", "include/grpcpp/impl/codegen/metadata_map.h", "include/grpcpp/impl/codegen/method_handler.h", + "include/grpcpp/impl/codegen/method_handler_impl.h", "include/grpcpp/impl/codegen/proto_buffer_reader.h", "include/grpcpp/impl/codegen/proto_buffer_writer.h", "include/grpcpp/impl/codegen/proto_utils.h", @@ -1510,10 +1552,6 @@ config("grpc_config") { deps = [ "//third_party/protobuf:protobuf_lite", ":grpc", - ":gpr", - ":address_sorting", - ":upb", - ":absl/synchronization:synchronization", ] public_configs = [ diff --git a/BUILDING.md b/BUILDING.md index 674d5ed0e8c..4a69c3b779f 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -245,6 +245,12 @@ $ make [Cross-compile example](test/distrib/cpp/run_distrib_test_cmake_aarch64_cross.sh) +### A note on SONAME and its ABI compatibility implications in the cmake build + +Best efforts are made to bump the SONAME revision during ABI breaches. While a +change in the SONAME clearly indicates an ABI incompatibility, no hard guarantees +can be made about any sort of ABI stability across the same SONAME version. + ## Building with make on UNIX systems (deprecated) NOTE: `make` used to be gRPC's default build system, but we're no longer recommending it. You should use `bazel` or `cmake` instead. The `Makefile` is only intended for internal usage and is not meant for public consumption. diff --git a/CMakeLists.txt b/CMakeLists.txt index f9e2dea1bbe..d312ec8edce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,13 +25,13 @@ cmake_minimum_required(VERSION 3.5.1) set(PACKAGE_NAME "grpc") -set(PACKAGE_VERSION "1.37.0-dev") -set(gRPC_CORE_VERSION "15.0.0") -set(gRPC_CORE_SOVERSION "15") -set(gRPC_CPP_VERSION "1.37.0-dev") -set(gRPC_CPP_SOVERSION "1") -set(gRPC_CSHARP_VERSION "2.37.0-dev") -set(gRPC_CSHARP_SOVERSION "2") +set(PACKAGE_VERSION "1.38.0-dev") +set(gRPC_CORE_VERSION "16.0.0") +set(gRPC_CORE_SOVERSION "16") +set(gRPC_CPP_VERSION "1.38.0-dev") +set(gRPC_CPP_SOVERSION "1.38") +set(gRPC_CSHARP_VERSION "2.38.0-dev") +set(gRPC_CSHARP_SOVERSION "2.38") set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") @@ -123,7 +123,6 @@ set(gRPC_ABSL_USED_TARGETS absl_exponential_biased absl_fixed_array absl_flat_hash_map - absl_flat_hash_set absl_function_ref absl_graphcycles_internal absl_hash @@ -140,6 +139,7 @@ set(gRPC_ABSL_USED_TARGETS absl_log_severity absl_malloc_internal absl_memory + absl_numeric_representation absl_optional absl_raw_hash_map absl_raw_hash_set @@ -161,6 +161,7 @@ set(gRPC_ABSL_USED_TARGETS absl_type_traits absl_utility absl_variant + absl_wyhash absl_meta ) @@ -255,6 +256,7 @@ include(cmake/protobuf.cmake) include(cmake/re2.cmake) include(cmake/ssl.cmake) include(cmake/upb.cmake) +include(cmake/xxhash.cmake) include(cmake/zlib.cmake) if(_gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_IOS) @@ -466,15 +468,27 @@ protobuf_generate_grpc_cpp( protobuf_generate_grpc_cpp( src/proto/grpc/testing/xds/v3/cluster.proto ) +protobuf_generate_grpc_cpp( + src/proto/grpc/testing/xds/v3/config_dump.proto +) protobuf_generate_grpc_cpp( src/proto/grpc/testing/xds/v3/config_source.proto ) +protobuf_generate_grpc_cpp( + src/proto/grpc/testing/xds/v3/csds.proto +) protobuf_generate_grpc_cpp( src/proto/grpc/testing/xds/v3/discovery.proto ) protobuf_generate_grpc_cpp( src/proto/grpc/testing/xds/v3/endpoint.proto ) +protobuf_generate_grpc_cpp( + src/proto/grpc/testing/xds/v3/fault.proto +) +protobuf_generate_grpc_cpp( + src/proto/grpc/testing/xds/v3/fault_common.proto +) protobuf_generate_grpc_cpp( src/proto/grpc/testing/xds/v3/http_connection_manager.proto ) @@ -665,7 +679,6 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_c slice_buffer_test) add_dependencies(buildtests_c slice_string_helpers_test) add_dependencies(buildtests_c sockaddr_resolver_test) - add_dependencies(buildtests_c sockaddr_utils_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_c socket_utils_test) endif() @@ -714,6 +727,7 @@ if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx address_sorting_test_unsecure) endif() + add_dependencies(buildtests_cxx admin_services_end2end_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx alarm_test) endif() @@ -723,7 +737,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx alts_util_test) add_dependencies(buildtests_cxx async_end2end_test) add_dependencies(buildtests_cxx auth_property_iterator_test) - add_dependencies(buildtests_cxx authorization_engine_test) + add_dependencies(buildtests_cxx authorization_matchers_test) add_dependencies(buildtests_cxx aws_request_signer_test) add_dependencies(buildtests_cxx backoff_test) add_dependencies(buildtests_cxx bad_streaming_id_bad_client_test) @@ -797,6 +811,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx byte_buffer_test) add_dependencies(buildtests_cxx byte_stream_test) add_dependencies(buildtests_cxx cancel_ares_query_test) + add_dependencies(buildtests_cxx cel_authorization_engine_test) add_dependencies(buildtests_cxx certificate_provider_registry_test) add_dependencies(buildtests_cxx certificate_provider_store_test) add_dependencies(buildtests_cxx cfstream_test) @@ -828,8 +843,8 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx duplicate_header_bad_client_test) add_dependencies(buildtests_cxx end2end_test) add_dependencies(buildtests_cxx error_details_test) + add_dependencies(buildtests_cxx error_utils_test) add_dependencies(buildtests_cxx evaluate_args_test) - add_dependencies(buildtests_cxx eventmanager_libuv_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx examine_stack_test) endif() @@ -843,6 +858,7 @@ if(gRPC_BUILD_TESTS) endif() add_dependencies(buildtests_cxx global_config_test) add_dependencies(buildtests_cxx google_mesh_ca_certificate_provider_factory_test) + add_dependencies(buildtests_cxx grpc_authorization_engine_test) add_dependencies(buildtests_cxx grpc_cli) add_dependencies(buildtests_cxx grpc_tls_certificate_distributor_test) add_dependencies(buildtests_cxx grpc_tls_certificate_provider_test) @@ -876,6 +892,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx log_test) add_dependencies(buildtests_cxx matchers_test) add_dependencies(buildtests_cxx message_allocator_end2end_test) + add_dependencies(buildtests_cxx mock_stream_test) add_dependencies(buildtests_cxx mock_test) add_dependencies(buildtests_cxx nonblocking_test) add_dependencies(buildtests_cxx noop-benchmark) @@ -888,6 +905,7 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx qps_json_driver) add_dependencies(buildtests_cxx qps_worker) add_dependencies(buildtests_cxx raw_end2end_test) + add_dependencies(buildtests_cxx rbac_translator_test) add_dependencies(buildtests_cxx ref_counted_ptr_test) add_dependencies(buildtests_cxx ref_counted_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -916,12 +934,14 @@ if(gRPC_BUILD_TESTS) add_dependencies(buildtests_cxx settings_timeout_test) add_dependencies(buildtests_cxx shutdown_test) add_dependencies(buildtests_cxx simple_request_bad_client_test) + add_dependencies(buildtests_cxx sockaddr_utils_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_dependencies(buildtests_cxx stack_tracer_test) endif() add_dependencies(buildtests_cxx stat_test) add_dependencies(buildtests_cxx static_metadata_test) add_dependencies(buildtests_cxx stats_test) + add_dependencies(buildtests_cxx status_helper_test) add_dependencies(buildtests_cxx status_metadata_test) add_dependencies(buildtests_cxx status_util_test) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -1015,6 +1035,7 @@ target_include_directories(address_sorting ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(address_sorting @@ -1093,10 +1114,12 @@ add_library(end2end_nosec_tests test/core/end2end/tests/request_with_payload.cc test/core/end2end/tests/resource_quota_server.cc test/core/end2end/tests/retry.cc + test/core/end2end/tests/retry_cancel_during_delay.cc test/core/end2end/tests/retry_cancellation.cc test/core/end2end/tests/retry_disabled.cc test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc + test/core/end2end/tests/retry_lb_drop.cc test/core/end2end/tests/retry_non_retriable_status.cc test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc test/core/end2end/tests/retry_recv_initial_metadata.cc @@ -1124,6 +1147,7 @@ add_library(end2end_nosec_tests test/core/end2end/tests/workaround_cronet_compression.cc test/core/end2end/tests/write_buffering.cc test/core/end2end/tests/write_buffering_at_end.cc + test/core/util/test_lb_policies.cc ) set_target_properties(end2end_nosec_tests PROPERTIES @@ -1152,15 +1176,12 @@ target_include_directories(end2end_nosec_tests ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(end2end_nosec_tests ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -1227,10 +1248,12 @@ add_library(end2end_tests test/core/end2end/tests/request_with_payload.cc test/core/end2end/tests/resource_quota_server.cc test/core/end2end/tests/retry.cc + test/core/end2end/tests/retry_cancel_during_delay.cc test/core/end2end/tests/retry_cancellation.cc test/core/end2end/tests/retry_disabled.cc test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc + test/core/end2end/tests/retry_lb_drop.cc test/core/end2end/tests/retry_non_retriable_status.cc test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc test/core/end2end/tests/retry_recv_initial_metadata.cc @@ -1258,6 +1281,7 @@ add_library(end2end_tests test/core/end2end/tests/workaround_cronet_compression.cc test/core/end2end/tests/write_buffering.cc test/core/end2end/tests/write_buffering_at_end.cc + test/core/util/test_lb_policies.cc ) set_target_properties(end2end_tests PROPERTIES @@ -1286,22 +1310,29 @@ target_include_directories(end2end_tests ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(end2end_tests - ${_gRPC_SSL_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) endif() add_library(gpr + src/core/ext/upb-generated/google/api/annotations.upb.c + src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c + src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c + src/core/ext/upb-generated/google/api/http.upb.c + src/core/ext/upb-generated/google/protobuf/any.upb.c + src/core/ext/upb-generated/google/protobuf/duration.upb.c + src/core/ext/upb-generated/google/protobuf/empty.upb.c + src/core/ext/upb-generated/google/protobuf/struct.upb.c + src/core/ext/upb-generated/google/protobuf/timestamp.upb.c + src/core/ext/upb-generated/google/protobuf/wrappers.upb.c + src/core/ext/upb-generated/google/rpc/status.upb.c src/core/lib/gpr/alloc.cc src/core/lib/gpr/atm.cc src/core/lib/gpr/cpu_iphone.cc @@ -1342,6 +1373,7 @@ add_library(gpr src/core/lib/gprpp/mpscq.cc src/core/lib/gprpp/stat_posix.cc src/core/lib/gprpp/stat_windows.cc + src/core/lib/gprpp/status_helper.cc src/core/lib/gprpp/thd_posix.cc src/core/lib/gprpp/thd_windows.cc src/core/lib/gprpp/time_util.cc @@ -1375,18 +1407,20 @@ target_include_directories(gpr ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(gpr ${_gRPC_ALLTARGETS_LIBRARIES} - absl::optional - absl::time - absl::synchronization - absl::strings - absl::str_format - absl::status - absl::memory absl::base + absl::memory + absl::status + absl::str_format + absl::strings + absl::synchronization + absl::time + absl::optional + upb ) if(_gRPC_PLATFORM_ANDROID) target_link_libraries(gpr @@ -1481,6 +1515,7 @@ add_library(grpc src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc src/core/ext/filters/client_channel/lb_policy/priority/priority.cc + src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc src/core/ext/filters/client_channel/lb_policy/xds/cds.cc @@ -1507,6 +1542,8 @@ add_library(grpc src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc src/core/ext/filters/client_channel/resolver_registry.cc src/core/ext/filters/client_channel/resolver_result_parsing.cc + src/core/ext/filters/client_channel/retry_filter.cc + src/core/ext/filters/client_channel/retry_service_config.cc src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/service_config.cc @@ -1516,6 +1553,8 @@ add_library(grpc src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_idle/client_idle_filter.cc src/core/ext/filters/deadline/deadline_filter.cc + src/core/ext/filters/fault_injection/fault_injection_filter.cc + src/core/ext/filters/fault_injection/service_config_parser.cc src/core/ext/filters/http/client/http_client_filter.cc src/core/ext/filters/http/client_authority_filter.cc src/core/ext/filters/http/http_filters_plugin.cc @@ -1561,9 +1600,11 @@ add_library(grpc src/core/ext/transport/chttp2/transport/writing.cc src/core/ext/transport/inproc/inproc_plugin.cc src/core/ext/transport/inproc/inproc_transport.cc + src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c src/core/ext/upb-generated/envoy/annotations/resource.upb.c src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c + src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c @@ -1588,12 +1629,16 @@ add_library(grpc src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c + src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c + src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c + src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c + src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c @@ -1608,11 +1653,14 @@ add_library(grpc src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c + src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c + src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c + src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c @@ -1620,17 +1668,6 @@ add_library(grpc src/core/ext/upb-generated/envoy/type/v3/percent.upb.c src/core/ext/upb-generated/envoy/type/v3/range.upb.c src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.c - src/core/ext/upb-generated/google/api/annotations.upb.c - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c - src/core/ext/upb-generated/google/api/http.upb.c - src/core/ext/upb-generated/google/protobuf/any.upb.c - src/core/ext/upb-generated/google/protobuf/duration.upb.c - src/core/ext/upb-generated/google/protobuf/empty.upb.c - src/core/ext/upb-generated/google/protobuf/struct.upb.c - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c - src/core/ext/upb-generated/google/rpc/status.upb.c src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c @@ -1650,9 +1687,11 @@ add_library(grpc src/core/ext/upb-generated/xds/core/v3/resource.upb.c src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c + src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c + src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c @@ -1677,11 +1716,15 @@ add_library(grpc src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c + src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c + src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c + src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c + src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c @@ -1696,11 +1739,14 @@ add_library(grpc src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c + src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c + src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c + src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c @@ -1738,8 +1784,11 @@ add_library(grpc src/core/ext/xds/xds_certificate_provider.cc src/core/ext/xds/xds_client.cc src/core/ext/xds/xds_client_stats.cc + src/core/ext/xds/xds_http_fault_filter.cc src/core/ext/xds/xds_http_filters.cc src/core/ext/xds/xds_server_config_fetcher.cc + src/core/lib/address_utils/parse_address.cc + src/core/lib/address_utils/sockaddr_utils.cc src/core/lib/avl/avl.cc src/core/lib/backoff/backoff.cc src/core/lib/channel/channel_args.cc @@ -1762,6 +1811,8 @@ add_library(grpc src/core/lib/debug/stats.cc src/core/lib/debug/stats_data.cc src/core/lib/debug/trace.cc + src/core/lib/event_engine/slice_allocator.cc + src/core/lib/event_engine/sockaddr.cc src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/httpcli_security_connector.cc @@ -1807,8 +1858,6 @@ add_library(grpc src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/parse_address.cc - src/core/lib/iomgr/poller/eventmanager_libuv.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -1822,7 +1871,6 @@ add_library(grpc src/core/lib/iomgr/resolve_address_posix.cc src/core/lib/iomgr/resolve_address_windows.cc src/core/lib/iomgr/resource_quota.cc - src/core/lib/iomgr/sockaddr_utils.cc src/core/lib/iomgr/socket_factory_posix.cc src/core/lib/iomgr/socket_mutator.cc src/core/lib/iomgr/socket_utils_common_posix.cc @@ -1865,9 +1913,7 @@ add_library(grpc src/core/lib/json/json_reader.cc src/core/lib/json/json_util.cc src/core/lib/json/json_writer.cc - src/core/lib/security/authorization/authorization_engine.cc - src/core/lib/security/authorization/evaluate_args.cc - src/core/lib/security/authorization/matchers.cc + src/core/lib/matchers/matchers.cc src/core/lib/security/context/security_context.cc src/core/lib/security/credentials/alts/alts_credentials.cc src/core/lib/security/credentials/alts/check_gcp_environment.cc @@ -2017,28 +2063,24 @@ target_include_directories(grpc ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc ${_gRPC_BASELIB_LIBRARIES} - ${_gRPC_SSL_LIBRARIES} ${_gRPC_ZLIB_LIBRARIES} ${_gRPC_CARES_LIBRARIES} ${_gRPC_ADDRESS_SORTING_LIBRARIES} ${_gRPC_RE2_LIBRARIES} ${_gRPC_UPB_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flat_hash_map + absl::inlined_vector + absl::bind_front + absl::statusor gpr + ${_gRPC_SSL_LIBRARIES} address_sorting - upb - absl::optional - absl::strings - absl::statusor - absl::status - absl::bind_front - absl::inlined_vector - absl::flat_hash_set - absl::flat_hash_map ) if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC) target_link_libraries(grpc "-framework CoreFoundation") @@ -2049,6 +2091,10 @@ foreach(_hdr include/grpc/byte_buffer_reader.h include/grpc/census.h include/grpc/compression.h + include/grpc/event_engine/channel_args.h + include/grpc/event_engine/event_engine.h + include/grpc/event_engine/port.h + include/grpc/event_engine/slice_allocator.h include/grpc/fork.h include/grpc/grpc.h include/grpc/grpc_posix.h @@ -2108,14 +2154,12 @@ target_include_directories(grpc_csharp_ext ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_csharp_ext ${_gRPC_ALLTARGETS_LIBRARIES} grpc - gpr - address_sorting - upb ) @@ -2124,7 +2168,6 @@ if(gRPC_BUILD_TESTS) add_library(grpc_test_util test/core/util/cmdline.cc - test/core/util/eval_args_mock_endpoint.cc test/core/util/fuzzer_util.cc test/core/util/grpc_profiler.cc test/core/util/histogram.cc @@ -2174,17 +2217,15 @@ target_include_directories(grpc_test_util ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_test_util ${_gRPC_ALLTARGETS_LIBRARIES} - grpc - gpr - address_sorting - upb - absl::symbolize - absl::stacktrace absl::failure_signal_handler + absl::stacktrace + absl::symbolize + grpc ) if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC) target_link_libraries(grpc_test_util "-framework CoreFoundation") @@ -2196,7 +2237,6 @@ if(gRPC_BUILD_TESTS) add_library(grpc_test_util_unsecure test/core/util/cmdline.cc - test/core/util/eval_args_mock_endpoint.cc test/core/util/fuzzer_util.cc test/core/util/grpc_profiler.cc test/core/util/histogram.cc @@ -2245,17 +2285,15 @@ target_include_directories(grpc_test_util_unsecure ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_test_util_unsecure ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_unsecure - gpr - address_sorting - upb - absl::symbolize - absl::stacktrace absl::failure_signal_handler + absl::stacktrace + absl::symbolize + grpc_unsecure ) if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC) target_link_libraries(grpc_test_util_unsecure "-framework CoreFoundation") @@ -2310,6 +2348,8 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc src/core/ext/filters/client_channel/resolver_registry.cc src/core/ext/filters/client_channel/resolver_result_parsing.cc + src/core/ext/filters/client_channel/retry_filter.cc + src/core/ext/filters/client_channel/retry_service_config.cc src/core/ext/filters/client_channel/retry_throttle.cc src/core/ext/filters/client_channel/server_address.cc src/core/ext/filters/client_channel/service_config.cc @@ -2319,6 +2359,8 @@ add_library(grpc_unsecure src/core/ext/filters/client_channel/subchannel_pool_interface.cc src/core/ext/filters/client_idle/client_idle_filter.cc src/core/ext/filters/deadline/deadline_filter.cc + src/core/ext/filters/fault_injection/fault_injection_filter.cc + src/core/ext/filters/fault_injection/service_config_parser.cc src/core/ext/filters/http/client/http_client_filter.cc src/core/ext/filters/http/client_authority_filter.cc src/core/ext/filters/http/http_filters_plugin.cc @@ -2362,21 +2404,12 @@ add_library(grpc_unsecure src/core/ext/transport/chttp2/transport/writing.cc src/core/ext/transport/inproc/inproc_plugin.cc src/core/ext/transport/inproc/inproc_transport.cc - src/core/ext/upb-generated/google/api/annotations.upb.c - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c - src/core/ext/upb-generated/google/api/http.upb.c - src/core/ext/upb-generated/google/protobuf/any.upb.c - src/core/ext/upb-generated/google/protobuf/duration.upb.c - src/core/ext/upb-generated/google/protobuf/empty.upb.c - src/core/ext/upb-generated/google/protobuf/struct.upb.c - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c - src/core/ext/upb-generated/google/rpc/status.upb.c src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c src/core/ext/upb-generated/validate/validate.upb.c + src/core/lib/address_utils/parse_address.cc + src/core/lib/address_utils/sockaddr_utils.cc src/core/lib/avl/avl.cc src/core/lib/backoff/backoff.cc src/core/lib/channel/channel_args.cc @@ -2399,6 +2432,8 @@ add_library(grpc_unsecure src/core/lib/debug/stats.cc src/core/lib/debug/stats_data.cc src/core/lib/debug/trace.cc + src/core/lib/event_engine/slice_allocator.cc + src/core/lib/event_engine/sockaddr.cc src/core/lib/http/format_request.cc src/core/lib/http/httpcli.cc src/core/lib/http/parser.cc @@ -2443,8 +2478,6 @@ add_library(grpc_unsecure src/core/lib/iomgr/is_epollexclusive_available.cc src/core/lib/iomgr/load_file.cc src/core/lib/iomgr/lockfree_event.cc - src/core/lib/iomgr/parse_address.cc - src/core/lib/iomgr/poller/eventmanager_libuv.cc src/core/lib/iomgr/polling_entity.cc src/core/lib/iomgr/pollset.cc src/core/lib/iomgr/pollset_custom.cc @@ -2458,7 +2491,6 @@ add_library(grpc_unsecure src/core/lib/iomgr/resolve_address_posix.cc src/core/lib/iomgr/resolve_address_windows.cc src/core/lib/iomgr/resource_quota.cc - src/core/lib/iomgr/sockaddr_utils.cc src/core/lib/iomgr/socket_factory_posix.cc src/core/lib/iomgr/socket_mutator.cc src/core/lib/iomgr/socket_utils_common_posix.cc @@ -2571,6 +2603,7 @@ target_include_directories(grpc_unsecure ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_unsecure @@ -2581,15 +2614,11 @@ target_link_libraries(grpc_unsecure ${_gRPC_RE2_LIBRARIES} ${_gRPC_UPB_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flat_hash_map + absl::inlined_vector + absl::statusor gpr address_sorting - upb - absl::optional - absl::strings - absl::statusor - absl::status - absl::inlined_vector - absl::flat_hash_map ) if(_gRPC_PLATFORM_IOS OR _gRPC_PLATFORM_MAC) target_link_libraries(grpc_unsecure "-framework CoreFoundation") @@ -2600,6 +2629,10 @@ foreach(_hdr include/grpc/byte_buffer_reader.h include/grpc/census.h include/grpc/compression.h + include/grpc/event_engine/channel_args.h + include/grpc/event_engine/event_engine.h + include/grpc/event_engine/port.h + include/grpc/event_engine/slice_allocator.h include/grpc/fork.h include/grpc/grpc.h include/grpc/grpc_posix.h @@ -2672,6 +2705,7 @@ target_include_directories(benchmark_helpers ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -2682,14 +2716,10 @@ target_include_directories(benchmark_helpers target_link_libraries(benchmark_helpers ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util_unsecure + ${_gRPC_BENCHMARK_LIBRARIES} grpc++_unsecure - grpc_unsecure + grpc_test_util_unsecure grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) endif() @@ -2775,6 +2805,7 @@ target_include_directories(grpc++ ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -2783,10 +2814,6 @@ target_link_libraries(grpc++ ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc - gpr - address_sorting - upb - absl::synchronization ) foreach(_hdr @@ -2910,6 +2937,7 @@ foreach(_hdr include/grpcpp/impl/codegen/message_allocator.h include/grpcpp/impl/codegen/metadata_map.h include/grpcpp/impl/codegen/method_handler.h + include/grpcpp/impl/codegen/method_handler_impl.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h include/grpcpp/impl/codegen/proto_utils.h @@ -3023,6 +3051,7 @@ target_include_directories(grpc++_alts ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3031,10 +3060,6 @@ target_link_libraries(grpc++_alts ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ - grpc - gpr - address_sorting - upb ) foreach(_hdr @@ -3088,6 +3113,7 @@ target_include_directories(grpc++_error_details ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3095,10 +3121,6 @@ target_link_libraries(grpc++_error_details ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ - grpc - gpr - address_sorting - upb ) foreach(_hdr @@ -3158,6 +3180,7 @@ target_include_directories(grpc++_reflection ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3165,10 +3188,6 @@ target_link_libraries(grpc++_reflection ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ - grpc - gpr - address_sorting - upb ) foreach(_hdr @@ -3226,6 +3245,7 @@ target_include_directories(grpc++_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -3237,10 +3257,6 @@ target_link_libraries(grpc++_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ - grpc - gpr - address_sorting - upb ) foreach(_hdr @@ -3292,6 +3308,7 @@ target_include_directories(grpc++_test_config ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -3302,8 +3319,8 @@ target_include_directories(grpc++_test_config target_link_libraries(grpc++_test_config ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - gpr absl::flags_parse + gpr ) @@ -3348,6 +3365,7 @@ target_include_directories(grpc++_test_util ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -3358,13 +3376,9 @@ target_include_directories(grpc++_test_util target_link_libraries(grpc++_test_util ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb absl::flags + grpc++ + grpc_test_util ) @@ -3439,6 +3453,7 @@ target_include_directories(grpc++_unsecure ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3447,10 +3462,6 @@ target_link_libraries(grpc++_unsecure ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_unsecure - gpr - address_sorting - upb - absl::synchronization ) foreach(_hdr @@ -3574,6 +3585,7 @@ foreach(_hdr include/grpcpp/impl/codegen/message_allocator.h include/grpcpp/impl/codegen/metadata_map.h include/grpcpp/impl/codegen/method_handler.h + include/grpcpp/impl/codegen/method_handler_impl.h include/grpcpp/impl/codegen/proto_buffer_reader.h include/grpcpp/impl/codegen/proto_buffer_writer.h include/grpcpp/impl/codegen/proto_utils.h @@ -3691,6 +3703,7 @@ target_include_directories(grpc_plugin_support ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3759,6 +3772,7 @@ target_include_directories(grpcpp_channelz ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3766,10 +3780,6 @@ target_link_libraries(grpcpp_channelz ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++ - grpc - gpr - address_sorting - upb ) foreach(_hdr @@ -3785,7 +3795,9 @@ endif() if(gRPC_BUILD_CODEGEN) -if(gRPC_INSTALL) +# grpcpp_channelz doesn't build with protobuf-lite, so no install required +# See https://github.com/grpc/grpc/issues/22826 +if(gRPC_INSTALL AND NOT gRPC_USE_PROTO_LITE) install(TARGETS grpcpp_channelz EXPORT gRPCTargets RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR} LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR} @@ -3800,8 +3812,6 @@ add_library(upb third_party/upb/upb/decode.c third_party/upb/upb/def.c third_party/upb/upb/encode.c - third_party/upb/upb/json_decode.c - third_party/upb/upb/json_encode.c third_party/upb/upb/msg.c third_party/upb/upb/reflection.c third_party/upb/upb/table.c @@ -3837,6 +3847,7 @@ target_include_directories(upb ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(upb @@ -3869,6 +3880,7 @@ target_include_directories(check_epollexclusive ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) @@ -3894,6 +3906,7 @@ target_include_directories(gen_hpack_tables ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3921,6 +3934,7 @@ target_include_directories(gen_legal_metadata_characters ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3946,6 +3960,7 @@ target_include_directories(gen_percent_encoding_tables ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -3972,16 +3987,13 @@ target_include_directories(algorithm_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(algorithm_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4002,16 +4014,13 @@ target_include_directories(alloc_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alloc_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4032,16 +4041,13 @@ target_include_directories(alpn_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alpn_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4063,16 +4069,13 @@ target_include_directories(alts_counter_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_counter_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4094,16 +4097,13 @@ target_include_directories(alts_crypt_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_crypt_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4125,16 +4125,13 @@ target_include_directories(alts_crypter_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_crypter_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4157,16 +4154,13 @@ target_include_directories(alts_frame_protector_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_frame_protector_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4188,16 +4182,13 @@ target_include_directories(alts_grpc_record_protocol_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_grpc_record_protocol_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4219,16 +4210,13 @@ target_include_directories(alts_handshaker_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_handshaker_client_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4250,16 +4238,13 @@ target_include_directories(alts_iovec_record_protocol_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_iovec_record_protocol_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4280,16 +4265,13 @@ target_include_directories(alts_security_connector_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_security_connector_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4311,16 +4293,13 @@ target_include_directories(alts_tsi_handshaker_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_tsi_handshaker_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4342,16 +4321,13 @@ target_include_directories(alts_tsi_utils_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_tsi_utils_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4373,16 +4349,13 @@ target_include_directories(alts_zero_copy_grpc_protector_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(alts_zero_copy_grpc_protector_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4403,16 +4376,13 @@ target_include_directories(arena_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(arena_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4433,16 +4403,13 @@ target_include_directories(auth_context_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(auth_context_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4463,16 +4430,13 @@ target_include_directories(avl_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(avl_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4493,16 +4457,13 @@ target_include_directories(b64_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(b64_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4524,16 +4485,13 @@ target_include_directories(bad_server_response_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(bad_server_response_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4556,16 +4514,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(bad_ssl_alpn_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4589,16 +4544,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(bad_ssl_cert_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4620,16 +4572,13 @@ target_include_directories(bin_decoder_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(bin_decoder_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4650,16 +4599,13 @@ target_include_directories(bin_encoder_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(bin_encoder_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4680,16 +4626,13 @@ target_include_directories(buffer_list_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(buffer_list_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4710,16 +4653,13 @@ target_include_directories(channel_args_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(channel_args_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4740,16 +4680,13 @@ target_include_directories(channel_create_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(channel_create_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4770,16 +4707,13 @@ target_include_directories(channel_stack_builder_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(channel_stack_builder_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4800,16 +4734,13 @@ target_include_directories(channel_stack_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(channel_stack_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4830,16 +4761,13 @@ target_include_directories(check_gcp_environment_linux_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(check_gcp_environment_linux_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4860,16 +4788,13 @@ target_include_directories(check_gcp_environment_windows_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(check_gcp_environment_windows_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4891,16 +4816,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(client_ssl_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4922,16 +4844,13 @@ target_include_directories(cmdline_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(cmdline_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4953,16 +4872,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(combiner_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -4984,16 +4900,13 @@ target_include_directories(completion_queue_threading_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(completion_queue_threading_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5014,16 +4927,13 @@ target_include_directories(compression_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(compression_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5044,16 +4954,13 @@ target_include_directories(concurrent_connectivity_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(concurrent_connectivity_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5075,16 +4982,13 @@ target_include_directories(connection_refused_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(connection_refused_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5105,16 +5009,13 @@ target_include_directories(cpu_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(cpu_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5135,16 +5036,13 @@ target_include_directories(dns_resolver_connectivity_using_ares_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(dns_resolver_connectivity_using_ares_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5165,16 +5063,13 @@ target_include_directories(dns_resolver_connectivity_using_native_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(dns_resolver_connectivity_using_native_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5195,16 +5090,13 @@ target_include_directories(dns_resolver_cooldown_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(dns_resolver_cooldown_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5225,16 +5117,13 @@ target_include_directories(dns_resolver_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(dns_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5257,16 +5146,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(dualstack_socket_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5289,16 +5175,13 @@ target_include_directories(endpoint_pair_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(endpoint_pair_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5319,16 +5202,13 @@ target_include_directories(env_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(env_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5350,16 +5230,13 @@ target_include_directories(error_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(error_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5381,16 +5258,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(ev_epollex_linux_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5412,16 +5286,13 @@ target_include_directories(fake_resolver_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(fake_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5443,16 +5314,13 @@ target_include_directories(fake_transport_security_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(fake_transport_security_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5474,16 +5342,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(fd_conservation_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5506,16 +5371,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(fd_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5542,16 +5404,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(fling_stream_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5578,16 +5437,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(fling_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5610,16 +5466,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(fork_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5645,16 +5498,13 @@ target_include_directories(format_request_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(format_request_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5676,16 +5526,13 @@ target_include_directories(frame_handler_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(frame_handler_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5707,16 +5554,13 @@ target_include_directories(goaway_server_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(goaway_server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5737,16 +5581,13 @@ target_include_directories(grpc_alts_credentials_options_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_alts_credentials_options_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5767,16 +5608,13 @@ target_include_directories(grpc_byte_buffer_reader_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_byte_buffer_reader_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5797,16 +5635,13 @@ target_include_directories(grpc_completion_queue_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_completion_queue_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5827,16 +5662,13 @@ target_include_directories(grpc_ipv6_loopback_available_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(grpc_ipv6_loopback_available_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5859,16 +5691,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(handshake_server_with_readahead_handshaker_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5891,16 +5720,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(handshake_verify_peer_options_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5922,16 +5748,13 @@ target_include_directories(histogram_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(histogram_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5952,16 +5775,13 @@ target_include_directories(host_port_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(host_port_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -5982,16 +5802,13 @@ target_include_directories(hpack_encoder_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(hpack_encoder_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6012,16 +5829,13 @@ target_include_directories(hpack_parser_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(hpack_parser_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6042,16 +5856,13 @@ target_include_directories(hpack_table_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(hpack_table_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6077,16 +5888,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(httpcli_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6113,16 +5921,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(httpscli_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6144,17 +5949,13 @@ target_include_directories(inproc_callback_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(inproc_callback_test ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests - grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6176,16 +5977,13 @@ target_include_directories(invalid_call_argument_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(invalid_call_argument_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6206,16 +6004,13 @@ target_include_directories(json_token_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(json_token_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6236,16 +6031,13 @@ target_include_directories(jwt_verifier_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(jwt_verifier_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6267,16 +6059,13 @@ target_include_directories(lame_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(lame_client_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6297,16 +6086,13 @@ target_include_directories(load_file_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(load_file_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6327,16 +6113,13 @@ target_include_directories(manual_constructor_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(manual_constructor_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6357,16 +6140,13 @@ target_include_directories(message_compress_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(message_compress_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6387,16 +6167,13 @@ target_include_directories(metadata_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(metadata_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6417,16 +6194,13 @@ target_include_directories(minimal_stack_is_minimal_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(minimal_stack_is_minimal_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6447,16 +6221,13 @@ target_include_directories(mpmcqueue_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(mpmcqueue_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6478,16 +6249,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(mpscq_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6510,16 +6278,13 @@ target_include_directories(multiple_server_queues_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(multiple_server_queues_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6540,16 +6305,13 @@ target_include_directories(murmur_hash_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(murmur_hash_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6571,16 +6333,13 @@ target_include_directories(no_server_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(no_server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6601,16 +6360,13 @@ target_include_directories(num_external_connectivity_watchers_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(num_external_connectivity_watchers_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6618,7 +6374,7 @@ endif() if(gRPC_BUILD_TESTS) add_executable(parse_address_test - test/core/iomgr/parse_address_test.cc + test/core/address_utils/parse_address_test.cc ) target_include_directories(parse_address_test @@ -6631,16 +6387,13 @@ target_include_directories(parse_address_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(parse_address_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6649,7 +6402,7 @@ if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) add_executable(parse_address_with_named_scope_id_test - test/core/iomgr/parse_address_with_named_scope_id_test.cc + test/core/address_utils/parse_address_with_named_scope_id_test.cc ) target_include_directories(parse_address_with_named_scope_id_test @@ -6662,16 +6415,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(parse_address_with_named_scope_id_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6697,16 +6447,13 @@ target_include_directories(parser_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(parser_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6727,16 +6474,13 @@ target_include_directories(percent_encoding_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(percent_encoding_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6757,16 +6501,13 @@ target_include_directories(public_headers_must_be_c89 ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(public_headers_must_be_c89 ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6788,16 +6529,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(resolve_address_using_ares_resolver_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6819,16 +6557,13 @@ target_include_directories(resolve_address_using_ares_resolver_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(resolve_address_using_ares_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6850,16 +6585,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(resolve_address_using_native_resolver_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6881,16 +6613,13 @@ target_include_directories(resolve_address_using_native_resolver_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(resolve_address_using_native_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6911,16 +6640,13 @@ target_include_directories(resource_quota_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(resource_quota_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6941,16 +6667,13 @@ target_include_directories(secure_channel_create_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(secure_channel_create_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -6972,16 +6695,13 @@ target_include_directories(secure_endpoint_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(secure_endpoint_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7002,16 +6722,13 @@ target_include_directories(security_connector_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(security_connector_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7032,16 +6749,13 @@ target_include_directories(sequential_connectivity_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(sequential_connectivity_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7064,16 +6778,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(server_ssl_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7095,16 +6806,13 @@ target_include_directories(server_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7125,16 +6833,13 @@ target_include_directories(slice_buffer_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(slice_buffer_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7155,16 +6860,13 @@ target_include_directories(slice_string_helpers_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(slice_string_helpers_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7185,56 +6887,23 @@ target_include_directories(sockaddr_resolver_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(sockaddr_resolver_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) endif() if(gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) -add_executable(sockaddr_utils_test - test/core/iomgr/sockaddr_utils_test.cc -) - -target_include_directories(sockaddr_utils_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(sockaddr_utils_test - ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util - grpc - gpr - address_sorting - upb -) - - -endif() -if(gRPC_BUILD_TESTS) -if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) - - add_executable(socket_utils_test - test/core/iomgr/socket_utils_test.cc - ) + add_executable(socket_utils_test + test/core/iomgr/socket_utils_test.cc + ) target_include_directories(socket_utils_test PRIVATE @@ -7246,16 +6915,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(socket_utils_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7277,16 +6943,13 @@ target_include_directories(spinlock_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(spinlock_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7307,16 +6970,13 @@ target_include_directories(ssl_credentials_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(ssl_credentials_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7339,16 +6999,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(ssl_transport_security_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7370,16 +7027,13 @@ target_include_directories(status_conversion_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(status_conversion_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7400,16 +7054,13 @@ target_include_directories(stream_compression_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(stream_compression_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7430,16 +7081,13 @@ target_include_directories(stream_map_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(stream_map_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7460,16 +7108,13 @@ target_include_directories(stream_owned_slice_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(stream_owned_slice_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7490,16 +7135,13 @@ target_include_directories(string_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(string_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7520,16 +7162,13 @@ target_include_directories(sync_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(sync_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7551,16 +7190,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(tcp_client_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7584,16 +7220,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(tcp_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7616,16 +7249,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(tcp_server_posix_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7647,16 +7277,13 @@ target_include_directories(test_core_gpr_time_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(test_core_gpr_time_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7677,16 +7304,13 @@ target_include_directories(test_core_security_credentials_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(test_core_security_credentials_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7707,16 +7331,13 @@ target_include_directories(test_core_slice_slice_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(test_core_slice_slice_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7737,16 +7358,13 @@ target_include_directories(thd_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(thd_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7767,16 +7385,13 @@ target_include_directories(threadpool_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(threadpool_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7797,16 +7412,13 @@ target_include_directories(time_averaged_stats_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(time_averaged_stats_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7827,16 +7439,13 @@ target_include_directories(timeout_encoding_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(timeout_encoding_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7857,16 +7466,13 @@ target_include_directories(timer_heap_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(timer_heap_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7887,16 +7493,13 @@ target_include_directories(timer_list_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(timer_list_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7917,16 +7520,13 @@ target_include_directories(tls_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(tls_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7947,16 +7547,13 @@ target_include_directories(transport_security_common_api_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(transport_security_common_api_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -7977,16 +7574,13 @@ target_include_directories(transport_security_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(transport_security_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8008,16 +7602,13 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(udp_server_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8039,16 +7630,13 @@ target_include_directories(useful_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(useful_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8069,16 +7657,13 @@ target_include_directories(varint_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ) target_link_libraries(varint_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8102,6 +7687,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8113,14 +7699,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(address_sorting_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -8148,6 +7728,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8159,17 +7740,68 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(address_sorting_test_unsecure ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util_unsecure grpc++_unsecure - grpc_unsecure + grpc_test_util_unsecure grpc++_test_config - gpr - address_sorting - upb ) endif() +endif() +if(gRPC_BUILD_TESTS) + +add_executable(admin_services_end2end_test + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h + src/cpp/server/admin/admin_services.cc + src/cpp/server/csds/csds.cc + test/cpp/end2end/admin_services_end2end_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(admin_services_end2end_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(admin_services_end2end_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_reflection + grpcpp_channelz + grpc++_test_util +) + + endif() if(gRPC_BUILD_TESTS) if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) @@ -8190,6 +7822,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8201,12 +7834,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(alarm_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util_unsecure grpc++_unsecure - grpc_unsecure - gpr - address_sorting - upb + grpc_test_util_unsecure ) @@ -8241,6 +7870,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8252,12 +7882,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) target_link_libraries(alts_concurrent_connectivity_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -8281,6 +7907,7 @@ target_include_directories(alts_util_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8292,14 +7919,8 @@ target_include_directories(alts_util_test target_link_libraries(alts_util_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util grpc++_alts - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -8342,6 +7963,7 @@ target_include_directories(async_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8354,12 +7976,6 @@ target_link_libraries(async_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -8382,6 +7998,7 @@ target_include_directories(auth_property_iterator_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8394,25 +8011,23 @@ target_link_libraries(auth_property_iterator_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) endif() if(gRPC_BUILD_TESTS) -add_executable(authorization_engine_test - test/core/security/authorization_engine_test.cc +add_executable(authorization_matchers_test + src/core/lib/security/authorization/evaluate_args.cc + src/core/lib/security/authorization/grpc_authorization_engine.cc + src/core/lib/security/authorization/matchers.cc + src/core/lib/security/authorization/rbac_policy.cc + test/core/security/authorization_matchers_test.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc ) -target_include_directories(authorization_engine_test +target_include_directories(authorization_matchers_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -8422,6 +8037,7 @@ target_include_directories(authorization_engine_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8430,14 +8046,10 @@ target_include_directories(authorization_engine_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(authorization_engine_test +target_link_libraries(authorization_matchers_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8460,6 +8072,7 @@ target_include_directories(aws_request_signer_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8472,10 +8085,6 @@ target_link_libraries(aws_request_signer_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8498,6 +8107,7 @@ target_include_directories(backoff_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8510,10 +8120,6 @@ target_link_libraries(backoff_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8538,6 +8144,7 @@ target_include_directories(bad_streaming_id_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8550,10 +8157,6 @@ target_link_libraries(bad_streaming_id_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8578,6 +8181,7 @@ target_include_directories(badreq_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8590,10 +8194,6 @@ target_link_libraries(badreq_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8617,6 +8217,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8629,10 +8230,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -8657,6 +8254,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8669,14 +8267,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -8701,6 +8291,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8713,14 +8304,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -8745,6 +8328,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8757,14 +8341,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -8789,6 +8365,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8801,14 +8378,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -8837,6 +8406,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8849,14 +8419,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -8885,6 +8447,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8897,14 +8460,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -8929,6 +8484,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8941,14 +8497,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -8973,6 +8521,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -8985,14 +8534,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9017,6 +8558,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9029,14 +8571,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9061,6 +8595,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9073,14 +8608,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9105,6 +8632,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9117,14 +8645,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9149,6 +8669,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9161,14 +8682,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9193,6 +8706,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9205,14 +8719,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9237,6 +8743,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9249,14 +8756,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9281,6 +8780,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9293,14 +8793,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9325,6 +8817,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9336,16 +8829,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(bm_fullstack_trickle ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} absl::flags + benchmark_helpers ) @@ -9370,6 +8855,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9382,14 +8868,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9414,6 +8892,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9426,14 +8905,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9458,6 +8929,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9470,14 +8942,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9502,6 +8966,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9514,14 +8979,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9546,6 +9003,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9558,14 +9016,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} benchmark_helpers - grpc_test_util_unsecure - grpc++_unsecure - grpc_unsecure - grpc++_test_config - gpr - address_sorting - upb - ${_gRPC_BENCHMARK_LIBRARIES} ) @@ -9589,6 +9039,7 @@ target_include_directories(byte_buffer_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9601,12 +9052,6 @@ target_link_libraries(byte_buffer_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -9629,6 +9074,7 @@ target_include_directories(byte_stream_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9641,10 +9087,6 @@ target_link_libraries(byte_stream_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -9669,6 +9111,7 @@ target_include_directories(cancel_ares_query_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9680,14 +9123,49 @@ target_include_directories(cancel_ares_query_test target_link_libraries(cancel_ares_query_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test_config grpc++_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(cel_authorization_engine_test + src/core/lib/security/authorization/cel_authorization_engine.cc + src/core/lib/security/authorization/evaluate_args.cc + src/core/lib/security/authorization/grpc_authorization_engine.cc + src/core/lib/security/authorization/matchers.cc + src/core/lib/security/authorization/rbac_policy.cc + test/core/security/cel_authorization_engine_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(cel_authorization_engine_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(cel_authorization_engine_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flat_hash_set grpc_test_util - grpc++ - grpc++_test_config - grpc - gpr - address_sorting - upb ) @@ -9710,6 +9188,7 @@ target_include_directories(certificate_provider_registry_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9722,10 +9201,6 @@ target_link_libraries(certificate_provider_registry_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -9748,6 +9223,7 @@ target_include_directories(certificate_provider_store_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9760,10 +9236,6 @@ target_link_libraries(certificate_provider_store_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -9799,6 +9271,7 @@ target_include_directories(cfstream_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9811,12 +9284,6 @@ target_link_libraries(cfstream_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -9839,6 +9306,7 @@ target_include_directories(channel_arguments_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9850,12 +9318,8 @@ target_include_directories(channel_arguments_test target_link_libraries(channel_arguments_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -9878,6 +9342,7 @@ target_include_directories(channel_filter_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9889,12 +9354,8 @@ target_include_directories(channel_filter_test target_link_libraries(channel_filter_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -9922,6 +9383,7 @@ target_include_directories(channel_trace_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9933,12 +9395,8 @@ target_include_directories(channel_trace_test target_link_libraries(channel_trace_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -9961,6 +9419,7 @@ target_include_directories(channelz_registry_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -9972,12 +9431,8 @@ target_include_directories(channelz_registry_test target_link_libraries(channelz_registry_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -10013,6 +9468,7 @@ target_include_directories(channelz_service_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10026,12 +9482,6 @@ target_link_libraries(channelz_service_test ${_gRPC_ALLTARGETS_LIBRARIES} grpcpp_channelz grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10059,6 +9509,7 @@ target_include_directories(channelz_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10070,12 +9521,8 @@ target_include_directories(channelz_test target_link_libraries(channelz_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -10120,6 +9567,7 @@ target_include_directories(cli_call_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10132,13 +9580,6 @@ target_link_libraries(cli_call_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb - absl::flags ) @@ -10175,6 +9616,7 @@ target_include_directories(client_callback_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10187,12 +9629,6 @@ target_link_libraries(client_callback_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10237,6 +9673,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10249,12 +9686,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10292,6 +9723,7 @@ target_include_directories(client_interceptors_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10304,12 +9736,6 @@ target_link_libraries(client_interceptors_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10355,6 +9781,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10367,12 +9794,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10396,6 +9817,7 @@ target_include_directories(codegen_test_full ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10407,12 +9829,8 @@ target_include_directories(codegen_test_full target_link_libraries(codegen_test_full ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -10435,6 +9853,7 @@ target_include_directories(codegen_test_minimal ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10446,12 +9865,8 @@ target_include_directories(codegen_test_minimal target_link_libraries(codegen_test_minimal ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -10476,6 +9891,7 @@ target_include_directories(connection_prefix_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10488,10 +9904,6 @@ target_link_libraries(connection_prefix_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -10514,6 +9926,7 @@ target_include_directories(connectivity_state_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10526,10 +9939,6 @@ target_link_libraries(connectivity_state_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -10565,6 +9974,7 @@ target_include_directories(context_allocator_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10577,12 +9987,6 @@ target_link_libraries(context_allocator_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10605,6 +10009,7 @@ target_include_directories(context_list_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10617,10 +10022,6 @@ target_link_libraries(context_list_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -10656,6 +10057,7 @@ target_include_directories(delegating_channel_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10668,12 +10070,6 @@ target_link_libraries(delegating_channel_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10696,6 +10092,7 @@ target_include_directories(destroy_grpclb_channel_with_active_connect_stress_tes ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10708,12 +10105,6 @@ target_link_libraries(destroy_grpclb_channel_with_active_connect_stress_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -10736,6 +10127,7 @@ target_include_directories(dual_ref_counted_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10748,10 +10140,6 @@ target_link_libraries(dual_ref_counted_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -10776,6 +10164,7 @@ target_include_directories(duplicate_header_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10788,10 +10177,6 @@ target_link_libraries(duplicate_header_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -10832,6 +10217,7 @@ target_include_directories(end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10843,14 +10229,8 @@ target_include_directories(end2end_test target_link_libraries(end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util grpc++_test - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -10881,6 +10261,7 @@ target_include_directories(error_details_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10894,24 +10275,19 @@ target_link_libraries(error_details_test ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_error_details grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) endif() if(gRPC_BUILD_TESTS) -add_executable(evaluate_args_test - test/core/security/evaluate_args_test.cc +add_executable(error_utils_test + test/core/transport/error_utils_test.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc ) -target_include_directories(evaluate_args_test +target_include_directories(error_utils_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -10921,6 +10297,7 @@ target_include_directories(evaluate_args_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10929,27 +10306,27 @@ target_include_directories(evaluate_args_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(evaluate_args_test +target_link_libraries(error_utils_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) endif() if(gRPC_BUILD_TESTS) -add_executable(eventmanager_libuv_test - test/core/iomgr/poller/eventmanager_libuv_test.cc +add_executable(evaluate_args_test + src/core/lib/security/authorization/evaluate_args.cc + src/core/lib/security/authorization/grpc_authorization_engine.cc + src/core/lib/security/authorization/matchers.cc + src/core/lib/security/authorization/rbac_policy.cc + test/core/security/evaluate_args_test.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc ) -target_include_directories(eventmanager_libuv_test +target_include_directories(evaluate_args_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -10959,6 +10336,7 @@ target_include_directories(eventmanager_libuv_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -10967,14 +10345,10 @@ target_include_directories(eventmanager_libuv_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(eventmanager_libuv_test +target_link_libraries(evaluate_args_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -10998,6 +10372,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11010,12 +10385,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb - absl::symbolize - absl::stacktrace ) @@ -11051,6 +10420,7 @@ target_include_directories(exception_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11063,12 +10433,6 @@ target_link_libraries(exception_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -11091,6 +10455,7 @@ target_include_directories(file_watcher_certificate_provider_factory_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11103,10 +10468,6 @@ target_link_libraries(file_watcher_certificate_provider_factory_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -11145,6 +10506,7 @@ target_include_directories(filter_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11157,12 +10519,6 @@ target_link_libraries(filter_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -11198,6 +10554,7 @@ target_include_directories(flaky_network_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11210,12 +10567,6 @@ target_link_libraries(flaky_network_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -11254,6 +10605,7 @@ target_include_directories(generic_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11266,12 +10618,6 @@ target_link_libraries(generic_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -11295,6 +10641,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11307,10 +10654,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -11334,6 +10677,7 @@ target_include_directories(global_config_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11346,10 +10690,6 @@ target_link_libraries(global_config_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -11373,6 +10713,7 @@ target_include_directories(google_mesh_ca_certificate_provider_factory_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11385,24 +10726,59 @@ target_link_libraries(google_mesh_ca_certificate_provider_factory_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) endif() if(gRPC_BUILD_TESTS) -add_executable(grpc_cli - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h - ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h - test/cpp/util/cli_call.cc - test/cpp/util/cli_credentials.cc - test/cpp/util/grpc_cli.cc +add_executable(grpc_authorization_engine_test + src/core/lib/security/authorization/evaluate_args.cc + src/core/lib/security/authorization/grpc_authorization_engine.cc + src/core/lib/security/authorization/matchers.cc + src/core/lib/security/authorization/rbac_policy.cc + test/core/security/grpc_authorization_engine_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(grpc_authorization_engine_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(grpc_authorization_engine_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(grpc_cli + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h + test/cpp/util/cli_call.cc + test/cpp/util/cli_credentials.cc + test/cpp/util/grpc_cli.cc test/cpp/util/grpc_tool.cc test/cpp/util/proto_file_parser.cc test/cpp/util/proto_reflection_descriptor_database.cc @@ -11421,6 +10797,7 @@ target_include_directories(grpc_cli ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11432,13 +10809,9 @@ target_include_directories(grpc_cli target_link_libraries(grpc_cli ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -11459,6 +10832,7 @@ target_include_directories(grpc_cpp_plugin ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -11497,6 +10871,7 @@ target_include_directories(grpc_csharp_plugin ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -11535,6 +10910,7 @@ target_include_directories(grpc_node_plugin ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -11573,6 +10949,7 @@ target_include_directories(grpc_objective_c_plugin ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -11611,6 +10988,7 @@ target_include_directories(grpc_php_plugin ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -11649,6 +11027,7 @@ target_include_directories(grpc_python_plugin ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -11687,6 +11066,7 @@ target_include_directories(grpc_ruby_plugin ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} ${_gRPC_PROTO_GENS_DIR} ) @@ -11727,6 +11107,7 @@ target_include_directories(grpc_tls_certificate_distributor_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11739,10 +11120,6 @@ target_link_libraries(grpc_tls_certificate_distributor_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -11765,6 +11142,7 @@ target_include_directories(grpc_tls_certificate_provider_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11777,10 +11155,6 @@ target_link_libraries(grpc_tls_certificate_provider_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -11803,6 +11177,7 @@ target_include_directories(grpc_tls_credentials_options_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11815,10 +11190,6 @@ target_link_libraries(grpc_tls_credentials_options_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -11860,6 +11231,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11871,15 +11243,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(grpc_tool_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util grpc++_reflection - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb - absl::flags + grpc++_test_util ) @@ -11907,6 +11272,7 @@ target_include_directories(grpclb_api_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11919,12 +11285,6 @@ target_link_libraries(grpclb_api_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -11969,6 +11329,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -11981,12 +11342,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -12010,6 +11365,7 @@ target_include_directories(h2_ssl_session_reuse_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12022,11 +11378,6 @@ target_link_libraries(h2_ssl_session_reuse_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} end2end_tests - grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12051,6 +11402,7 @@ target_include_directories(head_of_line_blocking_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12063,10 +11415,6 @@ target_link_libraries(head_of_line_blocking_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12091,6 +11439,7 @@ target_include_directories(headers_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12103,10 +11452,6 @@ target_link_libraries(headers_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12151,6 +11496,7 @@ target_include_directories(health_service_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12163,12 +11509,6 @@ target_link_libraries(health_service_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -12203,6 +11543,7 @@ target_include_directories(http2_client ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12214,15 +11555,8 @@ target_include_directories(http2_client target_link_libraries(http2_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags + grpc++_test_util ) @@ -12262,6 +11596,7 @@ target_include_directories(hybrid_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12274,12 +11609,6 @@ target_link_libraries(hybrid_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -12302,6 +11631,7 @@ target_include_directories(init_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12314,10 +11644,6 @@ target_link_libraries(init_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12342,6 +11668,7 @@ target_include_directories(initial_settings_frame_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12354,10 +11681,6 @@ target_link_libraries(initial_settings_frame_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12380,6 +11703,7 @@ target_include_directories(insecure_security_connector_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12392,10 +11716,6 @@ target_link_libraries(insecure_security_connector_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12433,6 +11753,7 @@ target_include_directories(interop_client ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12444,15 +11765,8 @@ target_include_directories(interop_client target_link_libraries(interop_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags + grpc++_test_util ) @@ -12489,6 +11803,7 @@ target_include_directories(interop_server ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12500,15 +11815,8 @@ target_include_directories(interop_server target_link_libraries(interop_server ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags + grpc++_test_util ) @@ -12532,6 +11840,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12543,15 +11852,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(interop_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags + grpc++_test_util ) @@ -12575,6 +11877,7 @@ target_include_directories(json_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12587,10 +11890,6 @@ target_link_libraries(json_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12615,6 +11914,7 @@ target_include_directories(large_metadata_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12627,10 +11927,6 @@ target_link_libraries(large_metadata_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12657,6 +11953,7 @@ target_include_directories(lb_get_cpu_stats_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12668,12 +11965,8 @@ target_include_directories(lb_get_cpu_stats_test target_link_libraries(lb_get_cpu_stats_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -12697,6 +11990,7 @@ target_include_directories(lb_load_data_store_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12708,12 +12002,8 @@ target_include_directories(lb_load_data_store_test target_link_libraries(lb_load_data_store_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -12736,6 +12026,7 @@ target_include_directories(linux_system_roots_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12748,10 +12039,6 @@ target_link_libraries(linux_system_roots_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12774,6 +12061,7 @@ target_include_directories(log_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12786,10 +12074,6 @@ target_link_libraries(log_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12812,6 +12096,7 @@ target_include_directories(matchers_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12824,10 +12109,6 @@ target_link_libraries(matchers_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -12863,6 +12144,7 @@ target_include_directories(message_allocator_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12875,12 +12157,54 @@ target_link_libraries(message_allocator_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(mock_stream_test + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h + test/cpp/test/mock_stream_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(mock_stream_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(mock_stream_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc++_test + grpc++_test_util ) @@ -12919,6 +12243,7 @@ target_include_directories(mock_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12930,14 +12255,8 @@ target_include_directories(mock_test target_link_libraries(mock_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util grpc++_test - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -12972,6 +12291,7 @@ target_include_directories(nonblocking_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -12984,12 +12304,6 @@ target_link_libraries(nonblocking_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -13012,6 +12326,7 @@ target_include_directories(noop-benchmark ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13023,12 +12338,8 @@ target_include_directories(noop-benchmark target_link_libraries(noop-benchmark ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util - grpc - gpr - address_sorting - upb ${_gRPC_BENCHMARK_LIBRARIES} + grpc_test_util ) @@ -13051,6 +12362,7 @@ target_include_directories(orphanable_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13063,10 +12375,6 @@ target_link_libraries(orphanable_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13091,6 +12399,7 @@ target_include_directories(out_of_bounds_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13103,10 +12412,6 @@ target_link_libraries(out_of_bounds_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13129,6 +12434,7 @@ target_include_directories(pid_controller_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13141,10 +12447,6 @@ target_link_libraries(pid_controller_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13180,6 +12482,7 @@ target_include_directories(port_sharing_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13192,12 +12495,6 @@ target_link_libraries(port_sharing_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -13238,6 +12535,7 @@ target_include_directories(proto_server_reflection_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13249,14 +12547,8 @@ target_include_directories(proto_server_reflection_test target_link_libraries(proto_server_reflection_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util grpc++_reflection - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -13279,6 +12571,7 @@ target_include_directories(proto_utils_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13290,12 +12583,8 @@ target_include_directories(proto_utils_test target_link_libraries(proto_utils_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -13364,6 +12653,7 @@ target_include_directories(qps_json_driver ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13375,15 +12665,8 @@ target_include_directories(qps_json_driver target_link_libraries(qps_json_driver ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags + grpc++_test_util ) @@ -13444,6 +12727,7 @@ target_include_directories(qps_worker ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13455,15 +12739,8 @@ target_include_directories(qps_worker target_link_libraries(qps_worker ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags + grpc++_test_util ) @@ -13503,6 +12780,7 @@ target_include_directories(raw_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13515,12 +12793,46 @@ target_link_libraries(raw_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(rbac_translator_test + src/core/lib/security/authorization/evaluate_args.cc + src/core/lib/security/authorization/grpc_authorization_engine.cc + src/core/lib/security/authorization/matchers.cc + src/core/lib/security/authorization/rbac_policy.cc + src/core/lib/security/authorization/rbac_translator.cc + test/core/security/rbac_translator_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(rbac_translator_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(rbac_translator_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -13543,6 +12855,7 @@ target_include_directories(ref_counted_ptr_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13555,10 +12868,6 @@ target_link_libraries(ref_counted_ptr_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13581,6 +12890,7 @@ target_include_directories(ref_counted_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13593,10 +12903,6 @@ target_link_libraries(ref_counted_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13620,6 +12926,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13632,10 +12939,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13659,6 +12962,7 @@ target_include_directories(retry_throttle_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13671,10 +12975,6 @@ target_link_libraries(retry_throttle_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13697,6 +12997,7 @@ target_include_directories(secure_auth_context_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13709,12 +13010,6 @@ target_link_libraries(secure_auth_context_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -13754,6 +13049,7 @@ target_include_directories(server_builder_plugin_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13766,12 +13062,6 @@ target_link_libraries(server_builder_plugin_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -13807,6 +13097,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13818,12 +13109,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(server_builder_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util_unsecure grpc++_unsecure - grpc_unsecure - gpr - address_sorting - upb + grpc_test_util_unsecure ) @@ -13860,6 +13147,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13871,12 +13159,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(server_builder_with_socket_mutator_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util_unsecure grpc++_unsecure - grpc_unsecure - gpr - address_sorting - upb + grpc_test_util_unsecure ) @@ -13900,6 +13184,7 @@ target_include_directories(server_chttp2_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13912,10 +13197,6 @@ target_link_libraries(server_chttp2_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -13938,6 +13219,7 @@ target_include_directories(server_context_test_spouse_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -13949,14 +13231,8 @@ target_include_directories(server_context_test_spouse_test target_link_libraries(server_context_test_spouse_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util grpc++_test - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -13991,6 +13267,7 @@ target_include_directories(server_early_return_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14003,12 +13280,6 @@ target_link_libraries(server_early_return_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -14045,6 +13316,7 @@ target_include_directories(server_interceptors_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14057,12 +13329,6 @@ target_link_libraries(server_interceptors_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -14087,6 +13353,7 @@ target_include_directories(server_registered_method_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14099,10 +13366,6 @@ target_link_libraries(server_registered_method_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -14138,6 +13401,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14149,12 +13413,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(server_request_call_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util_unsecure grpc++_unsecure - grpc_unsecure - gpr - address_sorting - upb + grpc_test_util_unsecure ) @@ -14195,6 +13455,7 @@ target_include_directories(service_config_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14207,12 +13468,6 @@ target_link_libraries(service_config_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -14235,6 +13490,7 @@ target_include_directories(service_config_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14247,10 +13503,6 @@ target_link_libraries(service_config_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -14273,6 +13525,7 @@ target_include_directories(settings_timeout_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14285,10 +13538,6 @@ target_link_libraries(settings_timeout_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -14327,6 +13576,7 @@ target_include_directories(shutdown_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14339,12 +13589,6 @@ target_link_libraries(shutdown_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -14369,6 +13613,7 @@ target_include_directories(simple_request_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14381,10 +13626,41 @@ target_link_libraries(simple_request_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb +) + + +endif() +if(gRPC_BUILD_TESTS) + +add_executable(sockaddr_utils_test + test/core/address_utils/sockaddr_utils_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(sockaddr_utils_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(sockaddr_utils_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util ) @@ -14408,6 +13684,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14420,25 +13697,55 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb - absl::symbolize ) -endif() +endif() +endif() +if(gRPC_BUILD_TESTS) + +add_executable(stat_test + test/core/gprpp/stat_test.cc + third_party/googletest/googletest/src/gtest-all.cc + third_party/googletest/googlemock/src/gmock-all.cc +) + +target_include_directories(stat_test + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR} + ${_gRPC_RE2_INCLUDE_DIR} + ${_gRPC_SSL_INCLUDE_DIR} + ${_gRPC_UPB_GENERATED_DIR} + ${_gRPC_UPB_GRPC_GENERATED_DIR} + ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} + ${_gRPC_ZLIB_INCLUDE_DIR} + third_party/googletest/googletest/include + third_party/googletest/googletest + third_party/googletest/googlemock/include + third_party/googletest/googlemock + ${_gRPC_PROTO_GENS_DIR} +) + +target_link_libraries(stat_test + ${_gRPC_PROTOBUF_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util +) + + endif() if(gRPC_BUILD_TESTS) -add_executable(stat_test - test/core/gprpp/stat_test.cc +add_executable(static_metadata_test + test/core/transport/static_metadata_test.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc ) -target_include_directories(stat_test +target_include_directories(static_metadata_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -14448,6 +13755,7 @@ target_include_directories(stat_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14456,27 +13764,23 @@ target_include_directories(stat_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(stat_test +target_link_libraries(static_metadata_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) endif() if(gRPC_BUILD_TESTS) -add_executable(static_metadata_test - test/core/transport/static_metadata_test.cc +add_executable(stats_test + test/core/debug/stats_test.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc ) -target_include_directories(static_metadata_test +target_include_directories(stats_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -14486,6 +13790,7 @@ target_include_directories(static_metadata_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14494,27 +13799,23 @@ target_include_directories(static_metadata_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(static_metadata_test +target_link_libraries(stats_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) endif() if(gRPC_BUILD_TESTS) -add_executable(stats_test - test/core/debug/stats_test.cc +add_executable(status_helper_test + test/core/gprpp/status_helper_test.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc ) -target_include_directories(stats_test +target_include_directories(status_helper_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include @@ -14524,6 +13825,7 @@ target_include_directories(stats_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14532,14 +13834,10 @@ target_include_directories(stats_test ${_gRPC_PROTO_GENS_DIR} ) -target_link_libraries(stats_test +target_link_libraries(status_helper_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -14562,6 +13860,7 @@ target_include_directories(status_metadata_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14574,10 +13873,6 @@ target_link_libraries(status_metadata_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -14600,6 +13895,7 @@ target_include_directories(status_util_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14612,10 +13908,6 @@ target_link_libraries(status_util_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -14640,6 +13932,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14652,10 +13945,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -14696,6 +13985,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14708,12 +13998,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -14737,6 +14021,7 @@ target_include_directories(string_ref_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14748,12 +14033,8 @@ target_include_directories(string_ref_test target_link_libraries(string_ref_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -14776,6 +14057,7 @@ target_include_directories(test_cpp_client_credentials_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14787,12 +14069,8 @@ target_include_directories(test_cpp_client_credentials_test target_link_libraries(test_cpp_client_credentials_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -14815,6 +14093,7 @@ target_include_directories(test_cpp_server_credentials_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14826,12 +14105,8 @@ target_include_directories(test_cpp_server_credentials_test target_link_libraries(test_cpp_server_credentials_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -14854,6 +14129,7 @@ target_include_directories(test_cpp_util_slice_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14866,12 +14142,6 @@ target_link_libraries(test_cpp_util_slice_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -14894,6 +14164,7 @@ target_include_directories(test_cpp_util_time_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14906,12 +14177,6 @@ target_link_libraries(test_cpp_util_time_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -14934,6 +14199,7 @@ target_include_directories(thread_manager_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -14945,14 +14211,8 @@ target_include_directories(thread_manager_test target_link_libraries(thread_manager_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -14992,6 +14252,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15004,12 +14265,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -15034,6 +14289,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15045,12 +14301,8 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(time_jump_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -15074,6 +14326,7 @@ target_include_directories(time_util_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15086,10 +14339,6 @@ target_link_libraries(time_util_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15112,6 +14361,7 @@ target_include_directories(timer_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15123,12 +14373,8 @@ target_include_directories(timer_test target_link_libraries(timer_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc_test_util grpc++ - grpc - gpr - address_sorting - upb + grpc_test_util ) @@ -15151,6 +14397,7 @@ target_include_directories(tls_security_connector_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15163,10 +14410,6 @@ target_link_libraries(tls_security_connector_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15190,6 +14433,7 @@ target_include_directories(too_many_pings_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15201,14 +14445,8 @@ target_include_directories(too_many_pings_test target_link_libraries(too_many_pings_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++_test_util - grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb + grpc++_test_util ) @@ -15233,6 +14471,7 @@ target_include_directories(unknown_frame_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15245,10 +14484,6 @@ target_link_libraries(unknown_frame_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15271,6 +14506,7 @@ target_include_directories(uri_parser_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15283,10 +14519,6 @@ target_link_libraries(uri_parser_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15311,6 +14543,7 @@ target_include_directories(window_overflow_bad_client_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15323,10 +14556,6 @@ target_link_libraries(window_overflow_bad_client_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15350,6 +14579,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15362,10 +14592,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15388,7 +14614,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/simple_messages.grpc.pb.h test/core/util/cmdline.cc - test/core/util/eval_args_mock_endpoint.cc test/core/util/fuzzer_util.cc test/core/util/grpc_profiler.cc test/core/util/histogram.cc @@ -15424,6 +14649,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15435,14 +14661,10 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) target_link_libraries(writes_per_rpc_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} - grpc++ - grpc - gpr - address_sorting - upb - absl::symbolize - absl::stacktrace absl::failure_signal_handler + absl::stacktrace + absl::symbolize + grpc++ ) @@ -15466,6 +14688,7 @@ target_include_directories(xds_bootstrap_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15478,10 +14701,6 @@ target_link_libraries(xds_bootstrap_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15504,6 +14723,7 @@ target_include_directories(xds_certificate_provider_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15516,10 +14736,6 @@ target_link_libraries(xds_certificate_provider_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15555,6 +14771,7 @@ target_include_directories(xds_credentials_end2end_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15567,12 +14784,6 @@ target_link_libraries(xds_credentials_end2end_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -15595,6 +14806,7 @@ target_include_directories(xds_credentials_test ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15607,10 +14819,6 @@ target_link_libraries(xds_credentials_test ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc_test_util - grpc - gpr - address_sorting - upb ) @@ -15675,10 +14883,18 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_source.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/discovery.pb.h @@ -15687,6 +14903,14 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/fault_common.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/http_connection_manager.pb.h @@ -15735,6 +14959,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/tls.grpc.pb.h + src/cpp/server/csds/csds.cc test/cpp/end2end/test_service_impl.cc test/cpp/end2end/xds_end2end_test.cc third_party/googletest/googletest/src/gtest-all.cc @@ -15751,6 +14976,7 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15763,12 +14989,6 @@ if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX) ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} grpc++_test_util - grpc_test_util - grpc++ - grpc - gpr - address_sorting - upb ) @@ -15789,6 +15009,24 @@ add_executable(xds_interop_client ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h + src/cpp/server/admin/admin_services.cc + src/cpp/server/csds/csds.cc test/cpp/interop/xds_interop_client.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc @@ -15804,6 +15042,7 @@ target_include_directories(xds_interop_client ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15815,14 +15054,11 @@ target_include_directories(xds_interop_client target_link_libraries(xds_interop_client ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags + grpc++_reflection + grpcpp_channelz grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -15830,6 +15066,10 @@ endif() if(gRPC_BUILD_TESTS) add_executable(xds_interop_server + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/health/v1/health.grpc.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/empty.pb.h @@ -15842,6 +15082,25 @@ add_executable(xds_interop_server ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.cc ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.pb.h ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/test.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/base.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/config_dump.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/csds.grpc.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.cc + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.pb.h + ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/xds/v3/percent.grpc.pb.h + src/cpp/server/admin/admin_services.cc + src/cpp/server/csds/csds.cc + test/cpp/end2end/test_health_check_service_impl.cc test/cpp/interop/xds_interop_server.cc third_party/googletest/googletest/src/gtest-all.cc third_party/googletest/googlemock/src/gmock-all.cc @@ -15857,6 +15116,7 @@ target_include_directories(xds_interop_server ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15868,14 +15128,11 @@ target_include_directories(xds_interop_server target_link_libraries(xds_interop_server ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags + grpc++_reflection + grpcpp_channelz grpc_test_util - grpc++ grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -15899,6 +15156,7 @@ target_include_directories(alts_credentials_fuzzer_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15910,13 +15168,9 @@ target_include_directories(alts_credentials_fuzzer_one_entry target_link_libraries(alts_credentials_fuzzer_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -15940,6 +15194,7 @@ target_include_directories(client_fuzzer_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15951,13 +15206,9 @@ target_include_directories(client_fuzzer_one_entry target_link_libraries(client_fuzzer_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -15981,6 +15232,7 @@ target_include_directories(hpack_parser_fuzzer_test_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -15992,13 +15244,9 @@ target_include_directories(hpack_parser_fuzzer_test_one_entry target_link_libraries(hpack_parser_fuzzer_test_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16022,6 +15270,7 @@ target_include_directories(http_request_fuzzer_test_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16033,13 +15282,9 @@ target_include_directories(http_request_fuzzer_test_one_entry target_link_libraries(http_request_fuzzer_test_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16063,6 +15308,7 @@ target_include_directories(http_response_fuzzer_test_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16074,13 +15320,9 @@ target_include_directories(http_response_fuzzer_test_one_entry target_link_libraries(http_response_fuzzer_test_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16104,6 +15346,7 @@ target_include_directories(json_fuzzer_test_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16115,13 +15358,9 @@ target_include_directories(json_fuzzer_test_one_entry target_link_libraries(json_fuzzer_test_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16145,6 +15384,7 @@ target_include_directories(nanopb_fuzzer_response_test_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16156,13 +15396,9 @@ target_include_directories(nanopb_fuzzer_response_test_one_entry target_link_libraries(nanopb_fuzzer_response_test_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16186,6 +15422,7 @@ target_include_directories(nanopb_fuzzer_serverlist_test_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16197,13 +15434,9 @@ target_include_directories(nanopb_fuzzer_serverlist_test_one_entry target_link_libraries(nanopb_fuzzer_serverlist_test_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16227,6 +15460,7 @@ target_include_directories(percent_decode_fuzzer_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16238,13 +15472,9 @@ target_include_directories(percent_decode_fuzzer_one_entry target_link_libraries(percent_decode_fuzzer_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16268,6 +15498,7 @@ target_include_directories(percent_encode_fuzzer_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16279,13 +15510,9 @@ target_include_directories(percent_encode_fuzzer_one_entry target_link_libraries(percent_encode_fuzzer_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16309,6 +15536,7 @@ target_include_directories(server_fuzzer_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16320,13 +15548,9 @@ target_include_directories(server_fuzzer_one_entry target_link_libraries(server_fuzzer_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16350,6 +15574,7 @@ target_include_directories(ssl_server_fuzzer_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16361,13 +15586,9 @@ target_include_directories(ssl_server_fuzzer_one_entry target_link_libraries(ssl_server_fuzzer_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16391,6 +15612,7 @@ target_include_directories(uri_fuzzer_test_one_entry ${_gRPC_UPB_GENERATED_DIR} ${_gRPC_UPB_GRPC_GENERATED_DIR} ${_gRPC_UPB_INCLUDE_DIR} + ${_gRPC_XXHASH_INCLUDE_DIR} ${_gRPC_ZLIB_INCLUDE_DIR} third_party/googletest/googletest/include third_party/googletest/googletest @@ -16402,13 +15624,9 @@ target_include_directories(uri_fuzzer_test_one_entry target_link_libraries(uri_fuzzer_test_one_entry ${_gRPC_PROTOBUF_LIBRARIES} ${_gRPC_ALLTARGETS_LIBRARIES} + absl::flags grpc_test_util grpc++_test_config - grpc - gpr - address_sorting - upb - absl::flags ) @@ -16471,8 +15689,8 @@ generate_pkgconfig( "gpr" "gRPC platform support library" "${gRPC_CORE_VERSION}" - "" - "-lgpr -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity" + "absl_base absl_memory absl_optional absl_status absl_str_format absl_strings absl_synchronization absl_time" + "-lgpr" "" "gpr.pc") @@ -16481,8 +15699,8 @@ generate_pkgconfig( "gRPC" "high performance general RPC framework" "${gRPC_CORE_VERSION}" - "gpr openssl" - "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_city -labsl_statusor -labsl_bad_variant_access -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity" + "gpr openssl absl_base absl_bind_front absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time" + "-lgrpc -laddress_sorting -lre2 -lupb -lcares -lz" "" "grpc.pc") @@ -16491,8 +15709,8 @@ generate_pkgconfig( "gRPC unsecure" "high performance general RPC framework without SSL" "${gRPC_CORE_VERSION}" - "gpr" - "-lgrpc_unsecure -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_city -labsl_statusor -labsl_bad_variant_access -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity" + "gpr absl_base absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time" + "-lgrpc_unsecure" "" "grpc_unsecure.pc") @@ -16501,8 +15719,8 @@ generate_pkgconfig( "gRPC++" "C++ wrapper for gRPC" "${gRPC_CPP_VERSION}" - "grpc" - "-lgrpc++ -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_city -labsl_statusor -labsl_bad_variant_access -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity" + "grpc absl_base absl_bind_front absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time" + "-lgrpc++" "" "grpc++.pc") @@ -16511,7 +15729,7 @@ generate_pkgconfig( "gRPC++ unsecure" "C++ wrapper for gRPC without SSL" "${gRPC_CPP_VERSION}" - "grpc_unsecure" - "-lgrpc++_unsecure -labsl_raw_hash_set -labsl_hashtablez_sampler -labsl_exponential_biased -labsl_hash -labsl_city -labsl_statusor -labsl_bad_variant_access -labsl_status -labsl_cord -labsl_str_format_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_symbolize -labsl_demangle_internal -labsl_stacktrace -labsl_debugging_internal -labsl_malloc_internal -labsl_time -labsl_time_zone -labsl_civil_time -labsl_strings -labsl_strings_internal -labsl_throw_delegate -labsl_int128 -labsl_base -labsl_spinlock_wait -labsl_bad_optional_access -labsl_raw_logging_internal -labsl_log_severity" + "grpc_unsecure absl_base absl_flat_hash_map absl_inlined_vector absl_memory absl_optional absl_status absl_statusor absl_str_format absl_strings absl_synchronization absl_time" + "-lgrpc++_unsecure" "" "grpc++_unsecure.pc") diff --git a/Makefile b/Makefile index cb4e68971d1..af2a99db0e1 100644 --- a/Makefile +++ b/Makefile @@ -371,7 +371,7 @@ CXXFLAGS += -stdlib=libc++ LDFLAGS += -framework CoreFoundation endif CFLAGS += -g -CPPFLAGS += -g -Wall -Wextra -DOSATOMIC_USE_INLINED=1 -Ithird_party/abseil-cpp -Ithird_party/re2 -Ithird_party/upb -Isrc/core/ext/upb-generated -Isrc/core/ext/upbdefs-generated +CPPFLAGS += -g -Wall -Wextra -DOSATOMIC_USE_INLINED=1 -Ithird_party/abseil-cpp -Ithird_party/re2 -Ithird_party/upb -Isrc/core/ext/upb-generated -Isrc/core/ext/upbdefs-generated -Ithird_party/xxhash COREFLAGS += -fno-exceptions LDFLAGS += -g @@ -454,9 +454,9 @@ E = @echo Q = @ endif -CORE_VERSION = 15.0.0 -CPP_VERSION = 1.37.0-dev -CSHARP_VERSION = 2.37.0-dev +CORE_VERSION = 16.0.0 +CPP_VERSION = 1.38.0-dev +CSHARP_VERSION = 2.38.0-dev CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES)) CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS) @@ -492,7 +492,7 @@ SHARED_EXT_CORE = dll SHARED_EXT_CPP = dll SHARED_EXT_CSHARP = dll SHARED_PREFIX = -SHARED_VERSION_CORE = -15 +SHARED_VERSION_CORE = -16 SHARED_VERSION_CPP = -1 SHARED_VERSION_CSHARP = -2 else ifeq ($(SYSTEM),Darwin) @@ -891,8 +891,8 @@ $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): ifeq ($(SYSTEM),Darwin) $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.15 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) - $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.15 + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libaddress_sorting.so.16 -o $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBADDRESS_SORTING_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so.16 $(Q) ln -sf $(SHARED_PREFIX)address_sorting$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libaddress_sorting$(SHARED_VERSION_CORE).so endif endif @@ -905,6 +905,17 @@ endif # start of build recipe for library "gpr" (generated by makelib(lib) template function) LIBGPR_SRC = \ + src/core/ext/upb-generated/google/api/annotations.upb.c \ + src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c \ + src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c \ + src/core/ext/upb-generated/google/api/http.upb.c \ + src/core/ext/upb-generated/google/protobuf/any.upb.c \ + src/core/ext/upb-generated/google/protobuf/duration.upb.c \ + src/core/ext/upb-generated/google/protobuf/empty.upb.c \ + src/core/ext/upb-generated/google/protobuf/struct.upb.c \ + src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \ + src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \ + src/core/ext/upb-generated/google/rpc/status.upb.c \ src/core/lib/gpr/alloc.cc \ src/core/lib/gpr/atm.cc \ src/core/lib/gpr/cpu_iphone.cc \ @@ -945,6 +956,7 @@ LIBGPR_SRC = \ src/core/lib/gprpp/mpscq.cc \ src/core/lib/gprpp/stat_posix.cc \ src/core/lib/gprpp/stat_windows.cc \ + src/core/lib/gprpp/status_helper.cc \ src/core/lib/gprpp/thd_posix.cc \ src/core/lib/gprpp/thd_windows.cc \ src/core/lib/gprpp/time_util.cc \ @@ -1009,19 +1021,19 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) +$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libupb.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else -$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) +$(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGPR_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libupb.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.15 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) - $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.15 + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgpr.so.16 -o $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGPR_OBJS) $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so.16 $(Q) ln -sf $(SHARED_PREFIX)gpr$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgpr$(SHARED_VERSION_CORE).so endif endif @@ -1059,6 +1071,7 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \ src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \ src/core/ext/filters/client_channel/lb_policy/priority/priority.cc \ + src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc \ src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \ src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc \ src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \ @@ -1085,6 +1098,8 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc \ src/core/ext/filters/client_channel/resolver_registry.cc \ src/core/ext/filters/client_channel/resolver_result_parsing.cc \ + src/core/ext/filters/client_channel/retry_filter.cc \ + src/core/ext/filters/client_channel/retry_service_config.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/service_config.cc \ @@ -1094,6 +1109,8 @@ LIBGRPC_SRC = \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_idle/client_idle_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \ + src/core/ext/filters/fault_injection/fault_injection_filter.cc \ + src/core/ext/filters/fault_injection/service_config_parser.cc \ src/core/ext/filters/http/client/http_client_filter.cc \ src/core/ext/filters/http/client_authority_filter.cc \ src/core/ext/filters/http/http_filters_plugin.cc \ @@ -1139,9 +1156,11 @@ LIBGRPC_SRC = \ src/core/ext/transport/chttp2/transport/writing.cc \ src/core/ext/transport/inproc/inproc_plugin.cc \ src/core/ext/transport/inproc/inproc_transport.cc \ + src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c \ src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \ src/core/ext/upb-generated/envoy/annotations/resource.upb.c \ src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c \ + src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c \ src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c \ src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c \ src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c \ @@ -1166,12 +1185,16 @@ LIBGRPC_SRC = \ src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c \ src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c \ src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c \ + src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c \ + src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c \ src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c \ src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c \ src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c \ src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c \ src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c \ src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c \ + src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c \ + src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \ @@ -1186,11 +1209,14 @@ LIBGRPC_SRC = \ src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c \ src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c \ src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c \ + src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c \ + src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c \ + src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c \ src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c \ src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c \ @@ -1198,17 +1224,6 @@ LIBGRPC_SRC = \ src/core/ext/upb-generated/envoy/type/v3/percent.upb.c \ src/core/ext/upb-generated/envoy/type/v3/range.upb.c \ src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.c \ - src/core/ext/upb-generated/google/api/annotations.upb.c \ - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c \ - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c \ - src/core/ext/upb-generated/google/api/http.upb.c \ - src/core/ext/upb-generated/google/protobuf/any.upb.c \ - src/core/ext/upb-generated/google/protobuf/duration.upb.c \ - src/core/ext/upb-generated/google/protobuf/empty.upb.c \ - src/core/ext/upb-generated/google/protobuf/struct.upb.c \ - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \ - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \ - src/core/ext/upb-generated/google/rpc/status.upb.c \ src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c \ src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c \ src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c \ @@ -1228,9 +1243,11 @@ LIBGRPC_SRC = \ src/core/ext/upb-generated/xds/core/v3/resource.upb.c \ src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c \ src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c \ + src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c \ @@ -1255,11 +1272,15 @@ LIBGRPC_SRC = \ src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \ @@ -1274,11 +1295,14 @@ LIBGRPC_SRC = \ src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c \ @@ -1316,8 +1340,11 @@ LIBGRPC_SRC = \ src/core/ext/xds/xds_certificate_provider.cc \ src/core/ext/xds/xds_client.cc \ src/core/ext/xds/xds_client_stats.cc \ + src/core/ext/xds/xds_http_fault_filter.cc \ src/core/ext/xds/xds_http_filters.cc \ src/core/ext/xds/xds_server_config_fetcher.cc \ + src/core/lib/address_utils/parse_address.cc \ + src/core/lib/address_utils/sockaddr_utils.cc \ src/core/lib/avl/avl.cc \ src/core/lib/backoff/backoff.cc \ src/core/lib/channel/channel_args.cc \ @@ -1340,6 +1367,8 @@ LIBGRPC_SRC = \ src/core/lib/debug/stats.cc \ src/core/lib/debug/stats_data.cc \ src/core/lib/debug/trace.cc \ + src/core/lib/event_engine/slice_allocator.cc \ + src/core/lib/event_engine/sockaddr.cc \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/httpcli_security_connector.cc \ @@ -1385,8 +1414,6 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/parse_address.cc \ - src/core/lib/iomgr/poller/eventmanager_libuv.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -1400,7 +1427,6 @@ LIBGRPC_SRC = \ src/core/lib/iomgr/resolve_address_posix.cc \ src/core/lib/iomgr/resolve_address_windows.cc \ src/core/lib/iomgr/resource_quota.cc \ - src/core/lib/iomgr/sockaddr_utils.cc \ src/core/lib/iomgr/socket_factory_posix.cc \ src/core/lib/iomgr/socket_mutator.cc \ src/core/lib/iomgr/socket_utils_common_posix.cc \ @@ -1443,9 +1469,7 @@ LIBGRPC_SRC = \ src/core/lib/json/json_reader.cc \ src/core/lib/json/json_util.cc \ src/core/lib/json/json_writer.cc \ - src/core/lib/security/authorization/authorization_engine.cc \ - src/core/lib/security/authorization/evaluate_args.cc \ - src/core/lib/security/authorization/matchers.cc \ + src/core/lib/matchers/matchers.cc \ src/core/lib/security/context/security_context.cc \ src/core/lib/security/credentials/alts/alts_credentials.cc \ src/core/lib/security/credentials/alts/check_gcp_environment.cc \ @@ -1573,6 +1597,10 @@ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer_reader.h \ include/grpc/census.h \ include/grpc/compression.h \ + include/grpc/event_engine/channel_args.h \ + include/grpc/event_engine/event_engine.h \ + include/grpc/event_engine/port.h \ + include/grpc/event_engine/slice_allocator.h \ include/grpc/fork.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ @@ -1609,19 +1637,19 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(OPENSSL_DEP) +$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else -$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(OPENSSL_DEP) +$(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_DEP) $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.15 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.15 + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc.so.16 -o $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so.16 $(Q) ln -sf $(SHARED_PREFIX)grpc$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc$(SHARED_VERSION_CORE).so endif endif @@ -1645,17 +1673,7 @@ PUBLIC_HEADERS_C += \ LIBGRPC_CSHARP_EXT_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CSHARP_EXT_SRC)))) -ifeq ($(NO_SECURE),true) - -# You can't build secure libraries if you don't have OpenSSL. - -$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a: openssl_dep_error - -$(LIBDIR)/$(CONFIG)/$(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): openssl_dep_error - -else - -$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBGRPC_CSHARP_EXT_OBJS) +$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a: $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBGRPC_CSHARP_EXT_OBJS) $(E) "[AR] Creating $@" $(Q) mkdir -p `dirname $@` $(Q) rm -f $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.a @@ -1667,30 +1685,26 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(OPENSSL_DEP) +$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else -$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(OPENSSL_DEP) +$(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_CSHARP_EXT_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgrpc.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.15 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.15 + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_csharp_ext.so.16 -o $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_CSHARP_EXT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so.16 $(Q) ln -sf $(SHARED_PREFIX)grpc_csharp_ext$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext$(SHARED_VERSION_CORE).so endif endif -endif - -ifneq ($(NO_SECURE),true) ifneq ($(NO_DEPS),true) -include $(LIBGRPC_CSHARP_EXT_OBJS:.o=.dep) endif -endif # end of build recipe for library "grpc_csharp_ext" @@ -1741,6 +1755,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \ src/core/ext/filters/client_channel/resolver_registry.cc \ src/core/ext/filters/client_channel/resolver_result_parsing.cc \ + src/core/ext/filters/client_channel/retry_filter.cc \ + src/core/ext/filters/client_channel/retry_service_config.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/service_config.cc \ @@ -1750,6 +1766,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_idle/client_idle_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \ + src/core/ext/filters/fault_injection/fault_injection_filter.cc \ + src/core/ext/filters/fault_injection/service_config_parser.cc \ src/core/ext/filters/http/client/http_client_filter.cc \ src/core/ext/filters/http/client_authority_filter.cc \ src/core/ext/filters/http/http_filters_plugin.cc \ @@ -1793,21 +1811,12 @@ LIBGRPC_UNSECURE_SRC = \ src/core/ext/transport/chttp2/transport/writing.cc \ src/core/ext/transport/inproc/inproc_plugin.cc \ src/core/ext/transport/inproc/inproc_transport.cc \ - src/core/ext/upb-generated/google/api/annotations.upb.c \ - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c \ - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c \ - src/core/ext/upb-generated/google/api/http.upb.c \ - src/core/ext/upb-generated/google/protobuf/any.upb.c \ - src/core/ext/upb-generated/google/protobuf/duration.upb.c \ - src/core/ext/upb-generated/google/protobuf/empty.upb.c \ - src/core/ext/upb-generated/google/protobuf/struct.upb.c \ - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c \ - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c \ - src/core/ext/upb-generated/google/rpc/status.upb.c \ src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c \ src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c \ src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c \ src/core/ext/upb-generated/validate/validate.upb.c \ + src/core/lib/address_utils/parse_address.cc \ + src/core/lib/address_utils/sockaddr_utils.cc \ src/core/lib/avl/avl.cc \ src/core/lib/backoff/backoff.cc \ src/core/lib/channel/channel_args.cc \ @@ -1830,6 +1839,8 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/debug/stats.cc \ src/core/lib/debug/stats_data.cc \ src/core/lib/debug/trace.cc \ + src/core/lib/event_engine/slice_allocator.cc \ + src/core/lib/event_engine/sockaddr.cc \ src/core/lib/http/format_request.cc \ src/core/lib/http/httpcli.cc \ src/core/lib/http/parser.cc \ @@ -1874,8 +1885,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/parse_address.cc \ - src/core/lib/iomgr/poller/eventmanager_libuv.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -1889,7 +1898,6 @@ LIBGRPC_UNSECURE_SRC = \ src/core/lib/iomgr/resolve_address_posix.cc \ src/core/lib/iomgr/resolve_address_windows.cc \ src/core/lib/iomgr/resource_quota.cc \ - src/core/lib/iomgr/sockaddr_utils.cc \ src/core/lib/iomgr/socket_factory_posix.cc \ src/core/lib/iomgr/socket_mutator.cc \ src/core/lib/iomgr/socket_utils_common_posix.cc \ @@ -1980,6 +1988,10 @@ PUBLIC_HEADERS_C += \ include/grpc/byte_buffer_reader.h \ include/grpc/census.h \ include/grpc/compression.h \ + include/grpc/event_engine/channel_args.h \ + include/grpc/event_engine/event_engine.h \ + include/grpc/event_engine/port.h \ + include/grpc/event_engine/slice_allocator.h \ include/grpc/fork.h \ include/grpc/grpc.h \ include/grpc/grpc_posix.h \ @@ -2005,19 +2017,19 @@ endif ifeq ($(SYSTEM),MINGW32) -$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a +$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,--output-def=$(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).def -Wl,--out-implib=$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE)-dll.a -o $(LIBDIR)/$(CONFIG)/grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else -$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a +$(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBGRPC_UNSECURE_OBJS) $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(E) "[LD] Linking $@" $(Q) mkdir -p `dirname $@` ifeq ($(SYSTEM),Darwin) - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.15 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(LIBDIR)/$(CONFIG)/libupb.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) - $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.15 + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libgrpc_unsecure.so.16 -o $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBGRPC_UNSECURE_OBJS) $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libaddress_sorting.a $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so.16 $(Q) ln -sf $(SHARED_PREFIX)grpc_unsecure$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure$(SHARED_VERSION_CORE).so endif endif @@ -2137,7 +2149,6 @@ LIBBORINGSSL_SRC = \ third_party/boringssl-with-bazel/src/crypto/ex_data.c \ third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c \ third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c \ - third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c \ third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c \ third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c \ third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c \ @@ -2204,7 +2215,6 @@ LIBBORINGSSL_SRC = \ third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_lu.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c \ - third_party/boringssl-with-bazel/src/crypto/x509/x509_r2x.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c \ @@ -2269,6 +2279,7 @@ LIBBORINGSSL_SRC = \ third_party/boringssl-with-bazel/src/ssl/d1_srtp.cc \ third_party/boringssl-with-bazel/src/ssl/dtls_method.cc \ third_party/boringssl-with-bazel/src/ssl/dtls_record.cc \ + third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc \ third_party/boringssl-with-bazel/src/ssl/handoff.cc \ third_party/boringssl-with-bazel/src/ssl/handshake.cc \ third_party/boringssl-with-bazel/src/ssl/handshake_client.cc \ @@ -2378,8 +2389,6 @@ LIBUPB_SRC = \ third_party/upb/upb/decode.c \ third_party/upb/upb/def.c \ third_party/upb/upb/encode.c \ - third_party/upb/upb/json_decode.c \ - third_party/upb/upb/json_encode.c \ third_party/upb/upb/msg.c \ third_party/upb/upb/reflection.c \ third_party/upb/upb/table.c \ @@ -2415,8 +2424,8 @@ $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE): $(LIBUPB_OB ifeq ($(SYSTEM),Darwin) $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -install_name $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) -dynamiclib -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) else - $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.15 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) - $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.15 + $(Q) $(LDXX) $(LDFLAGS) -L$(LIBDIR)/$(CONFIG) -shared -Wl,-soname,libupb.so.16 -o $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBUPB_OBJS) $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS) $(LDLIBS) + $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so.16 $(Q) ln -sf $(SHARED_PREFIX)upb$(SHARED_VERSION_CORE).$(SHARED_EXT_CORE) $(LIBDIR)/$(CONFIG)/libupb$(SHARED_VERSION_CORE).so endif endif @@ -2573,6 +2582,7 @@ LIBGRPC_ABSEIL_SRC = \ third_party/abseil-cpp/absl/debugging/symbolize.cc \ third_party/abseil-cpp/absl/hash/internal/city.cc \ third_party/abseil-cpp/absl/hash/internal/hash.cc \ + third_party/abseil-cpp/absl/hash/internal/wyhash.cc \ third_party/abseil-cpp/absl/numeric/int128.cc \ third_party/abseil-cpp/absl/status/status.cc \ third_party/abseil-cpp/absl/status/status_payload_printer.cc \ @@ -2583,6 +2593,8 @@ LIBGRPC_ABSEIL_SRC = \ third_party/abseil-cpp/absl/strings/escaping.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \ + third_party/abseil-cpp/absl/strings/internal/cord_internal.cc \ + third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc \ third_party/abseil-cpp/absl/strings/internal/escaping.cc \ third_party/abseil-cpp/absl/strings/internal/memutil.cc \ third_party/abseil-cpp/absl/strings/internal/ostringstream.cc \ @@ -2657,6 +2669,7 @@ ifneq ($(OPENSSL_DEP),) # installing headers to their final destination on the drive. We need this # otherwise parallel compilation will fail if a source is compiled first. src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc: $(OPENSSL_DEP) +src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc: $(OPENSSL_DEP) src/core/ext/filters/client_channel/lb_policy/xds/cds.cc: $(OPENSSL_DEP) src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc: $(OPENSSL_DEP) src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc: $(OPENSSL_DEP) @@ -2665,9 +2678,11 @@ src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc: src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc: $(OPENSSL_DEP) src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc: $(OPENSSL_DEP) src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/annotations/resource.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c: $(OPENSSL_DEP) @@ -2692,12 +2707,16 @@ src/core/ext/upb-generated/envoy/config/listener/v3/api_listener.upb.c: $(OPENSS src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c: $(OPENSSL_DEP) @@ -2712,11 +2731,14 @@ src/core/ext/upb-generated/envoy/service/listener/v3/lds.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c: $(OPENSSL_DEP) +src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c: $(OPENSSL_DEP) @@ -2739,9 +2761,11 @@ src/core/ext/upb-generated/xds/core/v3/context_params.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/xds/core/v3/resource.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c: $(OPENSSL_DEP) src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c: $(OPENSSL_DEP) @@ -2766,11 +2790,15 @@ src/core/ext/upbdefs-generated/envoy/config/listener/v3/api_listener.upbdefs.c: src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c: $(OPENSSL_DEP) @@ -2785,11 +2813,14 @@ src/core/ext/upbdefs-generated/envoy/service/listener/v3/lds.upbdefs.c: $(OPENSS src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c: $(OPENSSL_DEP) +src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c: $(OPENSSL_DEP) src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c: $(OPENSSL_DEP) @@ -2827,12 +2858,11 @@ src/core/ext/xds/xds_bootstrap.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_certificate_provider.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_client.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_client_stats.cc: $(OPENSSL_DEP) +src/core/ext/xds/xds_http_fault_filter.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_http_filters.cc: $(OPENSSL_DEP) src/core/ext/xds/xds_server_config_fetcher.cc: $(OPENSSL_DEP) src/core/lib/http/httpcli_security_connector.cc: $(OPENSSL_DEP) -src/core/lib/security/authorization/authorization_engine.cc: $(OPENSSL_DEP) -src/core/lib/security/authorization/evaluate_args.cc: $(OPENSSL_DEP) -src/core/lib/security/authorization/matchers.cc: $(OPENSSL_DEP) +src/core/lib/matchers/matchers.cc: $(OPENSSL_DEP) src/core/lib/security/context/security_context.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/alts/alts_credentials.cc: $(OPENSSL_DEP) src/core/lib/security/credentials/alts/check_gcp_environment.cc: $(OPENSSL_DEP) @@ -2914,7 +2944,6 @@ src/core/tsi/ssl/session_cache/ssl_session_openssl.cc: $(OPENSSL_DEP) src/core/tsi/ssl_transport_security.cc: $(OPENSSL_DEP) src/core/tsi/transport_security.cc: $(OPENSSL_DEP) src/core/tsi/transport_security_grpc.cc: $(OPENSSL_DEP) -src/csharp/ext/grpc_csharp_ext.c: $(OPENSSL_DEP) endif .PHONY: all strip tools dep_error openssl_dep_error openssl_dep_message git_update stop buildtests buildtests_c buildtests_cxx test test_c test_cxx install install_c install_cxx install_csharp install-static install-certs strip strip-shared strip-static strip_c strip-shared_c strip-static_c strip_cxx strip-shared_cxx strip-static_cxx dep_c dep_cxx bins_dep_c bins_dep_cxx clean diff --git a/PYTHON-MANIFEST.in b/PYTHON-MANIFEST.in index 391de4e907e..890a2faacb5 100644 --- a/PYTHON-MANIFEST.in +++ b/PYTHON-MANIFEST.in @@ -10,6 +10,7 @@ graft third_party/boringssl-with-bazel graft third_party/cares graft third_party/re2 graft third_party/upb +graft third_party/xxhash graft third_party/zlib include src/python/grpcio/_parallel_compile_patch.py include src/python/grpcio/_spawn_patch.py diff --git a/Package.swift b/Package.swift index c97d43f61c4..66e4a740765 100644 --- a/Package.swift +++ b/Package.swift @@ -40,28 +40,36 @@ let package = Package( ], path: ".", exclude: [ - "src/core/ext/filters/load_reporting/", "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc", "src/core/ext/filters/client_channel/xds/xds_channel.cc", + "src/core/ext/filters/load_reporting/", "src/core/ext/transport/cronet/", "src/core/ext/upb-generated/third_party/", + "src/core/ext/upb-generated/src/proto/grpc/auth/", "src/core/ext/upbdefs-generated/envoy/config/rbac/", "src/core/ext/upbdefs-generated/google/api/expr/", "src/core/ext/upbdefs-generated/src/", "src/core/ext/upbdefs-generated/third_party/", "src/core/ext/upbdefs-generated/udpa/data/", + "src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h", + "src/core/ext/xds/google_mesh_ca_certificate_provider_factory.cc", "src/core/lib/surface/init_unsecure.cc", - "src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h", - "src/core/lib/security/authorization/mock_cel/cel_expression.h", - "src/core/lib/security/authorization/mock_cel/evaluator_core.h", - "src/core/lib/security/authorization/mock_cel/flat_expr_builder.h", - "src/core/lib/security/authorization/mock_cel/statusor.h", + "src/core/lib/security/authorization/", "src/core/plugin_registry/grpc_unsecure_plugin_registry.cc", "third_party/re2/re2/testing/", "third_party/re2/re2/fuzzing/", "third_party/re2/util/benchmark.cc", "third_party/re2/util/test.cc", "third_party/re2/util/fuzz.cc", + "third_party/upb/upb/sink.c", + "third_party/upb/upb/json_decode.c", + "third_party/upb/upb/json_encode.c", + "third_party/upb/upb/handlers.h", + "third_party/upb/upb/sink.h", + "third_party/upb/upb/json_encode.h", + "third_party/upb/upb/json_decode.h", + "third_party/upb/upb/handlers-inl.h", + "third_party/upb/upb/handlers.c", "third_party/upb/upb/bindings/", "third_party/upb/upb/json/", "third_party/upb/upb/pb/", @@ -78,6 +86,8 @@ let package = Package( "third_party/re2/re2/", "third_party/re2/util/", "third_party/upb/upb/", + "third_party/upb/third_party/wyhash/wyhash.h", + "third_party/xxhash/xxhash.h", ], publicHeadersPath: "spm-core-include", cSettings: [ @@ -85,10 +95,15 @@ let package = Package( .headerSearchPath("include/"), .headerSearchPath("third_party/re2/"), .headerSearchPath("third_party/upb/"), + .headerSearchPath("third_party/xxhash/"), .headerSearchPath("src/core/ext/upb-generated/"), .headerSearchPath("src/core/ext/upbdefs-generated/"), .define("GRPC_ARES", to: "0"), .unsafeFlags(["-Wno-module-import-in-extern-c"]), + ], + linkerSettings: [ + .linkedFramework("CoreFoundation"), + .linkedLibrary("z"), ] ), .target( @@ -100,12 +115,18 @@ let package = Package( path: ".", exclude: [ "src/cpp/client/cronet_credentials.cc", + "src/cpp/client/channel_test_peer.cc", + "src/cpp/common/alts_util.cc", + "src/cpp/common/alts_context.cc", "src/cpp/common/insecure_create_auth_context.cc", - "src/cpp/ext/", + "src/cpp/server/admin/", "src/cpp/server/channelz/", + "src/cpp/server/csds/", "src/cpp/server/load_reporter/", + "src/cpp/ext/", "src/cpp/util/core_stats.cc", "src/cpp/util/core_stats.h", + "src/cpp/util/error_details.cc", ], sources: [ "src/cpp/", diff --git a/bazel/grpc_build_system.bzl b/bazel/grpc_build_system.bzl index e75d8b15477..85ec2d6b278 100644 --- a/bazel/grpc_build_system.bzl +++ b/bazel/grpc_build_system.bzl @@ -49,6 +49,8 @@ def _get_external_deps(external_deps): for dep in external_deps: if dep == "address_sorting": ret += ["//third_party/address_sorting"] + elif dep == "xxhash": + ret += ["//third_party/xxhash"] elif dep == "cares": ret += select({ "//:grpc_no_ares": [], @@ -178,8 +180,8 @@ def ios_cc_test( deps = ios_test_deps, ) -def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = None, tags = [], exec_compatible_with = [], exec_properties = {}, shard_count = None, flaky = None): - copts = if_mac(["-DGRPC_CFSTREAM"]) +def grpc_cc_test(name, srcs = [], deps = [], external_deps = [], args = [], data = [], uses_polling = True, language = "C++", size = "medium", timeout = None, tags = [], exec_compatible_with = [], exec_properties = {}, shard_count = None, flaky = None, copts = []): + copts = copts + if_mac(["-DGRPC_CFSTREAM"]) if language.upper() == "C": copts = copts + if_not_windows(["-std=c99"]) diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl index e9e9a38ce47..a463d01bfc1 100644 --- a/bazel/grpc_deps.bzl +++ b/bazel/grpc_deps.bzl @@ -121,6 +121,11 @@ def grpc_deps(): actual = "@io_opencensus_cpp//opencensus/trace:context_util", ) + native.bind( + name = "opencensus-trace-propagation", + actual = "@io_opencensus_cpp//opencensus/trace:grpc_trace_bin", + ) + native.bind( name = "opencensus-stats", actual = "@io_opencensus_cpp//opencensus/stats:stats", @@ -151,11 +156,11 @@ def grpc_deps(): name = "boringssl", # Use github mirror instead of https://boringssl.googlesource.com/boringssl # to obtain a boringssl archive with consistent sha256 - sha256 = "269c89eb60d3f3fcd5a0a755d1e28ffa65d423bc3c0e9562e2d666f5464680d2", - strip_prefix = "boringssl-1a7359455220f7010def8c63f7c7e041ce6707c6", + sha256 = "f8616dff15cb8aad6705af53c7caf7a5f1103b6aaf59c76b55995e179d47f89c", + strip_prefix = "boringssl-688fc5cf5428868679d2ae1072cad81055752068", urls = [ - "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/1a7359455220f7010def8c63f7c7e041ce6707c6.tar.gz", - "https://github.com/google/boringssl/archive/1a7359455220f7010def8c63f7c7e041ce6707c6.tar.gz", + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/boringssl/archive/688fc5cf5428868679d2ae1072cad81055752068.tar.gz", + "https://github.com/google/boringssl/archive/688fc5cf5428868679d2ae1072cad81055752068.tar.gz", ], ) @@ -174,11 +179,11 @@ def grpc_deps(): if "com_google_protobuf" not in native.existing_rules(): http_archive( name = "com_google_protobuf", - sha256 = "09709ea1a25dc2f02e281e11f559dd979139ba2a1ddb24c489ea6bea9e3ad8bc", - strip_prefix = "protobuf-d7e943b8d2bc444a8c770644e73d090b486f8b37", + sha256 = "cf63d46ef743f4c30b0e36a562caf83cabed3f10e6ca49eb476913c4655394d5", + strip_prefix = "protobuf-436bd7880e458532901c58f4d9d1ea23fa7edd52", urls = [ - "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/protobuf/archive/d7e943b8d2bc444a8c770644e73d090b486f8b37.tar.gz", - "https://github.com/google/protobuf/archive/d7e943b8d2bc444a8c770644e73d090b486f8b37.tar.gz", + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/protobuf/archive/436bd7880e458532901c58f4d9d1ea23fa7edd52.tar.gz", + "https://github.com/google/protobuf/archive/436bd7880e458532901c58f4d9d1ea23fa7edd52.tar.gz", ], patches = ["@com_github_grpc_grpc//third_party:protobuf.patch"], patch_args = ["-p1"], @@ -211,11 +216,11 @@ def grpc_deps(): if "com_github_google_benchmark" not in native.existing_rules(): http_archive( name = "com_github_google_benchmark", - sha256 = "f68aec93154d010324c05bcd8c5cc53468b87af88d87acb5ddcfaa1bba044837", - strip_prefix = "benchmark-090faecb454fbd6e6e17a75ef8146acb037118d4", + sha256 = "daa4a97e0547d76de300e325a49177b199f3689ce5a35e25d47696f7cb050f86", + strip_prefix = "benchmark-73d4d5e8d6d449fc8663765a42aa8aeeee844489", urls = [ - "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz", - "https://github.com/google/benchmark/archive/090faecb454fbd6e6e17a75ef8146acb037118d4.tar.gz", + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/google/benchmark/archive/73d4d5e8d6d449fc8663765a42aa8aeeee844489.tar.gz", + "https://github.com/google/benchmark/archive/73d4d5e8d6d449fc8663765a42aa8aeeee844489.tar.gz", ], ) @@ -245,11 +250,11 @@ def grpc_deps(): if "com_google_absl" not in native.existing_rules(): http_archive( name = "com_google_absl", - sha256 = "62c27e7a633e965a2f40ff16b487c3b778eae440bab64cad83b34ef1cbe3aa93", - strip_prefix = "abseil-cpp-6f9d96a1f41439ac172ee2ef7ccd8edf0e5d068c", + sha256 = "35f22ef5cb286f09954b7cc4c85b5a3f6221c9d4df6b8c4a1e9d399555b366ee", + strip_prefix = "abseil-cpp-997aaf3a28308eba1b9156aa35ab7bca9688e9f6", urls = [ - "https://storage.googleapis.com/grpc-bazel-mirror/github.com/abseil/abseil-cpp/archive/6f9d96a1f41439ac172ee2ef7ccd8edf0e5d068c.tar.gz", - "https://github.com/abseil/abseil-cpp/archive/6f9d96a1f41439ac172ee2ef7ccd8edf0e5d068c.tar.gz", + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/abseil/abseil-cpp/archive/997aaf3a28308eba1b9156aa35ab7bca9688e9f6.tar.gz", + "https://github.com/abseil/abseil-cpp/archive/997aaf3a28308eba1b9156aa35ab7bca9688e9f6.tar.gz", ], ) @@ -314,6 +319,7 @@ def grpc_deps(): sha256 = "4423bef0ab15053dca0f723cbdaf4b48ab145e9d8158f02e33028c66fb1d20e0", strip_prefix = "data-plane-api-18b54850c9b7ba29a4ab67cbd7ed7eab7b0bbdb2", urls = [ + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/envoyproxy/data-plane-api/archive/18b54850c9b7ba29a4ab67cbd7ed7eab7b0bbdb2.tar.gz", "https://github.com/envoyproxy/data-plane-api/archive/18b54850c9b7ba29a4ab67cbd7ed7eab7b0bbdb2.tar.gz", ], ) @@ -367,6 +373,7 @@ def grpc_deps(): sha256 = "a45019af4d3290f02eaeb1ce10990166978c807cb33a9692141a076ba46d1405", strip_prefix = "googleapis-82944da21578a53b74e547774cf62ed31a05b841", urls = [ + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/googleapis/googleapis/archive/82944da21578a53b74e547774cf62ed31a05b841.tar.gz", "https://github.com/googleapis/googleapis/archive/82944da21578a53b74e547774cf62ed31a05b841.tar.gz", ], ) @@ -377,6 +384,7 @@ def grpc_deps(): sha256 = "d987004a72697334a095bbaa18d615804a28280201a50ed6c234c40ccc41e493", strip_prefix = "bazel-gazelle-0.19.1", urls = [ + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/bazelbuild/bazel-gazelle/archive/v0.19.1.tar.gz", "https://github.com/bazelbuild/bazel-gazelle/archive/v0.19.1.tar.gz", ], ) @@ -386,7 +394,10 @@ def grpc_deps(): name = "opencensus_proto", sha256 = "b7e13f0b4259e80c3070b583c2f39e53153085a6918718b1c710caf7037572b0", strip_prefix = "opencensus-proto-0.3.0/src", - urls = ["https://github.com/census-instrumentation/opencensus-proto/archive/v0.3.0.tar.gz"], + urls = [ + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/census-instrumentation/opencensus-proto/archive/v0.3.0.tar.gz", + "https://github.com/census-instrumentation/opencensus-proto/archive/v0.3.0.tar.gz", + ], ) if "com_envoyproxy_protoc_gen_validate" not in native.existing_rules(): @@ -394,7 +405,10 @@ def grpc_deps(): name = "com_envoyproxy_protoc_gen_validate", sha256 = "e368733c9fb7f8489591ffaf269170d7658cc0cd1ee322b601512b769446d3c8", strip_prefix = "protoc-gen-validate-278964a8052f96a2f514add0298098f63fb7f47f", - urls = ["https://github.com/envoyproxy/protoc-gen-validate/archive/278964a8052f96a2f514add0298098f63fb7f47f.tar.gz"], + urls = [ + "https://storage.googleapis.com/grpc-bazel-mirror/github.com/envoyproxy/protoc-gen-validate/archive/278964a8052f96a2f514add0298098f63fb7f47f.tar.gz", + "https://github.com/envoyproxy/protoc-gen-validate/archive/278964a8052f96a2f514add0298098f63fb7f47f.tar.gz", + ], ) grpc_python_deps() diff --git a/build_autogenerated.yaml b/build_autogenerated.yaml index cd1ab85cdc6..83140925da5 100644 --- a/build_autogenerated.yaml +++ b/build_autogenerated.yaml @@ -12,7 +12,6 @@ libs: - third_party/address_sorting/address_sorting_posix.c - third_party/address_sorting/address_sorting_windows.c deps: [] - secure: false - name: end2end_nosec_tests build: private language: c @@ -25,6 +24,7 @@ libs: - test/core/end2end/fixtures/local_util.h - test/core/end2end/fixtures/proxy.h - test/core/end2end/tests/cancel_test_helpers.h + - test/core/util/test_lb_policies.h src: - test/core/end2end/cq_verifier.cc - test/core/end2end/data/client_certs.cc @@ -84,10 +84,12 @@ libs: - test/core/end2end/tests/request_with_payload.cc - test/core/end2end/tests/resource_quota_server.cc - test/core/end2end/tests/retry.cc + - test/core/end2end/tests/retry_cancel_during_delay.cc - test/core/end2end/tests/retry_cancellation.cc - test/core/end2end/tests/retry_disabled.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc + - test/core/end2end/tests/retry_lb_drop.cc - test/core/end2end/tests/retry_non_retriable_status.cc - test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc - test/core/end2end/tests/retry_recv_initial_metadata.cc @@ -115,13 +117,9 @@ libs: - test/core/end2end/tests/workaround_cronet_compression.cc - test/core/end2end/tests/write_buffering.cc - test/core/end2end/tests/write_buffering_at_end.cc + - test/core/util/test_lb_policies.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - secure: false - name: end2end_tests build: private language: c @@ -134,6 +132,7 @@ libs: - test/core/end2end/fixtures/local_util.h - test/core/end2end/fixtures/proxy.h - test/core/end2end/tests/cancel_test_helpers.h + - test/core/util/test_lb_policies.h src: - test/core/end2end/cq_verifier.cc - test/core/end2end/data/client_certs.cc @@ -194,10 +193,12 @@ libs: - test/core/end2end/tests/request_with_payload.cc - test/core/end2end/tests/resource_quota_server.cc - test/core/end2end/tests/retry.cc + - test/core/end2end/tests/retry_cancel_during_delay.cc - test/core/end2end/tests/retry_cancellation.cc - test/core/end2end/tests/retry_disabled.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc - test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc + - test/core/end2end/tests/retry_lb_drop.cc - test/core/end2end/tests/retry_non_retriable_status.cc - test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc - test/core/end2end/tests/retry_recv_initial_metadata.cc @@ -225,13 +226,9 @@ libs: - test/core/end2end/tests/workaround_cronet_compression.cc - test/core/end2end/tests/write_buffering.cc - test/core/end2end/tests/write_buffering_at_end.cc + - test/core/util/test_lb_policies.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - secure: true - name: gpr build: all language: c @@ -278,6 +275,17 @@ libs: - include/grpc/support/thd_id.h - include/grpc/support/time.h headers: + - src/core/ext/upb-generated/google/api/annotations.upb.h + - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h + - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h + - src/core/ext/upb-generated/google/api/http.upb.h + - src/core/ext/upb-generated/google/protobuf/any.upb.h + - src/core/ext/upb-generated/google/protobuf/duration.upb.h + - src/core/ext/upb-generated/google/protobuf/empty.upb.h + - src/core/ext/upb-generated/google/protobuf/struct.upb.h + - src/core/ext/upb-generated/google/protobuf/timestamp.upb.h + - src/core/ext/upb-generated/google/protobuf/wrappers.upb.h + - src/core/ext/upb-generated/google/rpc/status.upb.h - src/core/lib/gpr/alloc.h - src/core/lib/gpr/arena.h - src/core/lib/gpr/env.h @@ -295,6 +303,7 @@ libs: - src/core/lib/gpr/useful.h - src/core/lib/gprpp/arena.h - src/core/lib/gprpp/atomic.h + - src/core/lib/gprpp/debug_location.h - src/core/lib/gprpp/examine_stack.h - src/core/lib/gprpp/fork.h - src/core/lib/gprpp/global_config.h @@ -306,11 +315,23 @@ libs: - src/core/lib/gprpp/memory.h - src/core/lib/gprpp/mpscq.h - src/core/lib/gprpp/stat.h + - src/core/lib/gprpp/status_helper.h - src/core/lib/gprpp/sync.h - src/core/lib/gprpp/thd.h - src/core/lib/gprpp/time_util.h - src/core/lib/profiling/timers.h src: + - src/core/ext/upb-generated/google/api/annotations.upb.c + - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c + - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c + - src/core/ext/upb-generated/google/api/http.upb.c + - src/core/ext/upb-generated/google/protobuf/any.upb.c + - src/core/ext/upb-generated/google/protobuf/duration.upb.c + - src/core/ext/upb-generated/google/protobuf/empty.upb.c + - src/core/ext/upb-generated/google/protobuf/struct.upb.c + - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c + - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c + - src/core/ext/upb-generated/google/rpc/status.upb.c - src/core/lib/gpr/alloc.cc - src/core/lib/gpr/atm.cc - src/core/lib/gpr/cpu_iphone.cc @@ -351,21 +372,22 @@ libs: - src/core/lib/gprpp/mpscq.cc - src/core/lib/gprpp/stat_posix.cc - src/core/lib/gprpp/stat_windows.cc + - src/core/lib/gprpp/status_helper.cc - src/core/lib/gprpp/thd_posix.cc - src/core/lib/gprpp/thd_windows.cc - src/core/lib/gprpp/time_util.cc - src/core/lib/profiling/basic_timers.cc - src/core/lib/profiling/stap_timers.cc deps: - - absl/types:optional - - absl/time:time - - absl/synchronization:synchronization - - absl/strings:strings - - absl/strings:str_format - - absl/status:status - - absl/memory:memory - absl/base:base - secure: false + - absl/memory:memory + - absl/status:status + - absl/strings:str_format + - absl/strings:strings + - absl/synchronization:synchronization + - absl/time:time + - absl/types:optional + - upb - name: grpc build: all language: c @@ -374,6 +396,10 @@ libs: - include/grpc/byte_buffer_reader.h - include/grpc/census.h - include/grpc/compression.h + - include/grpc/event_engine/channel_args.h + - include/grpc/event_engine/event_engine.h + - include/grpc/event_engine/port.h + - include/grpc/event_engine/slice_allocator.h - include/grpc/fork.h - include/grpc/grpc.h - include/grpc/grpc_posix.h @@ -406,6 +432,7 @@ libs: - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h + - src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h - src/core/ext/filters/client_channel/lb_policy/subchannel_list.h - src/core/ext/filters/client_channel/lb_policy/xds/xds.h - src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h @@ -423,6 +450,8 @@ libs: - src/core/ext/filters/client_channel/resolver_factory.h - src/core/ext/filters/client_channel/resolver_registry.h - src/core/ext/filters/client_channel/resolver_result_parsing.h + - src/core/ext/filters/client_channel/retry_filter.h + - src/core/ext/filters/client_channel/retry_service_config.h - src/core/ext/filters/client_channel/retry_throttle.h - src/core/ext/filters/client_channel/server_address.h - src/core/ext/filters/client_channel/service_config.h @@ -432,6 +461,8 @@ libs: - src/core/ext/filters/client_channel/subchannel_interface.h - src/core/ext/filters/client_channel/subchannel_pool_interface.h - src/core/ext/filters/deadline/deadline_filter.h + - src/core/ext/filters/fault_injection/fault_injection_filter.h + - src/core/ext/filters/fault_injection/service_config_parser.h - src/core/ext/filters/http/client/http_client_filter.h - src/core/ext/filters/http/client_authority_filter.h - src/core/ext/filters/http/message_compress/message_compress_filter.h @@ -467,9 +498,11 @@ libs: - src/core/ext/transport/chttp2/transport/stream_map.h - src/core/ext/transport/chttp2/transport/varint.h - src/core/ext/transport/inproc/inproc_transport.h + - src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h - src/core/ext/upb-generated/envoy/annotations/resource.upb.h - src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h + - src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h - src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h - src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h - src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.h @@ -494,12 +527,16 @@ libs: - src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h - src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h - src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h + - src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h + - src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h - src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h - src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h - src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h - src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h - src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h - src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h + - src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h + - src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h - src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h - src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h @@ -514,11 +551,14 @@ libs: - src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.h - src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h - src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h + - src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h - src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h + - src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h - src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h - src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.h - src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h - src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h + - src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h - src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h - src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.h - src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.h @@ -526,17 +566,6 @@ libs: - src/core/ext/upb-generated/envoy/type/v3/percent.upb.h - src/core/ext/upb-generated/envoy/type/v3/range.upb.h - src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.h - - src/core/ext/upb-generated/google/api/annotations.upb.h - - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h - - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h - - src/core/ext/upb-generated/google/api/http.upb.h - - src/core/ext/upb-generated/google/protobuf/any.upb.h - - src/core/ext/upb-generated/google/protobuf/duration.upb.h - - src/core/ext/upb-generated/google/protobuf/empty.upb.h - - src/core/ext/upb-generated/google/protobuf/struct.upb.h - - src/core/ext/upb-generated/google/protobuf/timestamp.upb.h - - src/core/ext/upb-generated/google/protobuf/wrappers.upb.h - - src/core/ext/upb-generated/google/rpc/status.upb.h - src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.h - src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.h - src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.h @@ -556,9 +585,11 @@ libs: - src/core/ext/upb-generated/xds/core/v3/resource.upb.h - src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h - src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h + - src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h - src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h - src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.h @@ -583,11 +614,15 @@ libs: - src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h - src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h - src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h - src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h - src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h - src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h @@ -602,11 +637,14 @@ libs: - src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.h - src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h - src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h + - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.h - src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.h @@ -646,7 +684,10 @@ libs: - src/core/ext/xds/xds_channel_args.h - src/core/ext/xds/xds_client.h - src/core/ext/xds/xds_client_stats.h + - src/core/ext/xds/xds_http_fault_filter.h - src/core/ext/xds/xds_http_filters.h + - src/core/lib/address_utils/parse_address.h + - src/core/lib/address_utils/sockaddr_utils.h - src/core/lib/avl/avl.h - src/core/lib/backoff/backoff.h - src/core/lib/channel/channel_args.h @@ -672,7 +713,6 @@ libs: - src/core/lib/debug/stats_data.h - src/core/lib/debug/trace.h - src/core/lib/gprpp/atomic.h - - src/core/lib/gprpp/debug_location.h - src/core/lib/gprpp/dual_ref_counted.h - src/core/lib/gprpp/orphanable.h - src/core/lib/gprpp/ref_counted.h @@ -713,8 +753,6 @@ libs: - src/core/lib/iomgr/load_file.h - src/core/lib/iomgr/lockfree_event.h - src/core/lib/iomgr/nameser.h - - src/core/lib/iomgr/parse_address.h - - src/core/lib/iomgr/poller/eventmanager_libuv.h - src/core/lib/iomgr/polling_entity.h - src/core/lib/iomgr/pollset.h - src/core/lib/iomgr/pollset_custom.h @@ -731,7 +769,6 @@ libs: - src/core/lib/iomgr/sockaddr.h - src/core/lib/iomgr/sockaddr_custom.h - src/core/lib/iomgr/sockaddr_posix.h - - src/core/lib/iomgr/sockaddr_utils.h - src/core/lib/iomgr/sockaddr_windows.h - src/core/lib/iomgr/socket_factory_posix.h - src/core/lib/iomgr/socket_mutator.h @@ -759,15 +796,7 @@ libs: - src/core/lib/iomgr/work_serializer.h - src/core/lib/json/json.h - src/core/lib/json/json_util.h - - src/core/lib/security/authorization/authorization_engine.h - - src/core/lib/security/authorization/evaluate_args.h - - src/core/lib/security/authorization/matchers.h - - src/core/lib/security/authorization/mock_cel/activation.h - - src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h - - src/core/lib/security/authorization/mock_cel/cel_expression.h - - src/core/lib/security/authorization/mock_cel/cel_value.h - - src/core/lib/security/authorization/mock_cel/evaluator_core.h - - src/core/lib/security/authorization/mock_cel/flat_expr_builder.h + - src/core/lib/matchers/matchers.h - src/core/lib/security/context/security_context.h - src/core/lib/security/credentials/alts/alts_credentials.h - src/core/lib/security/credentials/alts/check_gcp_environment.h @@ -872,6 +901,7 @@ libs: - src/core/tsi/transport_security.h - src/core/tsi/transport_security_grpc.h - src/core/tsi/transport_security_interface.h + - third_party/xxhash/xxhash.h src: - src/core/ext/filters/census/grpc_context.cc - src/core/ext/filters/client_channel/backend_metric.cc @@ -898,6 +928,7 @@ libs: - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc - src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc - src/core/ext/filters/client_channel/lb_policy/priority/priority.cc + - src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc - src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc - src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc - src/core/ext/filters/client_channel/lb_policy/xds/cds.cc @@ -924,6 +955,8 @@ libs: - src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc - src/core/ext/filters/client_channel/resolver_registry.cc - src/core/ext/filters/client_channel/resolver_result_parsing.cc + - src/core/ext/filters/client_channel/retry_filter.cc + - src/core/ext/filters/client_channel/retry_service_config.cc - src/core/ext/filters/client_channel/retry_throttle.cc - src/core/ext/filters/client_channel/server_address.cc - src/core/ext/filters/client_channel/service_config.cc @@ -933,6 +966,8 @@ libs: - src/core/ext/filters/client_channel/subchannel_pool_interface.cc - src/core/ext/filters/client_idle/client_idle_filter.cc - src/core/ext/filters/deadline/deadline_filter.cc + - src/core/ext/filters/fault_injection/fault_injection_filter.cc + - src/core/ext/filters/fault_injection/service_config_parser.cc - src/core/ext/filters/http/client/http_client_filter.cc - src/core/ext/filters/http/client_authority_filter.cc - src/core/ext/filters/http/http_filters_plugin.cc @@ -978,9 +1013,11 @@ libs: - src/core/ext/transport/chttp2/transport/writing.cc - src/core/ext/transport/inproc/inproc_plugin.cc - src/core/ext/transport/inproc/inproc_transport.cc + - src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c - src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c - src/core/ext/upb-generated/envoy/annotations/resource.upb.c - src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c + - src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c - src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c - src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c - src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c @@ -1005,12 +1042,16 @@ libs: - src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c - src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c - src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c + - src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c + - src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c - src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c - src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c - src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c - src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c - src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c - src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c + - src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c + - src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c - src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c - src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c - src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c @@ -1025,11 +1066,14 @@ libs: - src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c - src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c - src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c + - src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c - src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c + - src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c - src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c - src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c - src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c - src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c + - src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c - src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c - src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c - src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c @@ -1037,17 +1081,6 @@ libs: - src/core/ext/upb-generated/envoy/type/v3/percent.upb.c - src/core/ext/upb-generated/envoy/type/v3/range.upb.c - src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.c - - src/core/ext/upb-generated/google/api/annotations.upb.c - - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c - - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c - - src/core/ext/upb-generated/google/api/http.upb.c - - src/core/ext/upb-generated/google/protobuf/any.upb.c - - src/core/ext/upb-generated/google/protobuf/duration.upb.c - - src/core/ext/upb-generated/google/protobuf/empty.upb.c - - src/core/ext/upb-generated/google/protobuf/struct.upb.c - - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c - - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c - - src/core/ext/upb-generated/google/rpc/status.upb.c - src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c - src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c - src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c @@ -1067,9 +1100,11 @@ libs: - src/core/ext/upb-generated/xds/core/v3/resource.upb.c - src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c - src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c + - src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c - src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c - src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c @@ -1094,11 +1129,15 @@ libs: - src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c - src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c - src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c - src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c - src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c - src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c @@ -1113,11 +1152,14 @@ libs: - src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c - src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c - src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c + - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c - src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c @@ -1155,8 +1197,11 @@ libs: - src/core/ext/xds/xds_certificate_provider.cc - src/core/ext/xds/xds_client.cc - src/core/ext/xds/xds_client_stats.cc + - src/core/ext/xds/xds_http_fault_filter.cc - src/core/ext/xds/xds_http_filters.cc - src/core/ext/xds/xds_server_config_fetcher.cc + - src/core/lib/address_utils/parse_address.cc + - src/core/lib/address_utils/sockaddr_utils.cc - src/core/lib/avl/avl.cc - src/core/lib/backoff/backoff.cc - src/core/lib/channel/channel_args.cc @@ -1179,6 +1224,8 @@ libs: - src/core/lib/debug/stats.cc - src/core/lib/debug/stats_data.cc - src/core/lib/debug/trace.cc + - src/core/lib/event_engine/slice_allocator.cc + - src/core/lib/event_engine/sockaddr.cc - src/core/lib/http/format_request.cc - src/core/lib/http/httpcli.cc - src/core/lib/http/httpcli_security_connector.cc @@ -1224,8 +1271,6 @@ libs: - src/core/lib/iomgr/is_epollexclusive_available.cc - src/core/lib/iomgr/load_file.cc - src/core/lib/iomgr/lockfree_event.cc - - src/core/lib/iomgr/parse_address.cc - - src/core/lib/iomgr/poller/eventmanager_libuv.cc - src/core/lib/iomgr/polling_entity.cc - src/core/lib/iomgr/pollset.cc - src/core/lib/iomgr/pollset_custom.cc @@ -1239,7 +1284,6 @@ libs: - src/core/lib/iomgr/resolve_address_posix.cc - src/core/lib/iomgr/resolve_address_windows.cc - src/core/lib/iomgr/resource_quota.cc - - src/core/lib/iomgr/sockaddr_utils.cc - src/core/lib/iomgr/socket_factory_posix.cc - src/core/lib/iomgr/socket_mutator.cc - src/core/lib/iomgr/socket_utils_common_posix.cc @@ -1282,9 +1326,7 @@ libs: - src/core/lib/json/json_reader.cc - src/core/lib/json/json_util.cc - src/core/lib/json/json_writer.cc - - src/core/lib/security/authorization/authorization_engine.cc - - src/core/lib/security/authorization/evaluate_args.cc - - src/core/lib/security/authorization/matchers.cc + - src/core/lib/matchers/matchers.cc - src/core/lib/security/context/security_context.cc - src/core/lib/security/credentials/alts/alts_credentials.cc - src/core/lib/security/credentials/alts/check_gcp_environment.cc @@ -1407,20 +1449,15 @@ libs: - src/core/tsi/transport_security.cc - src/core/tsi/transport_security_grpc.cc deps: + - absl/container:flat_hash_map + - absl/container:inlined_vector + - absl/functional:bind_front + - absl/status:statusor - gpr + - libssl - address_sorting - - upb - - absl/types:optional - - absl/strings:strings - - absl/status:statusor - - absl/status:status - - absl/functional:bind_front - - absl/container:inlined_vector - - absl/container:flat_hash_set - - absl/container:flat_hash_map baselib: true generate_plugin_registry: true - secure: true - name: grpc_csharp_ext build: all language: c @@ -1430,20 +1467,18 @@ libs: - src/csharp/ext/grpc_csharp_ext.c deps: - grpc - - gpr - - address_sorting - - upb - name: grpc_test_util build: private language: c public_headers: [] headers: - test/core/util/cmdline.h - - test/core/util/eval_args_mock_endpoint.h + - test/core/util/evaluate_args_test_util.h - test/core/util/fuzzer_util.h - test/core/util/grpc_profiler.h - test/core/util/histogram.h - test/core/util/memory_counters.h + - test/core/util/mock_authorization_endpoint.h - test/core/util/mock_endpoint.h - test/core/util/parse_hexstring.h - test/core/util/passthru_endpoint.h @@ -1461,7 +1496,6 @@ libs: - test/core/util/trickle_endpoint.h src: - test/core/util/cmdline.cc - - test/core/util/eval_args_mock_endpoint.cc - test/core/util/fuzzer_util.cc - test/core/util/grpc_profiler.cc - test/core/util/histogram.cc @@ -1484,24 +1518,22 @@ libs: - test/core/util/tracer_util.cc - test/core/util/trickle_endpoint.cc deps: - - grpc - - gpr - - address_sorting - - upb - - absl/debugging:symbolize - - absl/debugging:stacktrace - absl/debugging:failure_signal_handler + - absl/debugging:stacktrace + - absl/debugging:symbolize + - grpc - name: grpc_test_util_unsecure build: private language: c public_headers: [] headers: - test/core/util/cmdline.h - - test/core/util/eval_args_mock_endpoint.h + - test/core/util/evaluate_args_test_util.h - test/core/util/fuzzer_util.h - test/core/util/grpc_profiler.h - test/core/util/histogram.h - test/core/util/memory_counters.h + - test/core/util/mock_authorization_endpoint.h - test/core/util/mock_endpoint.h - test/core/util/parse_hexstring.h - test/core/util/passthru_endpoint.h @@ -1518,7 +1550,6 @@ libs: - test/core/util/trickle_endpoint.h src: - test/core/util/cmdline.cc - - test/core/util/eval_args_mock_endpoint.cc - test/core/util/fuzzer_util.cc - test/core/util/grpc_profiler.cc - test/core/util/histogram.cc @@ -1540,14 +1571,10 @@ libs: - test/core/util/tracer_util.cc - test/core/util/trickle_endpoint.cc deps: - - grpc_unsecure - - gpr - - address_sorting - - upb - - absl/debugging:symbolize - - absl/debugging:stacktrace - absl/debugging:failure_signal_handler - secure: false + - absl/debugging:stacktrace + - absl/debugging:symbolize + - grpc_unsecure - name: grpc_unsecure build: all language: c @@ -1556,6 +1583,10 @@ libs: - include/grpc/byte_buffer_reader.h - include/grpc/census.h - include/grpc/compression.h + - include/grpc/event_engine/channel_args.h + - include/grpc/event_engine/event_engine.h + - include/grpc/event_engine/port.h + - include/grpc/event_engine/slice_allocator.h - include/grpc/fork.h - include/grpc/grpc.h - include/grpc/grpc_posix.h @@ -1601,6 +1632,8 @@ libs: - src/core/ext/filters/client_channel/resolver_factory.h - src/core/ext/filters/client_channel/resolver_registry.h - src/core/ext/filters/client_channel/resolver_result_parsing.h + - src/core/ext/filters/client_channel/retry_filter.h + - src/core/ext/filters/client_channel/retry_service_config.h - src/core/ext/filters/client_channel/retry_throttle.h - src/core/ext/filters/client_channel/server_address.h - src/core/ext/filters/client_channel/service_config.h @@ -1610,6 +1643,8 @@ libs: - src/core/ext/filters/client_channel/subchannel_interface.h - src/core/ext/filters/client_channel/subchannel_pool_interface.h - src/core/ext/filters/deadline/deadline_filter.h + - src/core/ext/filters/fault_injection/fault_injection_filter.h + - src/core/ext/filters/fault_injection/service_config_parser.h - src/core/ext/filters/http/client/http_client_filter.h - src/core/ext/filters/http/client_authority_filter.h - src/core/ext/filters/http/message_compress/message_compress_filter.h @@ -1645,21 +1680,12 @@ libs: - src/core/ext/transport/chttp2/transport/stream_map.h - src/core/ext/transport/chttp2/transport/varint.h - src/core/ext/transport/inproc/inproc_transport.h - - src/core/ext/upb-generated/google/api/annotations.upb.h - - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.h - - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.h - - src/core/ext/upb-generated/google/api/http.upb.h - - src/core/ext/upb-generated/google/protobuf/any.upb.h - - src/core/ext/upb-generated/google/protobuf/duration.upb.h - - src/core/ext/upb-generated/google/protobuf/empty.upb.h - - src/core/ext/upb-generated/google/protobuf/struct.upb.h - - src/core/ext/upb-generated/google/protobuf/timestamp.upb.h - - src/core/ext/upb-generated/google/protobuf/wrappers.upb.h - - src/core/ext/upb-generated/google/rpc/status.upb.h - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.h - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.h - src/core/ext/upb-generated/validate/validate.upb.h + - src/core/lib/address_utils/parse_address.h + - src/core/lib/address_utils/sockaddr_utils.h - src/core/lib/avl/avl.h - src/core/lib/backoff/backoff.h - src/core/lib/channel/channel_args.h @@ -1685,7 +1711,6 @@ libs: - src/core/lib/debug/stats_data.h - src/core/lib/debug/trace.h - src/core/lib/gprpp/atomic.h - - src/core/lib/gprpp/debug_location.h - src/core/lib/gprpp/dual_ref_counted.h - src/core/lib/gprpp/orphanable.h - src/core/lib/gprpp/ref_counted.h @@ -1726,8 +1751,6 @@ libs: - src/core/lib/iomgr/load_file.h - src/core/lib/iomgr/lockfree_event.h - src/core/lib/iomgr/nameser.h - - src/core/lib/iomgr/parse_address.h - - src/core/lib/iomgr/poller/eventmanager_libuv.h - src/core/lib/iomgr/polling_entity.h - src/core/lib/iomgr/pollset.h - src/core/lib/iomgr/pollset_custom.h @@ -1744,7 +1767,6 @@ libs: - src/core/lib/iomgr/sockaddr.h - src/core/lib/iomgr/sockaddr_custom.h - src/core/lib/iomgr/sockaddr_posix.h - - src/core/lib/iomgr/sockaddr_utils.h - src/core/lib/iomgr/sockaddr_windows.h - src/core/lib/iomgr/socket_factory_posix.h - src/core/lib/iomgr/socket_mutator.h @@ -1852,6 +1874,8 @@ libs: - src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc - src/core/ext/filters/client_channel/resolver_registry.cc - src/core/ext/filters/client_channel/resolver_result_parsing.cc + - src/core/ext/filters/client_channel/retry_filter.cc + - src/core/ext/filters/client_channel/retry_service_config.cc - src/core/ext/filters/client_channel/retry_throttle.cc - src/core/ext/filters/client_channel/server_address.cc - src/core/ext/filters/client_channel/service_config.cc @@ -1861,6 +1885,8 @@ libs: - src/core/ext/filters/client_channel/subchannel_pool_interface.cc - src/core/ext/filters/client_idle/client_idle_filter.cc - src/core/ext/filters/deadline/deadline_filter.cc + - src/core/ext/filters/fault_injection/fault_injection_filter.cc + - src/core/ext/filters/fault_injection/service_config_parser.cc - src/core/ext/filters/http/client/http_client_filter.cc - src/core/ext/filters/http/client_authority_filter.cc - src/core/ext/filters/http/http_filters_plugin.cc @@ -1904,21 +1930,12 @@ libs: - src/core/ext/transport/chttp2/transport/writing.cc - src/core/ext/transport/inproc/inproc_plugin.cc - src/core/ext/transport/inproc/inproc_transport.cc - - src/core/ext/upb-generated/google/api/annotations.upb.c - - src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c - - src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c - - src/core/ext/upb-generated/google/api/http.upb.c - - src/core/ext/upb-generated/google/protobuf/any.upb.c - - src/core/ext/upb-generated/google/protobuf/duration.upb.c - - src/core/ext/upb-generated/google/protobuf/empty.upb.c - - src/core/ext/upb-generated/google/protobuf/struct.upb.c - - src/core/ext/upb-generated/google/protobuf/timestamp.upb.c - - src/core/ext/upb-generated/google/protobuf/wrappers.upb.c - - src/core/ext/upb-generated/google/rpc/status.upb.c - src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c - src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c - src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c - src/core/ext/upb-generated/validate/validate.upb.c + - src/core/lib/address_utils/parse_address.cc + - src/core/lib/address_utils/sockaddr_utils.cc - src/core/lib/avl/avl.cc - src/core/lib/backoff/backoff.cc - src/core/lib/channel/channel_args.cc @@ -1941,6 +1958,8 @@ libs: - src/core/lib/debug/stats.cc - src/core/lib/debug/stats_data.cc - src/core/lib/debug/trace.cc + - src/core/lib/event_engine/slice_allocator.cc + - src/core/lib/event_engine/sockaddr.cc - src/core/lib/http/format_request.cc - src/core/lib/http/httpcli.cc - src/core/lib/http/parser.cc @@ -1985,8 +2004,6 @@ libs: - src/core/lib/iomgr/is_epollexclusive_available.cc - src/core/lib/iomgr/load_file.cc - src/core/lib/iomgr/lockfree_event.cc - - src/core/lib/iomgr/parse_address.cc - - src/core/lib/iomgr/poller/eventmanager_libuv.cc - src/core/lib/iomgr/polling_entity.cc - src/core/lib/iomgr/pollset.cc - src/core/lib/iomgr/pollset_custom.cc @@ -2000,7 +2017,6 @@ libs: - src/core/lib/iomgr/resolve_address_posix.cc - src/core/lib/iomgr/resolve_address_windows.cc - src/core/lib/iomgr/resource_quota.cc - - src/core/lib/iomgr/sockaddr_utils.cc - src/core/lib/iomgr/socket_factory_posix.cc - src/core/lib/iomgr/socket_mutator.cc - src/core/lib/iomgr/socket_utils_common_posix.cc @@ -2086,18 +2102,13 @@ libs: - src/core/lib/uri/uri_parser.cc - src/core/plugin_registry/grpc_unsecure_plugin_registry.cc deps: + - absl/container:flat_hash_map + - absl/container:inlined_vector + - absl/status:statusor - gpr - address_sorting - - upb - - absl/types:optional - - absl/strings:strings - - absl/status:statusor - - absl/status:status - - absl/container:inlined_vector - - absl/container:flat_hash_map baselib: true generate_plugin_registry: true - secure: false - name: benchmark_helpers build: test language: c++ @@ -2112,14 +2123,10 @@ libs: - src/proto/grpc/testing/simple_messages.proto - test/cpp/microbenchmarks/helpers.cc deps: - - grpc_test_util_unsecure + - benchmark - grpc++_unsecure - - grpc_unsecure + - grpc_test_util_unsecure - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark defaults: benchmark - name: grpc++ build: all @@ -2245,6 +2252,7 @@ libs: - include/grpcpp/impl/codegen/message_allocator.h - include/grpcpp/impl/codegen/metadata_map.h - include/grpcpp/impl/codegen/method_handler.h + - include/grpcpp/impl/codegen/method_handler_impl.h - include/grpcpp/impl/codegen/proto_buffer_reader.h - include/grpcpp/impl/codegen/proto_buffer_writer.h - include/grpcpp/impl/codegen/proto_utils.h @@ -2374,10 +2382,6 @@ libs: - src/cpp/util/time_cc.cc deps: - grpc - - gpr - - address_sorting - - upb - - absl/synchronization:synchronization baselib: true - name: grpc++_alts build: all @@ -2391,10 +2395,6 @@ libs: - src/cpp/common/alts_util.cc deps: - grpc++ - - grpc - - gpr - - address_sorting - - upb baselib: true - name: grpc++_error_details build: all @@ -2407,10 +2407,6 @@ libs: - src/cpp/util/error_details.cc deps: - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: grpc++_reflection build: all language: c++ @@ -2425,10 +2421,6 @@ libs: - src/cpp/ext/proto_server_reflection_plugin.cc deps: - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: grpc++_test build: private language: c++ @@ -2445,10 +2437,6 @@ libs: - src/cpp/client/channel_test_peer.cc deps: - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: grpc++_test_config build: private language: c++ @@ -2458,8 +2446,8 @@ libs: src: - test/cpp/util/test_config_cc.cc deps: - - gpr - absl/flags:parse + - gpr - name: grpc++_test_util build: private language: c++ @@ -2482,13 +2470,9 @@ libs: - test/cpp/util/subprocess.cc - test/cpp/util/test_credentials_provider.cc deps: - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - absl/flags:flag + - grpc++ + - grpc_test_util - name: grpc++_unsecure build: all language: c++ @@ -2613,6 +2597,7 @@ libs: - include/grpcpp/impl/codegen/message_allocator.h - include/grpcpp/impl/codegen/metadata_map.h - include/grpcpp/impl/codegen/method_handler.h + - include/grpcpp/impl/codegen/method_handler_impl.h - include/grpcpp/impl/codegen/proto_buffer_reader.h - include/grpcpp/impl/codegen/proto_buffer_writer.h - include/grpcpp/impl/codegen/proto_utils.h @@ -2727,12 +2712,7 @@ libs: - src/cpp/util/time_cc.cc deps: - grpc_unsecure - - gpr - - address_sorting - - upb - - absl/synchronization:synchronization baselib: true - secure: false - name: grpc_plugin_support build: protoc language: c++ @@ -2772,7 +2752,6 @@ libs: - src/compiler/python_generator.cc - src/compiler/ruby_generator.cc deps: [] - secure: false - name: grpcpp_channelz build: all language: c++ @@ -2786,10 +2765,6 @@ libs: - src/cpp/server/channelz/channelz_service_plugin.cc deps: - grpc++ - - grpc - - gpr - - address_sorting - - upb targets: - name: algorithm_test build: test @@ -2799,10 +2774,6 @@ targets: - test/core/compression/algorithm_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: alloc_test build: test @@ -2812,10 +2783,6 @@ targets: - test/core/gpr/alloc_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: alpn_test build: test @@ -2825,10 +2792,6 @@ targets: - test/core/transport/chttp2/alpn_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_counter_test build: test language: c @@ -2839,10 +2802,6 @@ targets: - test/core/tsi/alts/frame_protector/alts_counter_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_crypt_test build: test language: c @@ -2853,10 +2812,6 @@ targets: - test/core/tsi/alts/crypt/gsec_test_util.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_crypter_test build: test language: c @@ -2867,10 +2822,6 @@ targets: - test/core/tsi/alts/frame_protector/alts_crypter_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_frame_protector_test build: test language: c @@ -2883,10 +2834,6 @@ targets: - test/core/tsi/transport_security_test_lib.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_grpc_record_protocol_test build: test language: c @@ -2897,10 +2844,6 @@ targets: - test/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_handshaker_client_test build: test language: c @@ -2911,10 +2854,6 @@ targets: - test/core/tsi/alts/handshaker/alts_handshaker_service_api_test_lib.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_iovec_record_protocol_test build: test language: c @@ -2925,10 +2864,6 @@ targets: - test/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_security_connector_test build: test language: c @@ -2937,10 +2872,6 @@ targets: - test/core/security/alts_security_connector_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_tsi_handshaker_test build: test language: c @@ -2951,10 +2882,6 @@ targets: - test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_tsi_utils_test build: test language: c @@ -2965,10 +2892,6 @@ targets: - test/core/tsi/alts/handshaker/alts_tsi_utils_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: alts_zero_copy_grpc_protector_test build: test language: c @@ -2979,10 +2902,6 @@ targets: - test/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: arena_test build: test language: c @@ -2991,10 +2910,6 @@ targets: - test/core/gpr/arena_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: auth_context_test build: test @@ -3004,10 +2919,6 @@ targets: - test/core/security/auth_context_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: avl_test build: test @@ -3017,10 +2928,6 @@ targets: - test/core/avl/avl_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: b64_test build: test @@ -3030,10 +2937,6 @@ targets: - test/core/slice/b64_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: bad_server_response_test build: test @@ -3045,10 +2948,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: bad_ssl_alpn_test build: test language: c @@ -3059,10 +2958,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3077,10 +2972,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3093,10 +2984,6 @@ targets: - test/core/transport/chttp2/bin_decoder_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: bin_encoder_test build: test @@ -3106,10 +2993,6 @@ targets: - test/core/transport/chttp2/bin_encoder_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: buffer_list_test build: test @@ -3119,10 +3002,6 @@ targets: - test/core/iomgr/buffer_list_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: channel_args_test build: test language: c @@ -3131,10 +3010,6 @@ targets: - test/core/channel/channel_args_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: channel_create_test build: test @@ -3144,10 +3019,6 @@ targets: - test/core/surface/channel_create_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: channel_stack_builder_test build: test language: c @@ -3156,10 +3027,6 @@ targets: - test/core/channel/channel_stack_builder_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: channel_stack_test build: test language: c @@ -3168,10 +3035,6 @@ targets: - test/core/channel/channel_stack_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: check_gcp_environment_linux_test build: test @@ -3181,10 +3044,6 @@ targets: - test/core/security/check_gcp_environment_linux_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: check_gcp_environment_windows_test build: test language: c @@ -3193,10 +3052,6 @@ targets: - test/core/security/check_gcp_environment_windows_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: client_ssl_test build: test language: c @@ -3205,10 +3060,6 @@ targets: - test/core/handshake/client_ssl.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3221,10 +3072,6 @@ targets: - test/core/util/cmdline_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: combiner_test build: test @@ -3234,10 +3081,6 @@ targets: - test/core/iomgr/combiner_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3251,10 +3094,6 @@ targets: - test/core/surface/completion_queue_threading_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: compression_test build: test language: c @@ -3263,10 +3102,6 @@ targets: - test/core/compression/compression_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: concurrent_connectivity_test build: test @@ -3276,10 +3111,6 @@ targets: - test/core/surface/concurrent_connectivity_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: connection_refused_test build: test language: c @@ -3290,10 +3121,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: cpu_test build: test language: c @@ -3302,10 +3129,6 @@ targets: - test/core/gpr/cpu_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: dns_resolver_connectivity_using_ares_test build: test @@ -3315,10 +3138,6 @@ targets: - test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb args: - --resolver=ares - name: dns_resolver_connectivity_using_native_test @@ -3329,10 +3148,6 @@ targets: - test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb args: - --resolver=native - name: dns_resolver_cooldown_test @@ -3343,10 +3158,6 @@ targets: - test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: dns_resolver_test build: test language: c @@ -3355,10 +3166,6 @@ targets: - test/core/client_channel/resolvers/dns_resolver_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: dualstack_socket_test build: test language: c @@ -3369,10 +3176,6 @@ targets: - test/core/end2end/dualstack_socket_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3387,10 +3190,6 @@ targets: - test/core/iomgr/endpoint_tests.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: env_test build: test language: c @@ -3399,10 +3198,6 @@ targets: - test/core/gpr/env_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: error_test build: test @@ -3414,10 +3209,6 @@ targets: - test/core/iomgr/error_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: ev_epollex_linux_test build: test @@ -3427,10 +3218,6 @@ targets: - test/core/iomgr/ev_epollex_linux_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3443,10 +3230,6 @@ targets: - test/core/client_channel/resolvers/fake_resolver_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: fake_transport_security_test build: test language: c @@ -3457,10 +3240,6 @@ targets: - test/core/tsi/transport_security_test_lib.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: fd_conservation_posix_test build: test language: c @@ -3469,10 +3248,6 @@ targets: - test/core/iomgr/fd_conservation_posix_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3485,10 +3260,6 @@ targets: - test/core/iomgr/fd_posix_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3506,10 +3277,6 @@ targets: - test/core/fling/fling_stream_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3527,10 +3294,6 @@ targets: - test/core/fling/fling_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3543,10 +3306,6 @@ targets: - test/core/gprpp/fork_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3565,10 +3324,6 @@ targets: - test/core/http/format_request_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: frame_handler_test build: test language: c @@ -3579,10 +3334,6 @@ targets: - test/core/tsi/alts/frame_protector/frame_handler_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: goaway_server_test build: test language: c @@ -3593,10 +3344,6 @@ targets: - test/core/end2end/goaway_server_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: grpc_alts_credentials_options_test build: test language: c @@ -3605,10 +3352,6 @@ targets: - test/core/security/grpc_alts_credentials_options_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: grpc_byte_buffer_reader_test build: test language: c @@ -3617,10 +3360,6 @@ targets: - test/core/surface/byte_buffer_reader_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: grpc_completion_queue_test build: test @@ -3630,10 +3369,6 @@ targets: - test/core/surface/completion_queue_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: grpc_ipv6_loopback_available_test build: test language: c @@ -3642,10 +3377,6 @@ targets: - test/core/iomgr/grpc_ipv6_loopback_available_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: handshake_server_with_readahead_handshaker_test build: test language: c @@ -3656,10 +3387,6 @@ targets: - test/core/handshake/server_ssl_common.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3672,10 +3399,6 @@ targets: - test/core/handshake/verify_peer_options.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3688,10 +3411,6 @@ targets: - test/core/util/histogram_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: host_port_test build: test @@ -3701,10 +3420,6 @@ targets: - test/core/gprpp/host_port_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: hpack_encoder_test build: test @@ -3714,10 +3429,6 @@ targets: - test/core/transport/chttp2/hpack_encoder_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: hpack_parser_test build: test @@ -3727,10 +3438,6 @@ targets: - test/core/transport/chttp2/hpack_parser_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: hpack_table_test build: test @@ -3740,10 +3447,6 @@ targets: - test/core/transport/chttp2/hpack_table_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: httpcli_test build: test @@ -3758,10 +3461,6 @@ targets: - test/core/http/httpcli_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3779,10 +3478,6 @@ targets: - test/core/http/httpscli_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3795,11 +3490,6 @@ targets: - test/core/end2end/inproc_callback_test.cc deps: - end2end_tests - - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: invalid_call_argument_test build: test @@ -3811,10 +3501,6 @@ targets: - test/core/end2end/invalid_call_argument_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: json_token_test build: test language: c @@ -3823,10 +3509,6 @@ targets: - test/core/security/json_token_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: jwt_verifier_test build: test @@ -3836,10 +3518,6 @@ targets: - test/core/security/jwt_verifier_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: lame_client_test build: test @@ -3851,10 +3529,6 @@ targets: - test/core/surface/lame_client_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: load_file_test build: test language: c @@ -3863,10 +3537,6 @@ targets: - test/core/iomgr/load_file_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: manual_constructor_test build: test @@ -3876,10 +3546,6 @@ targets: - test/core/gprpp/manual_constructor_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: message_compress_test build: test @@ -3889,10 +3555,6 @@ targets: - test/core/compression/message_compress_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: metadata_test build: test @@ -3902,10 +3564,6 @@ targets: - test/core/transport/metadata_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: minimal_stack_is_minimal_test build: test language: c @@ -3914,10 +3572,6 @@ targets: - test/core/channel/minimal_stack_is_minimal_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: mpmcqueue_test build: test @@ -3927,10 +3581,6 @@ targets: - test/core/iomgr/mpmcqueue_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: mpscq_test build: test @@ -3940,10 +3590,6 @@ targets: - test/core/gprpp/mpscq_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -3959,10 +3605,6 @@ targets: - test/core/end2end/multiple_server_queues_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: murmur_hash_test build: test language: c @@ -3971,10 +3613,6 @@ targets: - test/core/gpr/murmur_hash_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: no_server_test build: test @@ -3986,10 +3624,6 @@ targets: - test/core/end2end/no_server_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: num_external_connectivity_watchers_test build: test language: c @@ -3998,34 +3632,22 @@ targets: - test/core/surface/num_external_connectivity_watchers_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: parse_address_test build: test language: c headers: [] src: - - test/core/iomgr/parse_address_test.cc + - test/core/address_utils/parse_address_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: parse_address_with_named_scope_id_test build: test language: c headers: [] src: - - test/core/iomgr/parse_address_with_named_scope_id_test.cc + - test/core/address_utils/parse_address_with_named_scope_id_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4044,10 +3666,6 @@ targets: - test/core/http/parser_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: percent_encoding_test build: test @@ -4057,10 +3675,6 @@ targets: - test/core/slice/percent_encoding_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: public_headers_must_be_c89 build: test @@ -4070,10 +3684,6 @@ targets: - test/core/surface/public_headers_must_be_c89.c deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: resolve_address_using_ares_resolver_posix_test build: test language: c @@ -4082,10 +3692,6 @@ targets: - test/core/iomgr/resolve_address_posix_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb args: - --resolver=ares platforms: @@ -4100,10 +3706,6 @@ targets: - test/core/iomgr/resolve_address_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb args: - --resolver=ares - name: resolve_address_using_native_resolver_posix_test @@ -4114,10 +3716,6 @@ targets: - test/core/iomgr/resolve_address_posix_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb args: - --resolver=native platforms: @@ -4132,10 +3730,6 @@ targets: - test/core/iomgr/resolve_address_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb args: - --resolver=native - name: resource_quota_test @@ -4146,10 +3740,6 @@ targets: - test/core/iomgr/resource_quota_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: secure_channel_create_test build: test language: c @@ -4158,10 +3748,6 @@ targets: - test/core/surface/secure_channel_create_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: secure_endpoint_test build: test language: c @@ -4172,10 +3758,6 @@ targets: - test/core/security/secure_endpoint_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: security_connector_test build: test language: c @@ -4184,10 +3766,6 @@ targets: - test/core/security/security_connector_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: sequential_connectivity_test build: test run: false @@ -4197,10 +3775,6 @@ targets: - test/core/surface/sequential_connectivity_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: server_ssl_test build: test language: c @@ -4211,10 +3785,6 @@ targets: - test/core/handshake/server_ssl_common.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4227,10 +3797,6 @@ targets: - test/core/surface/server_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: slice_buffer_test build: test language: c @@ -4239,10 +3805,6 @@ targets: - test/core/slice/slice_buffer_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: slice_string_helpers_test build: test @@ -4252,10 +3814,6 @@ targets: - test/core/slice/slice_string_helpers_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: sockaddr_resolver_test build: test @@ -4265,22 +3823,6 @@ targets: - test/core/client_channel/resolvers/sockaddr_resolver_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb -- name: sockaddr_utils_test - build: test - language: c - headers: [] - src: - - test/core/iomgr/sockaddr_utils_test.cc - deps: - - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: socket_utils_test build: test language: c @@ -4289,10 +3831,6 @@ targets: - test/core/iomgr/socket_utils_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4305,10 +3843,6 @@ targets: - test/core/gpr/spinlock_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: ssl_credentials_test build: test @@ -4318,10 +3852,6 @@ targets: - test/core/security/ssl_credentials_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: ssl_transport_security_test build: test language: c @@ -4332,10 +3862,6 @@ targets: - test/core/tsi/transport_security_test_lib.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4348,10 +3874,6 @@ targets: - test/core/transport/status_conversion_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: stream_compression_test build: test @@ -4361,10 +3883,6 @@ targets: - test/core/compression/stream_compression_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: stream_map_test build: test @@ -4374,10 +3892,6 @@ targets: - test/core/transport/chttp2/stream_map_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: stream_owned_slice_test build: test language: c @@ -4386,10 +3900,6 @@ targets: - test/core/transport/stream_owned_slice_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: string_test build: test @@ -4399,10 +3909,6 @@ targets: - test/core/gpr/string_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: sync_test build: test @@ -4412,10 +3918,6 @@ targets: - test/core/gpr/sync_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: tcp_client_posix_test build: test @@ -4425,10 +3927,6 @@ targets: - test/core/iomgr/tcp_client_posix_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4443,10 +3941,6 @@ targets: - test/core/iomgr/tcp_posix_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4458,10 +3952,6 @@ targets: - test/core/iomgr/tcp_server_posix_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4474,10 +3964,6 @@ targets: - test/core/gpr/time_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: test_core_security_credentials_test build: test @@ -4487,10 +3973,6 @@ targets: - test/core/security/credentials_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: test_core_slice_slice_test build: test language: c @@ -4499,10 +3981,6 @@ targets: - test/core/slice/slice_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: thd_test build: test @@ -4512,10 +3990,6 @@ targets: - test/core/gprpp/thd_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: threadpool_test build: test @@ -4525,10 +3999,6 @@ targets: - test/core/iomgr/threadpool_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: time_averaged_stats_test build: test @@ -4538,10 +4008,6 @@ targets: - test/core/iomgr/time_averaged_stats_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: timeout_encoding_test build: test @@ -4551,10 +4017,6 @@ targets: - test/core/transport/timeout_encoding_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: timer_heap_test build: test @@ -4564,10 +4026,6 @@ targets: - test/core/iomgr/timer_heap_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: timer_list_test build: test @@ -4577,10 +4035,6 @@ targets: - test/core/iomgr/timer_list_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: tls_test build: test @@ -4590,10 +4044,6 @@ targets: - test/core/gpr/tls_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: transport_security_common_api_test build: test @@ -4603,10 +4053,6 @@ targets: - test/core/tsi/alts/handshaker/transport_security_common_api_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: transport_security_test build: test language: c @@ -4615,10 +4061,6 @@ targets: - test/core/tsi/transport_security_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: udp_server_test build: test language: c @@ -4627,10 +4069,6 @@ targets: - test/core/iomgr/udp_server_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4643,10 +4081,6 @@ targets: - test/core/gpr/useful_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: varint_test build: test @@ -4656,10 +4090,6 @@ targets: - test/core/transport/chttp2/varint_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: address_sorting_test gtest: true @@ -4669,14 +4099,8 @@ targets: src: - test/cpp/naming/address_sorting_test.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util platforms: - linux - posix @@ -4695,17 +4119,31 @@ targets: - test/cpp/util/string_ref_helper.cc - test/cpp/util/subprocess.cc deps: - - grpc_test_util_unsecure - grpc++_unsecure - - grpc_unsecure + - grpc_test_util_unsecure - grpc++_test_config - - gpr - - address_sorting - - upb platforms: - linux - posix - mac +- name: admin_services_end2end_test + gtest: true + build: test + language: c++ + headers: + - src/cpp/server/csds/csds.h + src: + - src/proto/grpc/testing/xds/v3/base.proto + - src/proto/grpc/testing/xds/v3/config_dump.proto + - src/proto/grpc/testing/xds/v3/csds.proto + - src/proto/grpc/testing/xds/v3/percent.proto + - src/cpp/server/admin/admin_services.cc + - src/cpp/server/csds/csds.cc + - test/cpp/end2end/admin_services_end2end_test.cc + deps: + - grpc++_reflection + - grpcpp_channelz + - grpc++_test_util - name: alarm_test gtest: true build: test @@ -4714,12 +4152,8 @@ targets: src: - test/cpp/common/alarm_test.cc deps: - - grpc_test_util_unsecure - grpc++_unsecure - - grpc_unsecure - - gpr - - address_sorting - - upb + - grpc_test_util_unsecure platforms: - linux - posix @@ -4738,12 +4172,8 @@ targets: - test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc - test/core/tsi/alts/handshaker/alts_concurrent_connectivity_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util platforms: - linux - posix @@ -4755,13 +4185,9 @@ targets: - test/core/security/alts_credentials_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/security/corpus/alts_credentials_corpus maxlen: 2048 @@ -4773,14 +4199,8 @@ targets: src: - test/cpp/common/alts_util_test.cc deps: - - grpc++_test_util - grpc++_alts - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util - name: async_end2end_test gtest: true build: test @@ -4795,12 +4215,6 @@ targets: - test/cpp/end2end/async_end2end_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: auth_property_iterator_test gtest: true build: test @@ -4810,26 +4224,25 @@ targets: - test/cpp/common/auth_property_iterator_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb uses_polling: false -- name: authorization_engine_test +- name: authorization_matchers_test gtest: true build: test language: c++ - headers: [] + headers: + - src/core/lib/security/authorization/authorization_engine.h + - src/core/lib/security/authorization/evaluate_args.h + - src/core/lib/security/authorization/grpc_authorization_engine.h + - src/core/lib/security/authorization/matchers.h + - src/core/lib/security/authorization/rbac_policy.h src: - - test/core/security/authorization_engine_test.cc + - src/core/lib/security/authorization/evaluate_args.cc + - src/core/lib/security/authorization/grpc_authorization_engine.cc + - src/core/lib/security/authorization/matchers.cc + - src/core/lib/security/authorization/rbac_policy.cc + - test/core/security/authorization_matchers_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: aws_request_signer_test gtest: true build: test @@ -4839,10 +4252,6 @@ targets: - test/core/security/aws_request_signer_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: backoff_test gtest: true build: test @@ -4852,10 +4261,6 @@ targets: - test/core/backoff/backoff_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: bad_streaming_id_bad_client_test gtest: true @@ -4870,10 +4275,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: badreq_bad_client_test gtest: true build: test @@ -4887,10 +4288,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: bdp_estimator_test gtest: true build: test @@ -4900,10 +4297,6 @@ targets: - test/core/transport/bdp_estimator_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -4917,14 +4310,6 @@ targets: - test/cpp/microbenchmarks/bm_alarm.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -4938,14 +4323,6 @@ targets: - test/cpp/microbenchmarks/bm_arena.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -4960,14 +4337,6 @@ targets: - test/cpp/microbenchmarks/bm_byte_buffer.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -4982,14 +4351,6 @@ targets: - test/cpp/microbenchmarks/bm_call_create.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5014,14 +4375,6 @@ targets: - test/cpp/util/subprocess.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5045,14 +4398,6 @@ targets: - test/cpp/util/subprocess.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5066,14 +4411,6 @@ targets: - test/cpp/microbenchmarks/bm_channel.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5088,14 +4425,6 @@ targets: - test/cpp/microbenchmarks/bm_chttp2_hpack.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5110,14 +4439,6 @@ targets: - test/cpp/microbenchmarks/bm_chttp2_transport.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5131,14 +4452,6 @@ targets: - test/cpp/microbenchmarks/bm_closure.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5152,14 +4465,6 @@ targets: - test/cpp/microbenchmarks/bm_cq.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5173,14 +4478,6 @@ targets: - test/cpp/microbenchmarks/bm_cq_multiple_threads.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5195,14 +4492,6 @@ targets: - test/cpp/microbenchmarks/bm_error.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5218,14 +4507,6 @@ targets: - test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5240,14 +4521,6 @@ targets: - test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5261,16 +4534,8 @@ targets: src: - test/cpp/microbenchmarks/bm_fullstack_trickle.cc deps: - - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark - absl/flags:flag + - benchmark_helpers benchmark: true defaults: benchmark platforms: @@ -5286,14 +4551,6 @@ targets: - test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5307,14 +4564,6 @@ targets: - test/cpp/microbenchmarks/bm_metadata.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5329,14 +4578,6 @@ targets: - test/cpp/microbenchmarks/bm_pollset.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5351,14 +4592,6 @@ targets: - test/cpp/microbenchmarks/bm_threadpool.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5374,14 +4607,6 @@ targets: - test/cpp/microbenchmarks/bm_timer.cc deps: - benchmark_helpers - - grpc_test_util_unsecure - - grpc++_unsecure - - grpc_unsecure - - grpc++_test_config - - gpr - - address_sorting - - upb - - benchmark benchmark: true defaults: benchmark platforms: @@ -5397,12 +4622,6 @@ targets: - test/cpp/util/byte_buffer_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: byte_stream_test gtest: true @@ -5413,10 +4632,6 @@ targets: - test/core/transport/byte_stream_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: cancel_ares_query_test gtest: true @@ -5430,14 +4645,35 @@ targets: - test/cpp/naming/cancel_ares_query_test.cc - test/cpp/naming/dns_test_util.cc deps: + - grpc++_test_config - grpc++_test_util +- name: cel_authorization_engine_test + gtest: true + build: test + language: c++ + headers: + - src/core/lib/security/authorization/authorization_engine.h + - src/core/lib/security/authorization/cel_authorization_engine.h + - src/core/lib/security/authorization/evaluate_args.h + - src/core/lib/security/authorization/grpc_authorization_engine.h + - src/core/lib/security/authorization/matchers.h + - src/core/lib/security/authorization/mock_cel/activation.h + - src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h + - src/core/lib/security/authorization/mock_cel/cel_expression.h + - src/core/lib/security/authorization/mock_cel/cel_value.h + - src/core/lib/security/authorization/mock_cel/evaluator_core.h + - src/core/lib/security/authorization/mock_cel/flat_expr_builder.h + - src/core/lib/security/authorization/rbac_policy.h + src: + - src/core/lib/security/authorization/cel_authorization_engine.cc + - src/core/lib/security/authorization/evaluate_args.cc + - src/core/lib/security/authorization/grpc_authorization_engine.cc + - src/core/lib/security/authorization/matchers.cc + - src/core/lib/security/authorization/rbac_policy.cc + - test/core/security/cel_authorization_engine_test.cc + deps: + - absl/container:flat_hash_set - grpc_test_util - - grpc++ - - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - name: certificate_provider_registry_test gtest: true build: test @@ -5447,10 +4683,6 @@ targets: - test/core/client_channel/certificate_provider_registry_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: certificate_provider_store_test gtest: true build: test @@ -5460,10 +4692,6 @@ targets: - test/core/xds/certificate_provider_store_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: cfstream_test gtest: true build: test @@ -5479,12 +4707,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: channel_arguments_test gtest: true build: test @@ -5493,12 +4715,8 @@ targets: src: - test/cpp/common/channel_arguments_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util uses_polling: false - name: channel_filter_test gtest: true @@ -5508,12 +4726,8 @@ targets: src: - test/cpp/common/channel_filter_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util uses_polling: false - name: channel_trace_test gtest: true @@ -5526,12 +4740,8 @@ targets: - test/core/channel/channel_trace_test.cc - test/cpp/util/channel_trace_proto_helper.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util - name: channelz_registry_test gtest: true build: test @@ -5540,12 +4750,8 @@ targets: src: - test/core/channel/channelz_registry_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util uses_polling: false - name: channelz_service_test gtest: true @@ -5562,12 +4768,6 @@ targets: deps: - grpcpp_channelz - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: channelz_test gtest: true build: test @@ -5579,12 +4779,8 @@ targets: - test/core/channel/channelz_test.cc - test/cpp/util/channel_trace_proto_helper.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util - name: cli_call_test gtest: true build: test @@ -5611,13 +4807,6 @@ targets: - test/cpp/util/service_describer.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag - name: client_callback_end2end_test gtest: true build: test @@ -5634,12 +4823,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: client_channel_stress_test gtest: true build: test @@ -5657,12 +4840,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -5675,13 +4852,9 @@ targets: - test/core/end2end/fuzzers/client_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/end2end/fuzzers/client_fuzzer_corpus dict: test/core/end2end/fuzzers/hpack.dictionary @@ -5702,12 +4875,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: client_lb_end2end_test gtest: true build: test @@ -5727,12 +4894,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -5745,12 +4906,8 @@ targets: src: - test/cpp/codegen/codegen_test_full.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util uses_polling: false - name: codegen_test_minimal gtest: true @@ -5760,12 +4917,8 @@ targets: src: - test/cpp/codegen/codegen_test_minimal.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util uses_polling: false - name: connection_prefix_bad_client_test gtest: true @@ -5780,10 +4933,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: connectivity_state_test gtest: true build: test @@ -5793,10 +4942,6 @@ targets: - test/core/transport/connectivity_state_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: context_allocator_end2end_test gtest: true build: test @@ -5811,12 +4956,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: context_list_test gtest: true build: test @@ -5826,10 +4965,6 @@ targets: - test/core/transport/chttp2/context_list_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: delegating_channel_test gtest: true @@ -5845,12 +4980,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: destroy_grpclb_channel_with_active_connect_stress_test gtest: true build: test @@ -5860,12 +4989,6 @@ targets: - test/cpp/client/destroy_grpclb_channel_with_active_connect_stress_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: dual_ref_counted_test gtest: true build: test @@ -5875,10 +4998,6 @@ targets: - test/core/gprpp/dual_ref_counted_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: duplicate_header_bad_client_test gtest: true build: test @@ -5892,10 +5011,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: end2end_test gtest: true build: test @@ -5913,14 +5028,8 @@ targets: - test/cpp/end2end/interceptors_util.cc - test/cpp/end2end/test_service_impl.cc deps: - - grpc++_test_util - grpc++_test - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util - name: error_details_test gtest: true build: test @@ -5933,38 +5042,33 @@ targets: deps: - grpc++_error_details - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb -- name: evaluate_args_test +- name: error_utils_test gtest: true build: test language: c++ headers: [] src: - - test/core/security/evaluate_args_test.cc + - test/core/transport/error_utils_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb -- name: eventmanager_libuv_test +- name: evaluate_args_test gtest: true build: test language: c++ - headers: [] + headers: + - src/core/lib/security/authorization/authorization_engine.h + - src/core/lib/security/authorization/evaluate_args.h + - src/core/lib/security/authorization/grpc_authorization_engine.h + - src/core/lib/security/authorization/matchers.h + - src/core/lib/security/authorization/rbac_policy.h src: - - test/core/iomgr/poller/eventmanager_libuv_test.cc + - src/core/lib/security/authorization/evaluate_args.cc + - src/core/lib/security/authorization/grpc_authorization_engine.cc + - src/core/lib/security/authorization/matchers.cc + - src/core/lib/security/authorization/rbac_policy.cc + - test/core/security/evaluate_args_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - uses_polling: false - name: examine_stack_test gtest: true build: test @@ -5974,12 +5078,6 @@ targets: - test/core/gprpp/examine_stack_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - - absl/debugging:symbolize - - absl/debugging:stacktrace platforms: - linux - posix @@ -5997,12 +5095,6 @@ targets: - test/cpp/end2end/exception_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: file_watcher_certificate_provider_factory_test gtest: true build: test @@ -6012,10 +5104,6 @@ targets: - test/core/xds/file_watcher_certificate_provider_factory_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: filter_end2end_test gtest: true build: test @@ -6029,12 +5117,6 @@ targets: - test/cpp/end2end/filter_end2end_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: flaky_network_test gtest: true build: test @@ -6050,12 +5132,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: generic_end2end_test gtest: true build: test @@ -6069,12 +5145,6 @@ targets: - test/cpp/end2end/generic_end2end_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: global_config_env_test gtest: true build: test @@ -6084,10 +5154,6 @@ targets: - test/core/gprpp/global_config_env_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -6102,10 +5168,6 @@ targets: - test/core/gprpp/global_config_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: google_mesh_ca_certificate_provider_factory_test gtest: true @@ -6118,10 +5180,24 @@ targets: - test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb +- name: grpc_authorization_engine_test + gtest: true + build: test + language: c++ + headers: + - src/core/lib/security/authorization/authorization_engine.h + - src/core/lib/security/authorization/evaluate_args.h + - src/core/lib/security/authorization/grpc_authorization_engine.h + - src/core/lib/security/authorization/matchers.h + - src/core/lib/security/authorization/rbac_policy.h + src: + - src/core/lib/security/authorization/evaluate_args.cc + - src/core/lib/security/authorization/grpc_authorization_engine.cc + - src/core/lib/security/authorization/matchers.cc + - src/core/lib/security/authorization/rbac_policy.cc + - test/core/security/grpc_authorization_engine_test.cc + deps: + - grpc_test_util - name: grpc_cli build: test run: false @@ -6144,13 +5220,9 @@ targets: - test/cpp/util/proto_reflection_descriptor_database.cc - test/cpp/util/service_describer.cc deps: + - absl/flags:flag - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag - name: grpc_cpp_plugin build: protoc language: c++ @@ -6159,7 +5231,6 @@ targets: - src/compiler/cpp_plugin.cc deps: - grpc_plugin_support - secure: false - name: grpc_csharp_plugin build: protoc language: c++ @@ -6168,7 +5239,6 @@ targets: - src/compiler/csharp_plugin.cc deps: - grpc_plugin_support - secure: false - name: grpc_node_plugin build: protoc language: c++ @@ -6177,7 +5247,6 @@ targets: - src/compiler/node_plugin.cc deps: - grpc_plugin_support - secure: false - name: grpc_objective_c_plugin build: protoc language: c++ @@ -6186,7 +5255,6 @@ targets: - src/compiler/objective_c_plugin.cc deps: - grpc_plugin_support - secure: false - name: grpc_php_plugin build: protoc language: c++ @@ -6195,7 +5263,6 @@ targets: - src/compiler/php_plugin.cc deps: - grpc_plugin_support - secure: false - name: grpc_python_plugin build: protoc language: c++ @@ -6204,7 +5271,6 @@ targets: - src/compiler/python_plugin.cc deps: - grpc_plugin_support - secure: false - name: grpc_ruby_plugin build: protoc language: c++ @@ -6213,7 +5279,6 @@ targets: - src/compiler/ruby_plugin.cc deps: - grpc_plugin_support - secure: false - name: grpc_tls_certificate_distributor_test gtest: true build: test @@ -6223,10 +5288,6 @@ targets: - test/core/security/grpc_tls_certificate_distributor_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: grpc_tls_certificate_provider_test gtest: true build: test @@ -6236,10 +5297,6 @@ targets: - test/core/security/grpc_tls_certificate_provider_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: grpc_tls_credentials_options_test gtest: true build: test @@ -6249,10 +5306,6 @@ targets: - test/core/security/grpc_tls_credentials_options_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: grpc_tool_test gtest: true build: test @@ -6277,15 +5330,8 @@ targets: - test/cpp/util/proto_reflection_descriptor_database.cc - test/cpp/util/service_describer.cc deps: - - grpc++_test_util - grpc++_reflection - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag + - grpc++_test_util platforms: - linux - posix @@ -6300,12 +5346,6 @@ targets: - test/cpp/grpclb/grpclb_api_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: grpclb_end2end_test gtest: true build: test @@ -6323,12 +5363,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -6342,11 +5376,6 @@ targets: - test/core/end2end/h2_ssl_session_reuse_test.cc deps: - end2end_tests - - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: head_of_line_blocking_bad_client_test gtest: true build: test @@ -6360,10 +5389,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: headers_bad_client_test gtest: true build: test @@ -6377,10 +5402,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: health_service_end2end_test gtest: true build: test @@ -6399,12 +5420,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: hpack_parser_fuzzer_test build: fuzzer language: c++ @@ -6413,13 +5428,9 @@ targets: - test/core/transport/chttp2/hpack_parser_fuzzer_test.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/transport/chttp2/hpack_parser_corpus dict: test/core/end2end/fuzzers/hpack.dictionary @@ -6435,15 +5446,8 @@ targets: - src/proto/grpc/testing/test.proto - test/cpp/interop/http2_client.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag + - grpc++_test_util - name: http_request_fuzzer_test build: fuzzer language: c++ @@ -6452,13 +5456,9 @@ targets: - test/core/http/request_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/http/request_corpus maxlen: 2048 @@ -6470,13 +5470,9 @@ targets: - test/core/http/response_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/http/response_corpus maxlen: 2048 @@ -6495,12 +5491,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: init_test gtest: true build: test @@ -6510,10 +5500,6 @@ targets: - 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 gtest: true @@ -6528,10 +5514,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: insecure_security_connector_test gtest: true build: test @@ -6541,10 +5523,6 @@ targets: - test/core/security/insecure_security_connector_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: interop_client build: test run: false @@ -6562,15 +5540,8 @@ targets: - test/cpp/interop/client_helper.cc - test/cpp/interop/interop_client.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag + - grpc++_test_util - name: interop_server build: test run: false @@ -6585,15 +5556,8 @@ targets: - test/cpp/interop/interop_server_bootstrap.cc - test/cpp/interop/server_helper.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag + - grpc++_test_util - name: interop_test build: test language: c++ @@ -6601,15 +5565,8 @@ targets: src: - test/cpp/interop/interop_test.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag + - grpc++_test_util platforms: - linux - posix @@ -6622,13 +5579,9 @@ targets: - test/core/json/fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/json/corpus maxlen: 512 @@ -6641,10 +5594,6 @@ targets: - test/core/json/json_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: large_metadata_bad_client_test gtest: true @@ -6659,10 +5608,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: lb_get_cpu_stats_test gtest: true build: test @@ -6676,12 +5621,8 @@ targets: - src/cpp/server/load_reporter/get_cpu_stats_windows.cc - test/cpp/server/load_reporter/get_cpu_stats_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util - name: lb_load_data_store_test gtest: true build: test @@ -6693,12 +5634,8 @@ targets: - src/cpp/server/load_reporter/load_data_store.cc - test/cpp/server/load_reporter/load_data_store_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util - name: linux_system_roots_test gtest: true build: test @@ -6708,10 +5645,6 @@ targets: - test/core/security/linux_system_roots_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: log_test gtest: true build: test @@ -6721,10 +5654,6 @@ targets: - test/core/gpr/log_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: matchers_test gtest: true @@ -6735,10 +5664,6 @@ targets: - test/core/security/matchers_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: message_allocator_end2end_test gtest: true build: test @@ -6753,12 +5678,19 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb +- name: mock_stream_test + gtest: true + build: test + language: c++ + headers: [] + src: + - src/proto/grpc/testing/echo.proto + - src/proto/grpc/testing/echo_messages.proto + - src/proto/grpc/testing/simple_messages.proto + - test/cpp/test/mock_stream_test.cc + deps: + - grpc++_test + - grpc++_test_util - name: mock_test gtest: true build: test @@ -6771,14 +5703,8 @@ targets: - src/proto/grpc/testing/simple_messages.proto - test/cpp/end2end/mock_test.cc deps: - - grpc++_test_util - grpc++_test - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util - name: nanopb_fuzzer_response_test build: fuzzer language: c++ @@ -6787,13 +5713,9 @@ targets: - test/core/nanopb/fuzzer_response.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/nanopb/corpus_response maxlen: 128 @@ -6805,13 +5727,9 @@ targets: - test/core/nanopb/fuzzer_serverlist.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/nanopb/corpus_serverlist maxlen: 128 @@ -6827,12 +5745,6 @@ targets: - test/cpp/end2end/nonblocking_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: noop-benchmark build: test language: c++ @@ -6840,12 +5752,8 @@ targets: src: - test/cpp/microbenchmarks/noop-benchmark.cc deps: - - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - benchmark + - grpc_test_util benchmark: true defaults: benchmark - name: orphanable_test @@ -6857,10 +5765,6 @@ targets: - test/core/gprpp/orphanable_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: out_of_bounds_bad_client_test gtest: true build: test @@ -6874,10 +5778,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: percent_decode_fuzzer build: fuzzer language: c++ @@ -6886,13 +5786,9 @@ targets: - test/core/slice/percent_decode_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/slice/percent_decode_corpus maxlen: 32 @@ -6904,13 +5800,9 @@ targets: - test/core/slice/percent_encode_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/slice/percent_encode_corpus maxlen: 32 @@ -6923,10 +5815,6 @@ targets: - test/core/transport/pid_controller_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: port_sharing_end2end_test gtest: true build: test @@ -6941,12 +5829,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: proto_server_reflection_test gtest: true build: test @@ -6963,14 +5845,8 @@ targets: - test/cpp/end2end/test_service_impl.cc - test/cpp/util/proto_reflection_descriptor_database.cc deps: - - grpc++_test_util - grpc++_reflection - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util - name: proto_utils_test gtest: true build: test @@ -6979,12 +5855,8 @@ targets: src: - test/cpp/codegen/proto_utils_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util uses_polling: false - name: qps_json_driver build: test @@ -7029,15 +5901,8 @@ targets: - test/cpp/qps/server_sync.cc - test/cpp/qps/usage_timer.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag + - grpc++_test_util - name: qps_worker build: test run: false @@ -7072,15 +5937,8 @@ targets: - test/cpp/qps/usage_timer.cc - test/cpp/qps/worker.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag + - grpc++_test_util - name: raw_end2end_test gtest: true build: test @@ -7096,12 +5954,26 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util +- name: rbac_translator_test + gtest: true + build: test + language: c++ + headers: + - src/core/lib/security/authorization/authorization_engine.h + - src/core/lib/security/authorization/evaluate_args.h + - src/core/lib/security/authorization/grpc_authorization_engine.h + - src/core/lib/security/authorization/matchers.h + - src/core/lib/security/authorization/rbac_policy.h + - src/core/lib/security/authorization/rbac_translator.h + src: + - src/core/lib/security/authorization/evaluate_args.cc + - src/core/lib/security/authorization/grpc_authorization_engine.cc + - src/core/lib/security/authorization/matchers.cc + - src/core/lib/security/authorization/rbac_policy.cc + - src/core/lib/security/authorization/rbac_translator.cc + - test/core/security/rbac_translator_test.cc + deps: - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: ref_counted_ptr_test gtest: true build: test @@ -7111,10 +5983,6 @@ targets: - test/core/gprpp/ref_counted_ptr_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: ref_counted_test gtest: true build: test @@ -7124,10 +5992,6 @@ targets: - test/core/gprpp/ref_counted_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: remove_stream_from_stalled_lists_test gtest: true build: test @@ -7137,10 +6001,6 @@ targets: - test/core/transport/chttp2/remove_stream_from_stalled_lists_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -7154,10 +6014,6 @@ targets: - test/core/client_channel/retry_throttle_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: secure_auth_context_test gtest: true @@ -7168,12 +6024,6 @@ targets: - test/cpp/common/secure_auth_context_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: server_builder_plugin_test gtest: true build: test @@ -7189,12 +6039,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: server_builder_test gtest: true build: test @@ -7206,12 +6050,8 @@ targets: - src/proto/grpc/testing/simple_messages.proto - test/cpp/server/server_builder_test.cc deps: - - grpc_test_util_unsecure - grpc++_unsecure - - grpc_unsecure - - gpr - - address_sorting - - upb + - grpc_test_util_unsecure platforms: - linux - posix @@ -7227,12 +6067,8 @@ targets: - src/proto/grpc/testing/simple_messages.proto - test/cpp/server/server_builder_with_socket_mutator_test.cc deps: - - grpc_test_util_unsecure - grpc++_unsecure - - grpc_unsecure - - gpr - - address_sorting - - upb + - grpc_test_util_unsecure platforms: - linux - posix @@ -7246,10 +6082,6 @@ targets: - test/core/surface/server_chttp2_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: server_context_test_spouse_test gtest: true build: test @@ -7258,14 +6090,8 @@ targets: src: - test/cpp/test/server_context_test_spouse_test.cc deps: - - grpc++_test_util - grpc++_test - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util - name: server_early_return_test gtest: true build: test @@ -7278,12 +6104,6 @@ targets: - test/cpp/end2end/server_early_return_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: server_fuzzer build: fuzzer language: c++ @@ -7292,13 +6112,9 @@ targets: - test/core/end2end/fuzzers/server_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: - - grpc_test_util - - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - absl/flags:flag + - grpc_test_util + - grpc++_test_config corpus_dirs: - test/core/end2end/fuzzers/server_fuzzer_corpus dict: test/core/end2end/fuzzers/hpack.dictionary @@ -7319,12 +6135,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: server_registered_method_bad_client_test gtest: true build: test @@ -7338,10 +6148,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: server_request_call_test gtest: true build: test @@ -7353,12 +6159,8 @@ targets: - src/proto/grpc/testing/simple_messages.proto - test/cpp/server/server_request_call_test.cc deps: - - grpc_test_util_unsecure - grpc++_unsecure - - grpc_unsecure - - gpr - - address_sorting - - upb + - grpc_test_util_unsecure platforms: - linux - posix @@ -7378,12 +6180,6 @@ targets: - test/cpp/end2end/test_service_impl.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: service_config_test gtest: true build: test @@ -7393,10 +6189,6 @@ targets: - test/core/client_channel/service_config_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: settings_timeout_test gtest: true build: test @@ -7407,10 +6199,6 @@ targets: - test/core/transport/chttp2/settings_timeout_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: shutdown_test gtest: true build: test @@ -7424,12 +6212,6 @@ targets: - test/cpp/end2end/shutdown_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: simple_request_bad_client_test gtest: true build: test @@ -7443,10 +6225,15 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb +- name: sockaddr_utils_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/core/address_utils/sockaddr_utils_test.cc + deps: + - grpc_test_util - name: ssl_server_fuzzer build: fuzzer language: c++ @@ -7455,13 +6242,9 @@ targets: - test/core/security/ssl_server_fuzzer.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/security/corpus/ssl_server_corpus maxlen: 2048 @@ -7474,11 +6257,6 @@ targets: - test/core/util/stack_tracer_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - - absl/debugging:symbolize platforms: - linux - posix @@ -7493,10 +6271,6 @@ targets: - test/core/gprpp/stat_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: static_metadata_test gtest: true @@ -7507,10 +6281,6 @@ targets: - test/core/transport/static_metadata_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: stats_test gtest: true build: test @@ -7520,10 +6290,16 @@ targets: - test/core/debug/stats_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb + uses_polling: false +- name: status_helper_test + gtest: true + build: test + language: c++ + headers: [] + src: + - test/core/gprpp/status_helper_test.cc + deps: + - grpc_test_util uses_polling: false - name: status_metadata_test gtest: true @@ -7534,10 +6310,6 @@ targets: - test/core/transport/status_metadata_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: status_util_test gtest: true @@ -7548,10 +6320,6 @@ targets: - test/core/channel/status_util_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: stranded_event_test gtest: true @@ -7564,10 +6332,6 @@ targets: - test/core/iomgr/stranded_event_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -7585,12 +6349,6 @@ targets: - test/cpp/end2end/streaming_throughput_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -7603,12 +6361,8 @@ targets: src: - test/cpp/util/string_ref_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util uses_polling: false - name: test_cpp_client_credentials_test gtest: true @@ -7618,12 +6372,8 @@ targets: src: - test/cpp/client/credentials_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util - name: test_cpp_server_credentials_test gtest: true build: test @@ -7632,12 +6382,8 @@ targets: src: - test/cpp/server/credentials_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util - name: test_cpp_util_slice_test gtest: true build: test @@ -7647,12 +6393,6 @@ targets: - test/cpp/util/slice_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: test_cpp_util_time_test gtest: true @@ -7663,12 +6403,6 @@ targets: - test/cpp/util/time_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: thread_manager_test gtest: true @@ -7678,14 +6412,8 @@ targets: src: - test/cpp/thread_manager/thread_manager_test.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util - name: thread_stress_test gtest: true build: test @@ -7699,12 +6427,6 @@ targets: - test/cpp/end2end/thread_stress_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -7718,12 +6440,8 @@ targets: src: - test/cpp/common/time_jump_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util platforms: - linux - posix @@ -7737,10 +6455,6 @@ targets: - test/core/gprpp/time_util_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb uses_polling: false - name: timer_test gtest: true @@ -7750,12 +6464,8 @@ targets: src: - test/cpp/common/timer_test.cc deps: - - grpc_test_util - grpc++ - - grpc - - gpr - - address_sorting - - upb + - grpc_test_util - name: tls_security_connector_test gtest: true build: test @@ -7765,10 +6475,6 @@ targets: - test/core/security/tls_security_connector_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: too_many_pings_test gtest: true build: test @@ -7779,14 +6485,8 @@ targets: - test/core/end2end/cq_verifier.cc - test/core/transport/chttp2/too_many_pings_test.cc deps: - - grpc++_test_util - - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb + - grpc++_test_util - name: unknown_frame_bad_client_test gtest: true build: test @@ -7800,10 +6500,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: uri_fuzzer_test build: fuzzer language: c++ @@ -7812,13 +6508,9 @@ targets: - test/core/uri/uri_fuzzer_test.cc - test/core/util/fuzzer_corpus_test.cc deps: + - absl/flags:flag - grpc_test_util - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag corpus_dirs: - test/core/uri/uri_corpus maxlen: 128 @@ -7831,10 +6523,6 @@ targets: - test/core/uri/uri_parser_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: window_overflow_bad_client_test gtest: true build: test @@ -7848,10 +6536,6 @@ targets: - test/core/end2end/cq_verifier.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: work_serializer_test gtest: true build: test @@ -7861,10 +6545,6 @@ targets: - test/core/iomgr/work_serializer_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -7875,11 +6555,12 @@ targets: language: c++ headers: - test/core/util/cmdline.h - - test/core/util/eval_args_mock_endpoint.h + - test/core/util/evaluate_args_test_util.h - test/core/util/fuzzer_util.h - test/core/util/grpc_profiler.h - test/core/util/histogram.h - test/core/util/memory_counters.h + - test/core/util/mock_authorization_endpoint.h - test/core/util/mock_endpoint.h - test/core/util/parse_hexstring.h - test/core/util/passthru_endpoint.h @@ -7899,7 +6580,6 @@ targets: - src/proto/grpc/testing/echo_messages.proto - src/proto/grpc/testing/simple_messages.proto - test/core/util/cmdline.cc - - test/core/util/eval_args_mock_endpoint.cc - test/core/util/fuzzer_util.cc - test/core/util/grpc_profiler.cc - test/core/util/histogram.cc @@ -7922,14 +6602,10 @@ targets: - test/core/util/trickle_endpoint.cc - test/cpp/performance/writes_per_rpc_test.cc deps: - - grpc++ - - grpc - - gpr - - address_sorting - - upb - - absl/debugging:symbolize - - absl/debugging:stacktrace - absl/debugging:failure_signal_handler + - absl/debugging:stacktrace + - absl/debugging:symbolize + - grpc++ platforms: - linux - posix @@ -7943,10 +6619,6 @@ targets: - test/core/xds/xds_bootstrap_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: xds_certificate_provider_test gtest: true build: test @@ -7956,10 +6628,6 @@ targets: - test/core/xds/xds_certificate_provider_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: xds_credentials_end2end_test gtest: true build: test @@ -7974,12 +6642,6 @@ targets: - test/cpp/end2end/xds_credentials_end2end_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb - name: xds_credentials_test gtest: true build: test @@ -7989,16 +6651,13 @@ targets: - test/core/security/xds_credentials_test.cc deps: - grpc_test_util - - grpc - - gpr - - address_sorting - - upb - name: xds_end2end_test gtest: true build: test run: false language: c++ headers: + - src/cpp/server/csds/csds.h - test/cpp/end2end/test_service_impl.h src: - src/proto/grpc/testing/duplicate/echo_duplicate.proto @@ -8015,9 +6674,13 @@ targets: - src/proto/grpc/testing/xds/v3/aggregate_cluster.proto - src/proto/grpc/testing/xds/v3/base.proto - src/proto/grpc/testing/xds/v3/cluster.proto + - src/proto/grpc/testing/xds/v3/config_dump.proto - src/proto/grpc/testing/xds/v3/config_source.proto + - src/proto/grpc/testing/xds/v3/csds.proto - src/proto/grpc/testing/xds/v3/discovery.proto - src/proto/grpc/testing/xds/v3/endpoint.proto + - src/proto/grpc/testing/xds/v3/fault.proto + - src/proto/grpc/testing/xds/v3/fault_common.proto - src/proto/grpc/testing/xds/v3/http_connection_manager.proto - src/proto/grpc/testing/xds/v3/listener.proto - src/proto/grpc/testing/xds/v3/load_report.proto @@ -8030,16 +6693,11 @@ targets: - src/proto/grpc/testing/xds/v3/router.proto - src/proto/grpc/testing/xds/v3/string.proto - src/proto/grpc/testing/xds/v3/tls.proto + - src/cpp/server/csds/csds.cc - test/cpp/end2end/test_service_impl.cc - test/cpp/end2end/xds_end2end_test.cc deps: - grpc++_test_util - - grpc_test_util - - grpc++ - - grpc - - gpr - - address_sorting - - upb platforms: - linux - posix @@ -8048,38 +6706,49 @@ targets: build: test run: false language: c++ - headers: [] + headers: + - src/cpp/server/csds/csds.h src: - src/proto/grpc/testing/empty.proto - src/proto/grpc/testing/messages.proto - src/proto/grpc/testing/test.proto + - src/proto/grpc/testing/xds/v3/base.proto + - src/proto/grpc/testing/xds/v3/config_dump.proto + - src/proto/grpc/testing/xds/v3/csds.proto + - src/proto/grpc/testing/xds/v3/percent.proto + - src/cpp/server/admin/admin_services.cc + - src/cpp/server/csds/csds.cc - test/cpp/interop/xds_interop_client.cc deps: + - absl/flags:flag + - grpc++_reflection + - grpcpp_channelz - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag - name: xds_interop_server build: test run: false language: c++ - headers: [] + headers: + - src/cpp/server/csds/csds.h + - test/cpp/end2end/test_health_check_service_impl.h src: + - src/proto/grpc/health/v1/health.proto - src/proto/grpc/testing/empty.proto - src/proto/grpc/testing/messages.proto - src/proto/grpc/testing/test.proto + - src/proto/grpc/testing/xds/v3/base.proto + - src/proto/grpc/testing/xds/v3/config_dump.proto + - src/proto/grpc/testing/xds/v3/csds.proto + - src/proto/grpc/testing/xds/v3/percent.proto + - src/cpp/server/admin/admin_services.cc + - src/cpp/server/csds/csds.cc + - test/cpp/end2end/test_health_check_service_impl.cc - test/cpp/interop/xds_interop_server.cc deps: + - absl/flags:flag + - grpc++_reflection + - grpcpp_channelz - grpc_test_util - - grpc++ - grpc++_test_config - - grpc - - gpr - - address_sorting - - upb - - absl/flags:flag tests: [] diff --git a/build_config.rb b/build_config.rb index ee3796534f2..98253e281fa 100644 --- a/build_config.rb +++ b/build_config.rb @@ -13,5 +13,5 @@ # limitations under the License. module GrpcBuildConfig - CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-15.dll' + CORE_WINDOWS_DLL = '/tmp/libs/opt/grpc-16.dll' end diff --git a/build_handwritten.yaml b/build_handwritten.yaml index 2da3f4a08b3..8aac341e925 100644 --- a/build_handwritten.yaml +++ b/build_handwritten.yaml @@ -12,11 +12,11 @@ settings: '#08': Use "-preN" suffixes to identify pre-release versions '#09': Per-language overrides are possible with (eg) ruby_version tag here '#10': See the expand_version.py for all the quirks here - core_version: 15.0.0 + core_version: 16.0.0 csharp_major_version: 2 - g_stands_for: gilded - protobuf_version: 3.15.2 - version: 1.37.0-dev + g_stands_for: guadalupe_river_park_conservancy + protobuf_version: 3.15.8 + version: 1.38.0-dev targets: - name: check_epollexclusive build: tool @@ -198,6 +198,7 @@ defaults: COREFLAGS: -fno-exceptions CPPFLAGS: -g -Wall -Wextra -DOSATOMIC_USE_INLINED=1 -Ithird_party/abseil-cpp -Ithird_party/re2 -Ithird_party/upb -Isrc/core/ext/upb-generated -Isrc/core/ext/upbdefs-generated + -Ithird_party/xxhash LDFLAGS: -g zlib: CFLAGS: -fvisibility=hidden diff --git a/cmake/modules/Findre2.cmake b/cmake/modules/Findre2.cmake index 41df4547138..e4f8e4d706b 100644 --- a/cmake/modules/Findre2.cmake +++ b/cmake/modules/Findre2.cmake @@ -18,6 +18,13 @@ if(re2_FOUND) return() endif() +# As per https://github.com/grpc/grpc/issues/25434, idempotence is necessary +# because CMake fails when another target with the same name already exists. +if(TARGET re2::re2) + message(STATUS "Found RE2 via pkg-config already?") + 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 diff --git a/cmake/xxhash.cmake b/cmake/xxhash.cmake new file mode 100644 index 00000000000..268ecef2a1c --- /dev/null +++ b/cmake/xxhash.cmake @@ -0,0 +1,15 @@ +# Copyright 2017 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(_gRPC_XXHASH_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/xxhash") diff --git a/config.m4 b/config.m4 index fa847df36eb..59653584807 100644 --- a/config.m4 +++ b/config.m4 @@ -14,6 +14,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl-with-bazel/src/include) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/re2) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/upb) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/xxhash) LIBS="-lpthread $LIBS" @@ -64,6 +65,7 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc \ src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \ src/core/ext/filters/client_channel/lb_policy/priority/priority.cc \ + src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc \ src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \ src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc \ src/core/ext/filters/client_channel/lb_policy/xds/cds.cc \ @@ -90,6 +92,8 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc \ src/core/ext/filters/client_channel/resolver_registry.cc \ src/core/ext/filters/client_channel/resolver_result_parsing.cc \ + src/core/ext/filters/client_channel/retry_filter.cc \ + src/core/ext/filters/client_channel/retry_service_config.cc \ src/core/ext/filters/client_channel/retry_throttle.cc \ src/core/ext/filters/client_channel/server_address.cc \ src/core/ext/filters/client_channel/service_config.cc \ @@ -99,6 +103,8 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/filters/client_channel/subchannel_pool_interface.cc \ src/core/ext/filters/client_idle/client_idle_filter.cc \ src/core/ext/filters/deadline/deadline_filter.cc \ + src/core/ext/filters/fault_injection/fault_injection_filter.cc \ + src/core/ext/filters/fault_injection/service_config_parser.cc \ src/core/ext/filters/http/client/http_client_filter.cc \ src/core/ext/filters/http/client_authority_filter.cc \ src/core/ext/filters/http/http_filters_plugin.cc \ @@ -144,9 +150,11 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/transport/chttp2/transport/writing.cc \ src/core/ext/transport/inproc/inproc_plugin.cc \ src/core/ext/transport/inproc/inproc_transport.cc \ + src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c \ src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c \ src/core/ext/upb-generated/envoy/annotations/resource.upb.c \ src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c \ + src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c \ src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c \ src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c \ src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c \ @@ -171,12 +179,16 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c \ src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c \ src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c \ + src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c \ + src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c \ src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c \ src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c \ src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c \ src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c \ src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c \ src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c \ + src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c \ + src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c \ src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c \ src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c \ @@ -191,11 +203,14 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c \ src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c \ src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c \ + src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c \ + src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c \ + src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c \ src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c \ src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c \ src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c \ @@ -234,9 +249,11 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upb-generated/xds/core/v3/resource.upb.c \ src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c \ src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c \ + src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c \ @@ -261,11 +278,15 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c \ @@ -280,11 +301,14 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c \ + src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c \ src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c \ @@ -323,8 +347,11 @@ if test "$PHP_GRPC" != "no"; then src/core/ext/xds/xds_certificate_provider.cc \ src/core/ext/xds/xds_client.cc \ src/core/ext/xds/xds_client_stats.cc \ + src/core/ext/xds/xds_http_fault_filter.cc \ src/core/ext/xds/xds_http_filters.cc \ src/core/ext/xds/xds_server_config_fetcher.cc \ + src/core/lib/address_utils/parse_address.cc \ + src/core/lib/address_utils/sockaddr_utils.cc \ src/core/lib/avl/avl.cc \ src/core/lib/backoff/backoff.cc \ src/core/lib/channel/channel_args.cc \ @@ -347,6 +374,8 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/debug/stats.cc \ src/core/lib/debug/stats_data.cc \ src/core/lib/debug/trace.cc \ + src/core/lib/event_engine/slice_allocator.cc \ + src/core/lib/event_engine/sockaddr.cc \ src/core/lib/gpr/alloc.cc \ src/core/lib/gpr/atm.cc \ src/core/lib/gpr/cpu_iphone.cc \ @@ -387,6 +416,7 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/gprpp/mpscq.cc \ src/core/lib/gprpp/stat_posix.cc \ src/core/lib/gprpp/stat_windows.cc \ + src/core/lib/gprpp/status_helper.cc \ src/core/lib/gprpp/thd_posix.cc \ src/core/lib/gprpp/thd_windows.cc \ src/core/lib/gprpp/time_util.cc \ @@ -435,8 +465,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/is_epollexclusive_available.cc \ src/core/lib/iomgr/load_file.cc \ src/core/lib/iomgr/lockfree_event.cc \ - src/core/lib/iomgr/parse_address.cc \ - src/core/lib/iomgr/poller/eventmanager_libuv.cc \ src/core/lib/iomgr/polling_entity.cc \ src/core/lib/iomgr/pollset.cc \ src/core/lib/iomgr/pollset_custom.cc \ @@ -450,7 +478,6 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/iomgr/resolve_address_posix.cc \ src/core/lib/iomgr/resolve_address_windows.cc \ src/core/lib/iomgr/resource_quota.cc \ - src/core/lib/iomgr/sockaddr_utils.cc \ src/core/lib/iomgr/socket_factory_posix.cc \ src/core/lib/iomgr/socket_mutator.cc \ src/core/lib/iomgr/socket_utils_common_posix.cc \ @@ -493,11 +520,9 @@ if test "$PHP_GRPC" != "no"; then src/core/lib/json/json_reader.cc \ src/core/lib/json/json_util.cc \ src/core/lib/json/json_writer.cc \ + src/core/lib/matchers/matchers.cc \ src/core/lib/profiling/basic_timers.cc \ src/core/lib/profiling/stap_timers.cc \ - src/core/lib/security/authorization/authorization_engine.cc \ - src/core/lib/security/authorization/evaluate_args.cc \ - src/core/lib/security/authorization/matchers.cc \ src/core/lib/security/context/security_context.cc \ src/core/lib/security/credentials/alts/alts_credentials.cc \ src/core/lib/security/credentials/alts/check_gcp_environment.cc \ @@ -651,6 +676,7 @@ if test "$PHP_GRPC" != "no"; then third_party/abseil-cpp/absl/debugging/symbolize.cc \ third_party/abseil-cpp/absl/hash/internal/city.cc \ third_party/abseil-cpp/absl/hash/internal/hash.cc \ + third_party/abseil-cpp/absl/hash/internal/wyhash.cc \ third_party/abseil-cpp/absl/numeric/int128.cc \ third_party/abseil-cpp/absl/status/status.cc \ third_party/abseil-cpp/absl/status/status_payload_printer.cc \ @@ -661,6 +687,8 @@ if test "$PHP_GRPC" != "no"; then third_party/abseil-cpp/absl/strings/escaping.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc \ third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc \ + third_party/abseil-cpp/absl/strings/internal/cord_internal.cc \ + third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc \ third_party/abseil-cpp/absl/strings/internal/escaping.cc \ third_party/abseil-cpp/absl/strings/internal/memutil.cc \ third_party/abseil-cpp/absl/strings/internal/ostringstream.cc \ @@ -813,7 +841,6 @@ if test "$PHP_GRPC" != "no"; then third_party/boringssl-with-bazel/src/crypto/ex_data.c \ third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c \ third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c \ - third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c \ third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c \ third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c \ third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c \ @@ -880,7 +907,6 @@ if test "$PHP_GRPC" != "no"; then third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_lu.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c \ - third_party/boringssl-with-bazel/src/crypto/x509/x509_r2x.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c \ third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c \ @@ -945,6 +971,7 @@ if test "$PHP_GRPC" != "no"; then third_party/boringssl-with-bazel/src/ssl/d1_srtp.cc \ third_party/boringssl-with-bazel/src/ssl/dtls_method.cc \ third_party/boringssl-with-bazel/src/ssl/dtls_record.cc \ + third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc \ third_party/boringssl-with-bazel/src/ssl/handoff.cc \ third_party/boringssl-with-bazel/src/ssl/handshake.cc \ third_party/boringssl-with-bazel/src/ssl/handshake_client.cc \ @@ -1001,8 +1028,6 @@ if test "$PHP_GRPC" != "no"; then third_party/upb/upb/decode_fast.c \ third_party/upb/upb/def.c \ third_party/upb/upb/encode.c \ - third_party/upb/upb/json_decode.c \ - third_party/upb/upb/json_encode.c \ third_party/upb/upb/msg.c \ third_party/upb/upb/reflection.c \ third_party/upb/upb/table.c \ @@ -1020,6 +1045,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/pick_first) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/priority) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/ring_hash) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/round_robin) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/weighted_target) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/xds) @@ -1032,6 +1058,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/resolver/xds) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_idle) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/deadline) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/fault_injection) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/http) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/http/client) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/http/message_compress) @@ -1048,16 +1075,22 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/server/secure) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/chttp2/transport) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/transport/inproc) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/admin/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/annotations) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/accesslog/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/bootstrap/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/cluster/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/core/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/endpoint/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/listener/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/metrics/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/overload/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/rbac/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/route/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/config/trace/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3) @@ -1067,6 +1100,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/listener/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/load_stats/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/route/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/service/status/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/metadata/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/envoy/type/tracing/v3) @@ -1083,15 +1117,21 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/udpa/type/v1) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/validate) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upb-generated/xds/core/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/admin/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/annotations) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/accesslog/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/cluster/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/core/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/endpoint/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/listener/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/metrics/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/overload/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/route/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/config/trace/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3) @@ -1101,6 +1141,7 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/listener/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/load_stats/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/route/v3) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/service/status/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/matcher/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/metadata/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/envoy/type/tracing/v3) @@ -1113,20 +1154,21 @@ if test "$PHP_GRPC" != "no"; then PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/validate) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/upbdefs-generated/xds/core/v3) PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/xds) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/address_utils) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/avl) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/backoff) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/channel) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/compression) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/debug) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/event_engine) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/gpr) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/gprpp) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/http) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr/executor) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/iomgr/poller) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/json) + PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/matchers) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/profiling) - PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/authorization) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/context) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials) PHP_ADD_BUILD_DIR($ext_builddir/src/core/lib/security/credentials/alts) diff --git a/config.w32 b/config.w32 index d45a565d962..1e65f5bfac7 100644 --- a/config.w32 +++ b/config.w32 @@ -31,6 +31,7 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\load_balancer_api.cc " + "src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first\\pick_first.cc " + "src\\core\\ext\\filters\\client_channel\\lb_policy\\priority\\priority.cc " + + "src\\core\\ext\\filters\\client_channel\\lb_policy\\ring_hash\\ring_hash.cc " + "src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin\\round_robin.cc " + "src\\core\\ext\\filters\\client_channel\\lb_policy\\weighted_target\\weighted_target.cc " + "src\\core\\ext\\filters\\client_channel\\lb_policy\\xds\\cds.cc " + @@ -57,6 +58,8 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\resolver\\xds\\xds_resolver.cc " + "src\\core\\ext\\filters\\client_channel\\resolver_registry.cc " + "src\\core\\ext\\filters\\client_channel\\resolver_result_parsing.cc " + + "src\\core\\ext\\filters\\client_channel\\retry_filter.cc " + + "src\\core\\ext\\filters\\client_channel\\retry_service_config.cc " + "src\\core\\ext\\filters\\client_channel\\retry_throttle.cc " + "src\\core\\ext\\filters\\client_channel\\server_address.cc " + "src\\core\\ext\\filters\\client_channel\\service_config.cc " + @@ -66,6 +69,8 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\filters\\client_channel\\subchannel_pool_interface.cc " + "src\\core\\ext\\filters\\client_idle\\client_idle_filter.cc " + "src\\core\\ext\\filters\\deadline\\deadline_filter.cc " + + "src\\core\\ext\\filters\\fault_injection\\fault_injection_filter.cc " + + "src\\core\\ext\\filters\\fault_injection\\service_config_parser.cc " + "src\\core\\ext\\filters\\http\\client\\http_client_filter.cc " + "src\\core\\ext\\filters\\http\\client_authority_filter.cc " + "src\\core\\ext\\filters\\http\\http_filters_plugin.cc " + @@ -111,9 +116,11 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\transport\\chttp2\\transport\\writing.cc " + "src\\core\\ext\\transport\\inproc\\inproc_plugin.cc " + "src\\core\\ext\\transport\\inproc\\inproc_transport.cc " + + "src\\core\\ext\\upb-generated\\envoy\\admin\\v3\\config_dump.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\annotations\\deprecation.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\annotations\\resource.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\accesslog\\v3\\accesslog.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\config\\bootstrap\\v3\\bootstrap.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\cluster\\v3\\circuit_breaker.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\cluster\\v3\\cluster.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\cluster\\v3\\filter.upb.c " + @@ -138,12 +145,16 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v3\\listener.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v3\\listener_components.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v3\\udp_listener_config.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\config\\metrics\\v3\\stats.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\config\\overload\\v3\\overload.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\rbac\\v3\\rbac.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\route\\v3\\route.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\route\\v3\\route_components.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\route\\v3\\scoped_route.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\config\\trace\\v3\\http_tracer.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\clusters\\aggregate\\v3\\cluster.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\common\\fault\\v3\\fault.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\fault\\v3\\fault.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\router\\v3\\router.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3\\http_connection_manager.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\cert.upb.c " + @@ -158,11 +169,14 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upb-generated\\envoy\\service\\load_stats\\v3\\lrs.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\service\\route\\v3\\rds.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\service\\route\\v3\\srds.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\service\\status\\v3\\csds.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\metadata.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\node.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\number.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\path.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\regex.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\string.upb.c " + + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\struct.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3\\value.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\metadata\\v3\\metadata.upb.c " + "src\\core\\ext\\upb-generated\\envoy\\type\\tracing\\v3\\custom_tag.upb.c " + @@ -201,9 +215,11 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upb-generated\\xds\\core\\v3\\resource.upb.c " + "src\\core\\ext\\upb-generated\\xds\\core\\v3\\resource_locator.upb.c " + "src\\core\\ext\\upb-generated\\xds\\core\\v3\\resource_name.upb.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\admin\\v3\\config_dump.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\annotations\\deprecation.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\annotations\\resource.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\accesslog\\v3\\accesslog.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\bootstrap\\v3\\bootstrap.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\cluster\\v3\\circuit_breaker.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\cluster\\v3\\cluster.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\cluster\\v3\\filter.upbdefs.c " + @@ -228,11 +244,15 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upbdefs-generated\\envoy\\config\\listener\\v3\\listener.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\listener\\v3\\listener_components.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\listener\\v3\\udp_listener_config.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\metrics\\v3\\stats.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\overload\\v3\\overload.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\route\\v3\\route.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\route\\v3\\route_components.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\route\\v3\\scoped_route.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\config\\trace\\v3\\http_tracer.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\clusters\\aggregate\\v3\\cluster.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\common\\fault\\v3\\fault.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\fault\\v3\\fault.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\router\\v3\\router.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\network\\http_connection_manager\\v3\\http_connection_manager.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\transport_sockets\\tls\\v3\\cert.upbdefs.c " + @@ -247,11 +267,14 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\upbdefs-generated\\envoy\\service\\load_stats\\v3\\lrs.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\service\\route\\v3\\rds.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\service\\route\\v3\\srds.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\service\\status\\v3\\csds.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\metadata.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\node.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\number.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\path.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\regex.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\string.upbdefs.c " + + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\struct.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3\\value.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\metadata\\v3\\metadata.upbdefs.c " + "src\\core\\ext\\upbdefs-generated\\envoy\\type\\tracing\\v3\\custom_tag.upbdefs.c " + @@ -290,8 +313,11 @@ if (PHP_GRPC != "no") { "src\\core\\ext\\xds\\xds_certificate_provider.cc " + "src\\core\\ext\\xds\\xds_client.cc " + "src\\core\\ext\\xds\\xds_client_stats.cc " + + "src\\core\\ext\\xds\\xds_http_fault_filter.cc " + "src\\core\\ext\\xds\\xds_http_filters.cc " + "src\\core\\ext\\xds\\xds_server_config_fetcher.cc " + + "src\\core\\lib\\address_utils\\parse_address.cc " + + "src\\core\\lib\\address_utils\\sockaddr_utils.cc " + "src\\core\\lib\\avl\\avl.cc " + "src\\core\\lib\\backoff\\backoff.cc " + "src\\core\\lib\\channel\\channel_args.cc " + @@ -314,6 +340,8 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\debug\\stats.cc " + "src\\core\\lib\\debug\\stats_data.cc " + "src\\core\\lib\\debug\\trace.cc " + + "src\\core\\lib\\event_engine\\slice_allocator.cc " + + "src\\core\\lib\\event_engine\\sockaddr.cc " + "src\\core\\lib\\gpr\\alloc.cc " + "src\\core\\lib\\gpr\\atm.cc " + "src\\core\\lib\\gpr\\cpu_iphone.cc " + @@ -354,6 +382,7 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\gprpp\\mpscq.cc " + "src\\core\\lib\\gprpp\\stat_posix.cc " + "src\\core\\lib\\gprpp\\stat_windows.cc " + + "src\\core\\lib\\gprpp\\status_helper.cc " + "src\\core\\lib\\gprpp\\thd_posix.cc " + "src\\core\\lib\\gprpp\\thd_windows.cc " + "src\\core\\lib\\gprpp\\time_util.cc " + @@ -402,8 +431,6 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\iomgr\\is_epollexclusive_available.cc " + "src\\core\\lib\\iomgr\\load_file.cc " + "src\\core\\lib\\iomgr\\lockfree_event.cc " + - "src\\core\\lib\\iomgr\\parse_address.cc " + - "src\\core\\lib\\iomgr\\poller\\eventmanager_libuv.cc " + "src\\core\\lib\\iomgr\\polling_entity.cc " + "src\\core\\lib\\iomgr\\pollset.cc " + "src\\core\\lib\\iomgr\\pollset_custom.cc " + @@ -417,7 +444,6 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\iomgr\\resolve_address_posix.cc " + "src\\core\\lib\\iomgr\\resolve_address_windows.cc " + "src\\core\\lib\\iomgr\\resource_quota.cc " + - "src\\core\\lib\\iomgr\\sockaddr_utils.cc " + "src\\core\\lib\\iomgr\\socket_factory_posix.cc " + "src\\core\\lib\\iomgr\\socket_mutator.cc " + "src\\core\\lib\\iomgr\\socket_utils_common_posix.cc " + @@ -460,11 +486,9 @@ if (PHP_GRPC != "no") { "src\\core\\lib\\json\\json_reader.cc " + "src\\core\\lib\\json\\json_util.cc " + "src\\core\\lib\\json\\json_writer.cc " + + "src\\core\\lib\\matchers\\matchers.cc " + "src\\core\\lib\\profiling\\basic_timers.cc " + "src\\core\\lib\\profiling\\stap_timers.cc " + - "src\\core\\lib\\security\\authorization\\authorization_engine.cc " + - "src\\core\\lib\\security\\authorization\\evaluate_args.cc " + - "src\\core\\lib\\security\\authorization\\matchers.cc " + "src\\core\\lib\\security\\context\\security_context.cc " + "src\\core\\lib\\security\\credentials\\alts\\alts_credentials.cc " + "src\\core\\lib\\security\\credentials\\alts\\check_gcp_environment.cc " + @@ -618,6 +642,7 @@ if (PHP_GRPC != "no") { "third_party\\abseil-cpp\\absl\\debugging\\symbolize.cc " + "third_party\\abseil-cpp\\absl\\hash\\internal\\city.cc " + "third_party\\abseil-cpp\\absl\\hash\\internal\\hash.cc " + + "third_party\\abseil-cpp\\absl\\hash\\internal\\wyhash.cc " + "third_party\\abseil-cpp\\absl\\numeric\\int128.cc " + "third_party\\abseil-cpp\\absl\\status\\status.cc " + "third_party\\abseil-cpp\\absl\\status\\status_payload_printer.cc " + @@ -628,6 +653,8 @@ if (PHP_GRPC != "no") { "third_party\\abseil-cpp\\absl\\strings\\escaping.cc " + "third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_bigint.cc " + "third_party\\abseil-cpp\\absl\\strings\\internal\\charconv_parse.cc " + + "third_party\\abseil-cpp\\absl\\strings\\internal\\cord_internal.cc " + + "third_party\\abseil-cpp\\absl\\strings\\internal\\cord_rep_ring.cc " + "third_party\\abseil-cpp\\absl\\strings\\internal\\escaping.cc " + "third_party\\abseil-cpp\\absl\\strings\\internal\\memutil.cc " + "third_party\\abseil-cpp\\absl\\strings\\internal\\ostringstream.cc " + @@ -780,7 +807,6 @@ if (PHP_GRPC != "no") { "third_party\\boringssl-with-bazel\\src\\crypto\\ex_data.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule\\bcm.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule\\fips_shared_support.c " + - "third_party\\boringssl-with-bazel\\src\\crypto\\fipsmodule\\is_fips.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\hkdf\\hkdf.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\hpke\\hpke.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\hrss\\hrss.c " + @@ -847,7 +873,6 @@ if (PHP_GRPC != "no") { "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\x509_ext.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\x509_lu.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\x509_obj.c " + - "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\x509_r2x.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\x509_req.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\x509_set.c " + "third_party\\boringssl-with-bazel\\src\\crypto\\x509\\x509_trs.c " + @@ -912,6 +937,7 @@ if (PHP_GRPC != "no") { "third_party\\boringssl-with-bazel\\src\\ssl\\d1_srtp.cc " + "third_party\\boringssl-with-bazel\\src\\ssl\\dtls_method.cc " + "third_party\\boringssl-with-bazel\\src\\ssl\\dtls_record.cc " + + "third_party\\boringssl-with-bazel\\src\\ssl\\encrypted_client_hello.cc " + "third_party\\boringssl-with-bazel\\src\\ssl\\handoff.cc " + "third_party\\boringssl-with-bazel\\src\\ssl\\handshake.cc " + "third_party\\boringssl-with-bazel\\src\\ssl\\handshake_client.cc " + @@ -968,8 +994,6 @@ if (PHP_GRPC != "no") { "third_party\\upb\\upb\\decode_fast.c " + "third_party\\upb\\upb\\def.c " + "third_party\\upb\\upb\\encode.c " + - "third_party\\upb\\upb\\json_decode.c " + - "third_party\\upb\\upb\\json_encode.c " + "third_party\\upb\\upb\\msg.c " + "third_party\\upb\\upb\\reflection.c " + "third_party\\upb\\upb\\table.c " + @@ -1004,6 +1028,7 @@ if (PHP_GRPC != "no") { "/I"+configure_module_dirname+"\\third_party\\boringssl-with-bazel\\src\\include "+ "/I"+configure_module_dirname+"\\third_party\\re2 "+ "/I"+configure_module_dirname+"\\third_party\\upb "+ + "/I"+configure_module_dirname+"\\third_party\\xxhash "+ "/I"+configure_module_dirname+"\\third_party\\zlib "); base_dir = get_define('BUILD_DIR'); @@ -1020,6 +1045,7 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\priority"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\ring_hash"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\weighted_target"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\lb_policy\\xds"); @@ -1033,6 +1059,7 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_channel\\resolver\\xds"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\client_idle"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\deadline"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\fault_injection"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\client"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\filters\\http\\message_compress"); @@ -1053,10 +1080,14 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\transport\\inproc"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\admin"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\admin\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\annotations"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\accesslog"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\accesslog\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\bootstrap"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\bootstrap\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\cluster"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\cluster\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\core"); @@ -1065,6 +1096,10 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\endpoint\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\listener"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\listener\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\metrics"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\metrics\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\overload"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\overload\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\rbac"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\rbac\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\config\\route"); @@ -1076,7 +1111,12 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\clusters\\aggregate"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\clusters\\aggregate\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\common"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\common\\fault"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\common\\fault\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\fault"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\fault\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\router"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\http\\router\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\extensions\\filters\\network"); @@ -1098,6 +1138,8 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service\\load_stats\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service\\route"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service\\route\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service\\status"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\service\\status\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\type"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\type\\matcher"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\envoy\\type\\matcher\\v3"); @@ -1133,10 +1175,14 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upb-generated\\xds\\core\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\admin"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\admin\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\annotations"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\accesslog"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\accesslog\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\bootstrap"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\bootstrap\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\cluster"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\cluster\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\core"); @@ -1145,6 +1191,10 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\endpoint\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\listener"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\listener\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\metrics"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\metrics\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\overload"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\overload\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\route"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\route\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\config\\trace"); @@ -1154,7 +1204,12 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\clusters\\aggregate"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\clusters\\aggregate\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\common"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\common\\fault"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\common\\fault\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\fault"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\fault\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\router"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\http\\router\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\extensions\\filters\\network"); @@ -1176,6 +1231,8 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\service\\load_stats\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\service\\route"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\service\\route\\v3"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\service\\status"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\service\\status\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\type"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\envoy\\type\\matcher\\v3"); @@ -1198,21 +1255,22 @@ if (PHP_GRPC != "no") { FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\upbdefs-generated\\xds\\core\\v3"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\ext\\xds"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\address_utils"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\avl"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\backoff"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\channel"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\compression"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\debug"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\event_engine"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\gpr"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\gprpp"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\http"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\iomgr"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\iomgr\\executor"); - FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\iomgr\\poller"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\json"); + FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\matchers"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\profiling"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security"); - FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\authorization"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\context"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials"); FSO.CreateFolder(base_dir+"\\ext\\grpc\\src\\core\\lib\\security\\credentials\\alts"); diff --git a/doc/PROTOCOL-WEB.md b/doc/PROTOCOL-WEB.md index 1ee93606f65..c3f9169b331 100644 --- a/doc/PROTOCOL-WEB.md +++ b/doc/PROTOCOL-WEB.md @@ -137,5 +137,5 @@ Versioning --- Browser-specific features - -* For features that are unique to browser or HTML clients, check the [spec doc](https://github.com/grpc/grpc-web/blob/master/BROWSER-FEATURES.md) published in the grpc/grpc-web repo. + +* For features that are unique to browser or HTML clients, check the [spec doc](https://github.com/grpc/grpc-web/blob/master/doc/browser-features.md) published in the grpc/grpc-web repo. diff --git a/doc/command_line_tool.md b/doc/command_line_tool.md index be95a6d4f72..e303b0853d4 100644 --- a/doc/command_line_tool.md +++ b/doc/command_line_tool.md @@ -176,7 +176,8 @@ We can send RPCs to a server and get responses using `grpc_cli call` command. ``` If the proto file is not under the current directory, you can use - `--proto_path` to specify a new search root. + `--proto_path` to specify new search roots + (separated by colon on Mac/Linux/Cygwin or semicolon on Windows). Note that the tool will always attempt to use the reflection service first, falling back to local proto files if the service is not found. Use diff --git a/doc/core/grpc-error.md b/doc/core/grpc-error.md index 105a6482845..dc0e0ea92bc 100644 --- a/doc/core/grpc-error.md +++ b/doc/core/grpc-error.md @@ -56,8 +56,8 @@ For example, in the following code block, error1 and error2 are owned by the current function. ```C -grpc_error* error1 = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); -grpc_error* error2 = some_operation_that_might_fail(...); +grpc_error_handle error1 = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); +grpc_error_handle error2 = some_operation_that_might_fail(...); ``` The current function would have to explicitly call GRPC_ERROR_UNREF on the @@ -71,24 +71,24 @@ errors, or pass them along to a function that would take over the ownership. A `grpc_closure` callback function is any function that has the signature: ```C -void (*cb)(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error); +void (*cb)(void *arg, grpc_error_handle error); ``` This means that the error ownership is NOT transferred when a functions calls: ```C -c->cb(exec_ctx, c->cb_arg, err); +c->cb(c->cb_arg, err); ``` The caller is still responsible for unref-ing the error. -However, the above line is currently being phased out! It is safer to invoke -callbacks with `GRPC_CLOSURE_RUN` and `GRPC_CLOSURE_SCHED`. These functions are -not callbacks, so they will take ownership of the error passed to them. +Note that you'll likely never need to run `c->cb(...)` yourself; the idiomatic +way to execute callbacks is via the `Closure::Run` method, which takes ownership +of the error variable. ```C -grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); -GRPC_CLOSURE_RUN(exec_ctx, cb, error); +grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); +grpc_core::Closure::Run(DEBUG_LOCATION, c->cb, error); // current function no longer has ownership of the error ``` @@ -96,8 +96,8 @@ If you schedule or run a closure, but still need ownership of the error, then you must explicitly take a reference. ```C -grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); -GRPC_CLOSURE_RUN(exec_ctx, cb, GRPC_ERROR_REF(error)); +grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); +grpc_core::Closure::Run(DEBUG_LOCATION, c->cb, GRPC_ERROR_REF(error)); // do some other things with the error GRPC_ERROR_UNREF(error); ``` @@ -109,7 +109,7 @@ would take ownership of the error, without explicitly taking ownership yourself. For example: ```C -void on_some_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { +void on_some_action(void *arg, grpc_error_handle error) { // this would cause a crash, because some_function will unref the error, // and the caller of this callback will also unref it. some_function(error); @@ -128,7 +128,7 @@ void on_some_action(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { Take the following example: ```C -grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); +grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error occurred"); // do some things some_function(error); // can't use error anymore! might be gone. @@ -142,7 +142,7 @@ if would have to take on a reference to it. This is a common pattern seen. ```C void func() { - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error"); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Some error"); some_function(GRPC_ERROR_REF(error)); // do things some_other_function(GRPC_ERROR_REF(error)); diff --git a/doc/g_stands_for.md b/doc/g_stands_for.md index 17f392b7610..25facbecc03 100644 --- a/doc/g_stands_for.md +++ b/doc/g_stands_for.md @@ -36,4 +36,5 @@ - 1.34 'g' stands for ['gauntlet'](https://github.com/grpc/grpc/tree/v1.34.x) - 1.35 'g' stands for ['gecko'](https://github.com/grpc/grpc/tree/v1.35.x) - 1.36 'g' stands for ['gummybear'](https://github.com/grpc/grpc/tree/v1.36.x) -- 1.37 'g' stands for ['gilded'](https://github.com/grpc/grpc/tree/master) +- 1.37 'g' stands for ['gilded'](https://github.com/grpc/grpc/tree/v1.37.x) +- 1.38 'g' stands for ['guadalupe_river_park_conservancy'](https://github.com/grpc/grpc/tree/master) diff --git a/doc/grpc_xds_features.md b/doc/grpc_xds_features.md index 49711c0890e..8c3332af180 100644 --- a/doc/grpc_xds_features.md +++ b/doc/grpc_xds_features.md @@ -41,5 +41,10 @@ Features | gRFCs | [C++, Python,
Ruby, PHP](https://github.com/grpc/grpc/re ---------|--------|--------------|------|------|------ **xDS Infrastructure in gRPC client channel:** | [A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) | v1.30.0 | v1.30.0 | v1.30.0 | v1.2.0 | **Load Balancing:** | [A27](https://github.com/grpc/proposal/blob/master/A27-xds-global-load-balancing.md) | v1.30.0 | v1.30.0 | v1.30.0 | v1.2.0 | -Request matching based on:Request routing to multiple clusters based on [weights](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-weightedcluster) | [A28](https://github.com/grpc/proposal/blob/master/A28-xds-traffic-splitting-and-routing.md) | v1.31.0 | v1.31.0 | v1.31.0 | | -Case insensitive prefix/full path matching: | | v1.34.0 | v1.34.0 | v1.34.0 | | +Request matching based on:Request routing to multiple clusters based on [weights](https://www.envoyproxy.io/docs/envoy/latest/api-v2/api/v2/route/route_components.proto#route-weightedcluster) | [A28](https://github.com/grpc/proposal/blob/master/A28-xds-traffic-splitting-and-routing.md) | v1.31.0 | v1.31.0 | v1.31.0 | v1.3.0 | +Case insensitive prefix/full path matching: | | v1.34.0 | v1.34.0 | v1.34.0 | v1.3.0 | +Support for [xDS v3 APIs](https://www.envoyproxy.io/docs/envoy/latest/api-v3/api) | [A30](https://github.com/grpc/proposal/blob/master/A30-xds-v3.md) | v1.36.0 | v1.36.0 | v1.36.0 | | +[Maximum Stream Duration](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/route/v3/route_components.proto#config-route-v3-routeaction-maxstreamduration): | [A31](https://github.com/grpc/proposal/blob/master/A31-xds-timeout-support-and-config-selector.md) | v1.37.1 | v1.37.0 | v1.37.0 | | +[Circuit Breaking](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/circuit_breaker.proto): | [A32](https://github.com/grpc/proposal/blob/master/A32-xds-circuit-breaking.md) | v1.37.1 (N/A for PHP) | v1.37.0 | v1.37.0 | | +[Fault Injection](https://www.envoyproxy.io/docs/envoy/latest/api-v3/extensions/filters/http/fault/v3/fault.proto):
Only the following fields are supported: | [A33](https://github.com/grpc/proposal/blob/master/A33-Fault-Injection.md) | v1.37.1 | v1.37.0 | v1.37.0 | | +[Client Status Discovery Service](https://github.com/envoyproxy/envoy/blob/main/api/envoy/service/status/v3/csds.proto) | [A40](https://github.com/grpc/proposal/blob/master/A40-csds-support.md) | v1.37.1 (Only C++) | v1.37.0 | v1.37.0 | | diff --git a/doc/interop-test-descriptions.md b/doc/interop-test-descriptions.md index f7fbb48148a..524ccf52c67 100755 --- a/doc/interop-test-descriptions.md +++ b/doc/interop-test-descriptions.md @@ -35,7 +35,10 @@ Clients should accept these arguments: * OAuth scope. For example, "https://www.googleapis.com/auth/xapi.zoo" * --service_account_key_file=PATH * The path to the service account JSON key file generated from GCE developer - console. + console. +* --service_config_json=SERVICE_CONFIG_JSON + * Disables service config lookups and sets the provided string as the + default service config. Clients must support TLS with ALPN. Clients must not disable certificate checking. diff --git a/doc/keepalive.md b/doc/keepalive.md index b598a2822df..f773bd87b94 100644 --- a/doc/keepalive.md +++ b/doc/keepalive.md @@ -4,25 +4,27 @@ The keepalive ping is a way to check if a channel is currently working by sendin This guide documents the knobs within gRPC core to control the current behavior of the keepalive ping. -The keepalive ping is controlled by two important channel arguments - +The keepalive ping in core is controlled by the following channel arguments - * **GRPC_ARG_KEEPALIVE_TIME_MS** * This channel argument controls the period (in milliseconds) after which a keepalive ping is sent on the transport. * **GRPC_ARG_KEEPALIVE_TIMEOUT_MS** * This channel argument controls the amount of time (in milliseconds) the sender of the keepalive ping waits for an acknowledgement. If it does not receive an acknowledgment within this time, it will close the connection. - -The above two channel arguments should be sufficient for most users, but the following arguments can also be useful in certain use cases. - +* **GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA** + * This channel argument controls the maximum number of pings that can be sent when there is no data/header frame to be sent. gRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without such a restriction. (Note that this is an unfortunate setting that does not agree with [A8-client-side-keepalive.md](https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md). There should ideally be no such restriction on the keepalive ping and we plan to deprecate it in the future.) * **GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS** * This channel argument if set to 1 (0 : false; 1 : true), allows keepalive pings to be sent even if there are no calls in flight. -* **GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA** - * This channel argument controls the maximum number of pings that can be sent when there is no data/header frame to be sent. GRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without such a restriction. + +On the server-side, the following additional channel arguments need to be configured - + * **GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS** * If there are no data/header frames being sent on the transport, this channel argument on the server side controls the minimum time (in milliseconds) that gRPC Core would expect between receiving successive pings. If the time between successive pings is less that than this time, then the ping will be considered a bad ping from the peer. Such a ping counts as a ‘ping strike’. On the client side, this does not have any effect. * **GRPC_ARG_HTTP2_MAX_PING_STRIKES** * This arg controls the maximum number of bad pings that the server will tolerate before sending an HTTP2 GOAWAY frame and closing the transport. Setting it to 0 allows the server to accept any number of bad pings. +**IMPORTANT NOTE** - For keepalive to work properly and as intended, all of the above channel arguments should be configured appropriately. The client-side keepalive settings should also be in agreement with the server-side settings. If a client sends pings more often than the server is willing to accept, the connection will be terminated with a GOAWAY frame with "too_many_pings" as the debug data. + ### Defaults Values Channel Argument| Client|Server @@ -46,3 +48,7 @@ GRPC_ARG_HTTP2_MAX_PING_STRIKES|N/A|2 * A server sends a GOAWAY with `ENHANCE_YOUR_CALM` if the client sends too many misbehaving pings as described in [A8-client-side-keepalive.md](https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md). Some scenarios where this can happen are - * if a server has `GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS` set to false while the client has set this to true resulting in keepalive pings being sent even when there is no call in flight. * if the client's `GRPC_ARG_KEEPALIVE_TIME_MS` setting is lower than the server's `GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS`. +* Why is my client not sending keepalive pings even after configuring `GRPC_ARG_KEEPALIVE_TIME_MS` and `GRPC_ARG_KEEPALIVE_TIMEOUT_MS`? + * This can happen in the following cases - + * There are no RPCs in flight and `GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS` has not been set to 1(defaults to 0). If we require the endpoint to be able to send pings even when there are no ongoing RPCs, `GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS` should be set to 1 as documented above. + * When there isn't any data/header being sent on the transport, gRPC clients restrict the number of pings to 2 by default. Setting `GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA` to 0 will remove this limit. diff --git a/doc/python/sphinx/grpc_admin.rst b/doc/python/sphinx/grpc_admin.rst new file mode 100644 index 00000000000..40ae9f0ba0e --- /dev/null +++ b/doc/python/sphinx/grpc_admin.rst @@ -0,0 +1,14 @@ +gRPC Admin +========== + +What is gRPC Admin? +--------------------------------------------- + +It's a convenient API to improve the usability of creating a gRPC server with admin services to expose states in the gRPC library. + +Design Document `gRPC Admin Interface `_ + +Module Contents +--------------- + +.. automodule:: grpc_admin diff --git a/doc/python/sphinx/grpc_asyncio.rst b/doc/python/sphinx/grpc_asyncio.rst index b0ba347cd9b..39584c3a045 100644 --- a/doc/python/sphinx/grpc_asyncio.rst +++ b/doc/python/sphinx/grpc_asyncio.rst @@ -76,6 +76,11 @@ gRPC Exceptions .. autoexception:: InternalError .. autoexception:: AioRpcError +gRPC Metadata +^^^^^^^^^^^^^ + +.. autoclass:: Metadata + Shared Context ^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/python/sphinx/grpc_csds.rst b/doc/python/sphinx/grpc_csds.rst new file mode 100644 index 00000000000..e1550c7ff01 --- /dev/null +++ b/doc/python/sphinx/grpc_csds.rst @@ -0,0 +1,14 @@ +gRPC CSDS +========= + +What is gRPC CSDS? +--------------------------------------------- + +In short, it's a xDS configuration dump protocol. + +Design Document `gRPC CSDS `_ + +Module Contents +--------------- + +.. automodule:: grpc_csds diff --git a/doc/python/sphinx/index.rst b/doc/python/sphinx/index.rst index c033542cf27..2bdd60b826d 100644 --- a/doc/python/sphinx/index.rst +++ b/doc/python/sphinx/index.rst @@ -11,7 +11,9 @@ API Reference grpc grpc_asyncio + grpc_admin grpc_channelz + grpc_csds grpc_health_checking grpc_reflection grpc_status diff --git a/doc/service_config.md b/doc/service_config.md index 928f27bcd80..57f5e1989e8 100644 --- a/doc/service_config.md +++ b/doc/service_config.md @@ -8,12 +8,38 @@ parameters to be automatically used by all clients of their service. # Format -The format of the service config is defined by the +The fields of the service config are defined by the [`grpc.service_config.ServiceConfig` protocol buffer message](https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto). Note that new fields may be added in the future as new functionality is introduced. +Internally, gRPC uses the service config in JSON form. The JSON +representation is the result of converting the protobuf form into JSON +using the normal [protobuf to JSON translation +rules](https://developers.google.com/protocol-buffers/docs/proto3#json). +In particular, this means: +- Field names are converted from `snake_case` to `camelCase`. +- Field values are converted as per the documented translation rules: + - Strings, 32-bit integers, and bools are converted into the + corresponding JSON types. + - 64-bit integers are converted into strings (e.g., `"251"`). + - The value of a repeated field will be represented as a JSON array. + - The value of a `google.protobuf.Duration` will be represented as a + string containing a decimal number of seconds (e.g., `"1.000340012s"`). + +For more details, see the protobuf docs linked above. + +Note that the JSON representation has one advantage over the protobuf +representation, which is that it is possible to encode configurations +for [LB policies](load-balancing.md) that are not known to gRPC. In +protobuf form, the `loadBalancingConfig` field contains a `oneof` +supporting only the built-in LB policies. However, in JSON form, the +field inside the `oneof` is encoded as a string that indicates the LB +policy name. In JSON form, that string can be any arbitrary value, not +just one of the supported policies inside of the `oneof`, so third-party +policies can be selected. + # Architecture A service config is associated with a server name. The [name @@ -23,11 +49,10 @@ name, will return both the resolved addresses and the service config. The name resolver returns the service config to the gRPC client in JSON form. Individual resolver implementations determine where and in what format the service config is stored. If the resolver implemention obtains the -service config in protobuf form, it must convert it to JSON using the -normal [protobuf to JSON translation -rules](https://developers.google.com/protocol-buffers/docs/proto3#json). +service config in protobuf form, it must convert it to JSON. Alternatively, a resolver implementation may obtain the service config -already in JSON form, in which case it may return it directly. +already in JSON form, in which case it may return it directly. Or it +may construct the JSON dynamically from some other source data. For details of how the DNS resolver plugin supports service configs, see [gRFC A2: Service Config via @@ -71,7 +96,7 @@ Here is the same example service config in JSON form: { "service": "foo", "method": "bar" }, { "service": "baz" } ], - "timeout": "1.0000000001s" + "timeout": "1.000000001s" } ] } diff --git a/doc/xds-test-descriptions.md b/doc/xds-test-descriptions.md index 83771d29ea8..6a82a7bf387 100644 --- a/doc/xds-test-descriptions.md +++ b/doc/xds-test-descriptions.md @@ -69,6 +69,9 @@ message ClientConfigureRequest { repeated RpcType types = 1; // The collection of custom metadata to be attached to RPCs sent by the client. repeated Metadata metadata = 2; + // The deadline to use, in seconds, for all RPCs. If unset or zero, the + // client will use the default from the command-line. + int32 timeout_sec = 3; } message ClientConfigureResponse {} @@ -81,7 +84,7 @@ service XdsUpdateClientConfigureService { The test client changes its behavior right after receiving the `ClientConfigureRequest`. Currently it only supports configuring the type(s) -of RPCs sent by the test client and metadata attached to each type of RPCs. +of RPCs sent by the test client, metadata attached to each type of RPCs, and the timeout. ## Test Driver @@ -105,21 +108,42 @@ message LoadBalancerStatsRequest { } message LoadBalancerStatsResponse { + message RpcsByPeer { + // The number of completed RPCs for each peer. + map rpcs_by_peer = 1; + } // The number of completed RPCs for each peer. map rpcs_by_peer = 1; // The number of RPCs that failed to record a remote peer. int32 num_failures = 2; + map rpcs_by_method = 3; } message LoadBalancerAccumulatedStatsRequest {} message LoadBalancerAccumulatedStatsResponse { // The total number of RPCs have ever issued for each type. - map num_rpcs_started_by_method = 1; + // Deprecated: use stats_per_method.rpcs_started instead. + map num_rpcs_started_by_method = 1 [deprecated = true]; // The total number of RPCs have ever completed successfully for each type. - map num_rpcs_succeeded_by_method = 2; + // Deprecated: use stats_per_method.result instead. + map num_rpcs_succeeded_by_method = 2 [deprecated = true]; // The total number of RPCs have ever failed for each type. - map num_rpcs_failed_by_method = 3; + // Deprecated: use stats_per_method.result instead. + map num_rpcs_failed_by_method = 3 [deprecated = true]; + + message MethodStats { + // The number of RPCs that were started for this method. + int32 rpcs_started = 1; + + // The number of RPCs that completed with each status for this method. The + // key is the integral value of a google.rpc.Code; the value is the count. + map result = 2; + } + + // Per-method RPC statistics. The key is the RpcType in string form; e.g. + // 'EMPTY_CALL' or 'UNARY_CALL' + map stats_per_method = 4; } service LoadBalancerStatsService { diff --git a/examples/cpp/compression/CMakeLists.txt b/examples/cpp/compression/CMakeLists.txt new file mode 100644 index 00000000000..bac7903396f --- /dev/null +++ b/examples/cpp/compression/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright 2021 the gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ helloworld example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building helloworld. + +cmake_minimum_required(VERSION 3.5.1) + +project(Compression C CXX) + +include(../cmake/common.cmake) + +# Proto file +get_filename_component(hw_proto "../../protos/helloworld.proto" ABSOLUTE) +get_filename_component(hw_proto_path "${hw_proto}" PATH) + +# Generated sources +set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc") +set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h") +set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc") +set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h") +add_custom_command( + OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${hw_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${hw_proto}" + DEPENDS "${hw_proto}") + +# Include generated *.pb.h files +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# hw_grpc_proto +add_library(hw_grpc_proto + ${hw_grpc_srcs} + ${hw_grpc_hdrs} + ${hw_proto_srcs} + ${hw_proto_hdrs}) +target_link_libraries(hw_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + +# Targets greeter_(client|server) +foreach(_target + greeter_client greeter_server) + add_executable(${_target} "${_target}.cc") + target_link_libraries(${_target} + hw_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) +endforeach() diff --git a/examples/cpp/compression/greeter_client.cc b/examples/cpp/compression/greeter_client.cc index 99e2a5973fc..b1ef4546d8a 100644 --- a/examples/cpp/compression/greeter_client.cc +++ b/examples/cpp/compression/greeter_client.cc @@ -32,9 +32,9 @@ using grpc::Channel; using grpc::ChannelArguments; using grpc::ClientContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; class GreeterClient { public: diff --git a/examples/cpp/compression/greeter_server.cc b/examples/cpp/compression/greeter_server.cc index 7399017afb7..dc1b1f6530f 100644 --- a/examples/cpp/compression/greeter_server.cc +++ b/examples/cpp/compression/greeter_server.cc @@ -32,9 +32,9 @@ using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; // Logic and data behind the server's behavior. class GreeterServiceImpl final : public Greeter::Service { diff --git a/examples/cpp/helloworld/BUILD b/examples/cpp/helloworld/BUILD index ac13e5282ff..747f0b22997 100644 --- a/examples/cpp/helloworld/BUILD +++ b/examples/cpp/helloworld/BUILD @@ -44,6 +44,18 @@ cc_binary( ], ) +cc_binary( + name = "xds_greeter_client", + srcs = ["xds_greeter_client.cc"], + defines = ["BAZEL_BUILD"], + deps = [ + "//:grpc++", + "//examples/protos:helloworld_cc_grpc", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/flags:parse", + ], +) + cc_binary( name = "greeter_server", srcs = ["greeter_server.cc"], @@ -64,3 +76,17 @@ cc_binary( "//examples/protos:helloworld_cc_grpc", ], ) + +cc_binary( + name = "xds_greeter_server", + srcs = ["xds_greeter_server.cc"], + defines = ["BAZEL_BUILD"], + deps = [ + "//:grpc++", + "//:grpc++_reflection", + "//:grpcpp_admin", + "//examples/protos:helloworld_cc_grpc", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/flags:parse", + ], +) diff --git a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/AppDelegate.h b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/AppDelegate.h index 91ba988c4ae..3ec86f1b31f 100644 --- a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/AppDelegate.h +++ b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/AppDelegate.h @@ -19,5 +19,5 @@ #import @interface AppDelegate : UIResponder -@property (strong, nonatomic) UIWindow *window; +@property(strong, nonatomic) UIWindow *window; @end diff --git a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.h b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.h index 28d4ca09614..673d49bf77f 100644 --- a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.h +++ b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.h @@ -20,4 +20,3 @@ @interface ViewController : UIViewController @end - diff --git a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.mm b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.mm index 36294848663..abdf9178b5d 100644 --- a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.mm +++ b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/ViewController.mm @@ -18,14 +18,15 @@ #import "ViewController.h" #import -#include + #include +#include static void* tag(int i) { return (void*)(intptr_t)i; } // Serialized Proto bytes of Hello World example -const uint8_t kMessage[] = - {0x0A, 0x0B, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2D, 0x43}; +const uint8_t kMessage[] = {0x0A, 0x0B, 0x4F, 0x62, 0x6A, 0x65, 0x63, + 0x74, 0x69, 0x76, 0x65, 0x2D, 0x43}; @interface ViewController () @@ -57,7 +58,7 @@ const uint8_t kMessage[] = abort(); } grpc::Slice send_slice = grpc::Slice(kMessage, sizeof(kMessage) / sizeof(kMessage[0])); - std::unique_ptr send_buffer(new grpc::ByteBuffer(&send_slice, 1)); + std::unique_ptr send_buffer(new grpc::ByteBuffer(&send_slice, 1)); call->Write(*send_buffer, tag(2)); cq_.Next(&got_tag, &ok); if (!ok || got_tag != tag(2)) { @@ -85,17 +86,17 @@ const uint8_t kMessage[] = } std::vector slices; recv_buffer.Dump(&slices); - NSString *recvBytes = [[NSString alloc] init]; + NSString* recvBytes = [[NSString alloc] init]; for (auto slice : slices) { auto p = slice.begin(); while (p != slice.end()) { - recvBytes = - [recvBytes stringByAppendingString:[NSString stringWithFormat:@"%02x ", *p]]; + recvBytes = [recvBytes stringByAppendingString:[NSString stringWithFormat:@"%02x ", *p]]; p++; } } NSLog(@"Hello World succeeded.\nReceived bytes: %@\n" - "Expected bytes: 0a 11 48 65 6c 6c 6f 20 4f 62 6a 65 63 74 69 76 65 2d 43", recvBytes); + "Expected bytes: 0a 11 48 65 6c 6c 6f 20 4f 62 6a 65 63 74 69 76 65 2d 43", + recvBytes); } @end diff --git a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/main.m b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/main.m index a3a22258067..8ee64b0ecb1 100644 --- a/examples/cpp/helloworld/cocoapods/HelloWorldCpp/main.m +++ b/examples/cpp/helloworld/cocoapods/HelloWorldCpp/main.m @@ -19,8 +19,8 @@ #import #import "AppDelegate.h" -int main(int argc, char * argv[]) { +int main(int argc, char* argv[]) { @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } diff --git a/examples/cpp/helloworld/greeter_async_client.cc b/examples/cpp/helloworld/greeter_async_client.cc index 9b1def6d1da..ab02bbc478a 100644 --- a/examples/cpp/helloworld/greeter_async_client.cc +++ b/examples/cpp/helloworld/greeter_async_client.cc @@ -20,8 +20,8 @@ #include #include -#include #include +#include #ifdef BAZEL_BUILD #include "examples/protos/helloworld.grpc.pb.h" @@ -34,9 +34,9 @@ using grpc::ClientAsyncResponseReader; using grpc::ClientContext; using grpc::CompletionQueue; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; class GreeterClient { public: diff --git a/examples/cpp/helloworld/greeter_async_client2.cc b/examples/cpp/helloworld/greeter_async_client2.cc index 97631f38889..407a4414f42 100644 --- a/examples/cpp/helloworld/greeter_async_client2.cc +++ b/examples/cpp/helloworld/greeter_async_client2.cc @@ -20,8 +20,8 @@ #include #include -#include #include +#include #include #ifdef BAZEL_BUILD @@ -35,113 +35,109 @@ using grpc::ClientAsyncResponseReader; using grpc::ClientContext; using grpc::CompletionQueue; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; class GreeterClient { - public: - explicit GreeterClient(std::shared_ptr channel) - : stub_(Greeter::NewStub(channel)) {} - - // Assembles the client's payload and sends it to the server. - void SayHello(const std::string& user) { - // Data we are sending to the server. - HelloRequest request; - request.set_name(user); - - // Call object to store rpc data - AsyncClientCall* call = new AsyncClientCall; - - // stub_->PrepareAsyncSayHello() creates an RPC object, returning - // an instance to store in "call" but does not actually start the RPC - // Because we are using the asynchronous API, we need to hold on to - // the "call" instance in order to get updates on the ongoing RPC. - call->response_reader = - stub_->PrepareAsyncSayHello(&call->context, request, &cq_); - - // StartCall initiates the RPC call - call->response_reader->StartCall(); - - // Request that, upon completion of the RPC, "reply" be updated with the - // server's response; "status" with the indication of whether the operation - // was successful. Tag the request with the memory address of the call object. - call->response_reader->Finish(&call->reply, &call->status, (void*)call); - + public: + explicit GreeterClient(std::shared_ptr channel) + : stub_(Greeter::NewStub(channel)) {} + + // Assembles the client's payload and sends it to the server. + void SayHello(const std::string& user) { + // Data we are sending to the server. + HelloRequest request; + request.set_name(user); + + // Call object to store rpc data + AsyncClientCall* call = new AsyncClientCall; + + // stub_->PrepareAsyncSayHello() creates an RPC object, returning + // an instance to store in "call" but does not actually start the RPC + // Because we are using the asynchronous API, we need to hold on to + // the "call" instance in order to get updates on the ongoing RPC. + call->response_reader = + stub_->PrepareAsyncSayHello(&call->context, request, &cq_); + + // StartCall initiates the RPC call + call->response_reader->StartCall(); + + // Request that, upon completion of the RPC, "reply" be updated with the + // server's response; "status" with the indication of whether the operation + // was successful. Tag the request with the memory address of the call + // object. + call->response_reader->Finish(&call->reply, &call->status, (void*)call); + } + + // Loop while listening for completed responses. + // Prints out the response from the server. + void AsyncCompleteRpc() { + void* got_tag; + bool ok = false; + + // Block until the next result is available in the completion queue "cq". + while (cq_.Next(&got_tag, &ok)) { + // The tag in this example is the memory location of the call object + AsyncClientCall* call = static_cast(got_tag); + + // Verify that the request was completed successfully. Note that "ok" + // corresponds solely to the request for updates introduced by Finish(). + GPR_ASSERT(ok); + + if (call->status.ok()) + std::cout << "Greeter received: " << call->reply.message() << std::endl; + else + std::cout << "RPC failed" << std::endl; + + // Once we're complete, deallocate the call object. + delete call; } + } - // Loop while listening for completed responses. - // Prints out the response from the server. - void AsyncCompleteRpc() { - void* got_tag; - bool ok = false; - - // Block until the next result is available in the completion queue "cq". - while (cq_.Next(&got_tag, &ok)) { - // The tag in this example is the memory location of the call object - AsyncClientCall* call = static_cast(got_tag); - - // Verify that the request was completed successfully. Note that "ok" - // corresponds solely to the request for updates introduced by Finish(). - GPR_ASSERT(ok); - - if (call->status.ok()) - std::cout << "Greeter received: " << call->reply.message() << std::endl; - else - std::cout << "RPC failed" << std::endl; - - // Once we're complete, deallocate the call object. - delete call; - } - } - - private: - - // struct for keeping state and data information - struct AsyncClientCall { - // Container for the data we expect from the server. - HelloReply reply; - - // Context for the client. It could be used to convey extra information to - // the server and/or tweak certain RPC behaviors. - ClientContext context; + private: + // struct for keeping state and data information + struct AsyncClientCall { + // Container for the data we expect from the server. + HelloReply reply; - // Storage for the status of the RPC upon completion. - Status status; + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + // Storage for the status of the RPC upon completion. + Status status; - std::unique_ptr> response_reader; - }; + std::unique_ptr> response_reader; + }; - // Out of the passed in Channel comes the stub, stored here, our view of the - // server's exposed services. - std::unique_ptr stub_; + // Out of the passed in Channel comes the stub, stored here, our view of the + // server's exposed services. + std::unique_ptr stub_; - // The producer-consumer queue we use to communicate asynchronously with the - // gRPC runtime. - CompletionQueue cq_; + // The producer-consumer queue we use to communicate asynchronously with the + // gRPC runtime. + CompletionQueue cq_; }; int main(int argc, char** argv) { + // Instantiate the client. It requires a channel, out of which the actual RPCs + // are created. This channel models a connection to an endpoint (in this case, + // localhost at port 50051). We indicate that the channel isn't authenticated + // (use of InsecureChannelCredentials()). + GreeterClient greeter(grpc::CreateChannel( + "localhost:50051", grpc::InsecureChannelCredentials())); + // Spawn reader thread that loops indefinitely + std::thread thread_ = std::thread(&GreeterClient::AsyncCompleteRpc, &greeter); - // Instantiate the client. It requires a channel, out of which the actual RPCs - // are created. This channel models a connection to an endpoint (in this case, - // localhost at port 50051). We indicate that the channel isn't authenticated - // (use of InsecureChannelCredentials()). - GreeterClient greeter(grpc::CreateChannel( - "localhost:50051", grpc::InsecureChannelCredentials())); - - // Spawn reader thread that loops indefinitely - std::thread thread_ = std::thread(&GreeterClient::AsyncCompleteRpc, &greeter); - - for (int i = 0; i < 100; i++) { - std::string user("world " + std::to_string(i)); - greeter.SayHello(user); // The actual RPC call! - } + for (int i = 0; i < 100; i++) { + std::string user("world " + std::to_string(i)); + greeter.SayHello(user); // The actual RPC call! + } - std::cout << "Press control-c to quit" << std::endl << std::endl; - thread_.join(); //blocks forever + std::cout << "Press control-c to quit" << std::endl << std::endl; + thread_.join(); // blocks forever - return 0; + return 0; } diff --git a/examples/cpp/helloworld/greeter_async_server.cc b/examples/cpp/helloworld/greeter_async_server.cc index d4d1594c72b..d35d3e97ab0 100644 --- a/examples/cpp/helloworld/greeter_async_server.cc +++ b/examples/cpp/helloworld/greeter_async_server.cc @@ -16,13 +16,13 @@ * */ -#include #include +#include #include #include -#include #include +#include #ifdef BAZEL_BUILD #include "examples/protos/helloworld.grpc.pb.h" @@ -33,12 +33,12 @@ using grpc::Server; using grpc::ServerAsyncResponseWriter; using grpc::ServerBuilder; -using grpc::ServerContext; using grpc::ServerCompletionQueue; +using grpc::ServerContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; class ServerImpl final { public: diff --git a/examples/cpp/helloworld/greeter_client.cc b/examples/cpp/helloworld/greeter_client.cc index 7ece0330c51..6b9c12d509f 100644 --- a/examples/cpp/helloworld/greeter_client.cc +++ b/examples/cpp/helloworld/greeter_client.cc @@ -31,9 +31,9 @@ using grpc::Channel; using grpc::ClientContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; class GreeterClient { public: @@ -87,7 +87,8 @@ int main(int argc, char** argv) { if (arg_val[start_pos] == '=') { target_str = arg_val.substr(start_pos + 1); } else { - std::cout << "The only correct argument syntax is --target=" << std::endl; + std::cout << "The only correct argument syntax is --target=" + << std::endl; return 0; } } else { @@ -97,8 +98,8 @@ int main(int argc, char** argv) { } else { target_str = "localhost:50051"; } - GreeterClient greeter(grpc::CreateChannel( - target_str, grpc::InsecureChannelCredentials())); + GreeterClient greeter( + grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials())); std::string user("world"); std::string reply = greeter.SayHello(user); std::cout << "Greeter received: " << reply << std::endl; diff --git a/examples/cpp/helloworld/greeter_server.cc b/examples/cpp/helloworld/greeter_server.cc index cb8f92cf20b..560b8b42828 100644 --- a/examples/cpp/helloworld/greeter_server.cc +++ b/examples/cpp/helloworld/greeter_server.cc @@ -20,9 +20,9 @@ #include #include +#include #include #include -#include #ifdef BAZEL_BUILD #include "examples/protos/helloworld.grpc.pb.h" @@ -34,9 +34,9 @@ using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; // Logic and data behind the server's behavior. class GreeterServiceImpl final : public Greeter::Service { diff --git a/examples/cpp/helloworld/xds_greeter_client.cc b/examples/cpp/helloworld/xds_greeter_client.cc new file mode 100644 index 00000000000..839625eca1f --- /dev/null +++ b/examples/cpp/helloworld/xds_greeter_client.cc @@ -0,0 +1,92 @@ +/* + * + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "absl/flags/flag.h" +#include "absl/flags/parse.h" + +#include + +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else +#include "helloworld.grpc.pb.h" +#endif + +ABSL_FLAG(std::string, target, "xds:///helloworld:50051", "Target string"); +ABSL_FLAG(bool, secure, true, "Secure mode"); + +using grpc::Channel; +using grpc::ClientContext; +using grpc::Status; +using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; + +class GreeterClient { + public: + GreeterClient(std::shared_ptr channel) + : stub_(Greeter::NewStub(channel)) {} + + // Assembles the client's payload, sends it and presents the response back + // from the server. + std::string SayHello(const std::string& user) { + // Data we are sending to the server. + HelloRequest request; + request.set_name(user); + + // Container for the data we expect from the server. + HelloReply reply; + + // Context for the client. It could be used to convey extra information to + // the server and/or tweak certain RPC behaviors. + ClientContext context; + + // The actual RPC. + Status status = stub_->SayHello(&context, request, &reply); + + // Act upon its status. + if (status.ok()) { + return reply.message(); + } else { + std::cout << status.error_code() << ": " << status.error_message() + << std::endl; + return "RPC failed"; + } + } + + private: + std::unique_ptr stub_; +}; + +int main(int argc, char** argv) { + absl::ParseCommandLine(argc, argv); + GreeterClient greeter(grpc::CreateChannel( + absl::GetFlag(FLAGS_target), absl::GetFlag(FLAGS_secure) + ? grpc::experimental::XdsCredentials( + grpc::InsecureChannelCredentials()) + : grpc::InsecureChannelCredentials())); + std::string user("world"); + std::string reply = greeter.SayHello(user); + std::cout << "Greeter received: " << reply << std::endl; + + return 0; +} diff --git a/examples/cpp/helloworld/xds_greeter_server.cc b/examples/cpp/helloworld/xds_greeter_server.cc new file mode 100644 index 00000000000..21a964dedd6 --- /dev/null +++ b/examples/cpp/helloworld/xds_greeter_server.cc @@ -0,0 +1,108 @@ +/* + * + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include "absl/flags/flag.h" +#include "absl/flags/parse.h" +#include "absl/strings/str_cat.h" + +#include +#include +#include +#include +#include + +#ifdef BAZEL_BUILD +#include "examples/protos/helloworld.grpc.pb.h" +#else +#include "helloworld.grpc.pb.h" +#endif + +ABSL_FLAG(int32_t, port, 50051, "Server port for service."); +ABSL_FLAG(int32_t, maintenance_port, 50052, + "Server port for maintenance if --secure is used."); +ABSL_FLAG(bool, secure, true, "Secure mode"); + +using grpc::Server; +using grpc::ServerBuilder; +using grpc::ServerContext; +using grpc::Status; +using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; + +// Logic and data behind the server's behavior. +class GreeterServiceImpl final : public Greeter::Service { + Status SayHello(ServerContext* context, const HelloRequest* request, + HelloReply* reply) override { + std::string prefix("Hello "); + reply->set_message(prefix + request->name()); + return Status::OK; + } +}; + +void RunServer() { + grpc::EnableDefaultHealthCheckService(true); + grpc::reflection::InitProtoReflectionServerBuilderPlugin(); + int port = absl::GetFlag(FLAGS_port); + int maintenance_port = absl::GetFlag(FLAGS_maintenance_port); + grpc::experimental::XdsServerBuilder xds_builder; + ServerBuilder builder; + std::unique_ptr xds_enabled_server; + std::unique_ptr server; + GreeterServiceImpl service; + // Register "service" as the instance through which we'll communicate with + // clients. In this case it corresponds to an *synchronous* service. + xds_builder.RegisterService(&service); + if (absl::GetFlag(FLAGS_secure)) { + // Listen on the given address with XdsServerCredentials and a fallback of + // InsecureServerCredentials + xds_builder.AddListeningPort(absl::StrCat("0.0.0.0:", port), + grpc::experimental::XdsServerCredentials( + grpc::InsecureServerCredentials())); + xds_enabled_server = xds_builder.BuildAndStart(); + gpr_log(GPR_INFO, "Server starting on 0.0.0.0:%d", port); + grpc::AddAdminServices(&builder); + // For the maintenance server, do not use any authentication mechanism. + builder.AddListeningPort(absl::StrCat("0.0.0.0:", maintenance_port), + grpc::InsecureServerCredentials()); + server = builder.BuildAndStart(); + gpr_log(GPR_INFO, "Maintenance server listening on 0.0.0.0:%d", + maintenance_port); + } else { + grpc::AddAdminServices(&xds_builder); + // Listen on the given address without any authentication mechanism. + builder.AddListeningPort(absl::StrCat("0.0.0.0:", port), + grpc::InsecureServerCredentials()); + server = xds_builder.BuildAndStart(); + gpr_log(GPR_INFO, "Server listening on 0.0.0.0:%d", port); + } + + // Wait for the server to shutdown. Note that some other thread must be + // responsible for shutting down the server for this call to ever return. + server->Wait(); +} + +int main(int argc, char** argv) { + absl::ParseCommandLine(argc, argv); + RunServer(); + return 0; +} diff --git a/examples/cpp/keyvaluestore/CMakeLists.txt b/examples/cpp/keyvaluestore/CMakeLists.txt new file mode 100644 index 00000000000..f0de502fbd0 --- /dev/null +++ b/examples/cpp/keyvaluestore/CMakeLists.txt @@ -0,0 +1,73 @@ +# Copyright 2021 the gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ keyvaluestore example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building keyvaluestore. + +cmake_minimum_required(VERSION 3.5.1) + +project(KeyValueStore C CXX) + +include(../cmake/common.cmake) + +# Proto file +get_filename_component(kvs_proto "../../protos/keyvaluestore.proto" ABSOLUTE) +get_filename_component(kvs_proto_path "${kvs_proto}" PATH) + +# Generated sources +set(kvs_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.pb.cc") +set(kvs_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.pb.h") +set(kvs_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.grpc.pb.cc") +set(kvs_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/keyvaluestore.grpc.pb.h") +add_custom_command( + OUTPUT "${kvs_proto_srcs}" "${kvs_proto_hdrs}" "${kvs_grpc_srcs}" "${kvs_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${kvs_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${kvs_proto}" + DEPENDS "${kvs_proto}") + +# Include generated *.pb.h files +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# kvs_grpc_proto +add_library(kvs_grpc_proto + ${kvs_grpc_srcs} + ${kvs_grpc_hdrs} + ${kvs_proto_srcs} + ${kvs_proto_hdrs}) +target_link_libraries(kvs_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + +# client +add_executable(client "client.cc" "caching_interceptor.h") +target_link_libraries(client + kvs_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + +# server +add_executable(server "server.cc") +target_link_libraries(server + kvs_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) diff --git a/examples/cpp/load_balancing/CMakeLists.txt b/examples/cpp/load_balancing/CMakeLists.txt new file mode 100644 index 00000000000..126b713172c --- /dev/null +++ b/examples/cpp/load_balancing/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright 2021 the gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ helloworld example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building helloworld. + +cmake_minimum_required(VERSION 3.5.1) + +project(LoadBalancing C CXX) + +include(../cmake/common.cmake) + +# Proto file +get_filename_component(hw_proto "../../protos/helloworld.proto" ABSOLUTE) +get_filename_component(hw_proto_path "${hw_proto}" PATH) + +# Generated sources +set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc") +set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h") +set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc") +set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h") +add_custom_command( + OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${hw_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${hw_proto}" + DEPENDS "${hw_proto}") + +# Include generated *.pb.h files +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# hw_grpc_proto +add_library(hw_grpc_proto + ${hw_grpc_srcs} + ${hw_grpc_hdrs} + ${hw_proto_srcs} + ${hw_proto_hdrs}) +target_link_libraries(hw_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + +# Targets greeter_(client|server) +foreach(_target + greeter_client greeter_server) + add_executable(${_target} "${_target}.cc") + target_link_libraries(${_target} + hw_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) +endforeach() diff --git a/examples/cpp/load_balancing/greeter_client.cc b/examples/cpp/load_balancing/greeter_client.cc index 5b08204a96b..25322dbfc95 100644 --- a/examples/cpp/load_balancing/greeter_client.cc +++ b/examples/cpp/load_balancing/greeter_client.cc @@ -32,9 +32,9 @@ using grpc::Channel; using grpc::ChannelArguments; using grpc::ClientContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; class GreeterClient { public: diff --git a/examples/cpp/load_balancing/greeter_server.cc b/examples/cpp/load_balancing/greeter_server.cc index f36ad906a29..d021b54c4d1 100644 --- a/examples/cpp/load_balancing/greeter_server.cc +++ b/examples/cpp/load_balancing/greeter_server.cc @@ -32,9 +32,9 @@ using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; // Logic and data behind the server's behavior. class GreeterServiceImpl final : public Greeter::Service { diff --git a/examples/cpp/metadata/CMakeLists.txt b/examples/cpp/metadata/CMakeLists.txt new file mode 100644 index 00000000000..48d6f178e55 --- /dev/null +++ b/examples/cpp/metadata/CMakeLists.txt @@ -0,0 +1,68 @@ +# Copyright 2021 the gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# cmake build file for C++ helloworld example. +# Assumes protobuf and gRPC have been installed using cmake. +# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build +# that automatically builds all the dependencies before building helloworld. + +cmake_minimum_required(VERSION 3.5.1) + +project(Metadata C CXX) + +include(../cmake/common.cmake) + +# Proto file +get_filename_component(hw_proto "../../protos/helloworld.proto" ABSOLUTE) +get_filename_component(hw_proto_path "${hw_proto}" PATH) + +# Generated sources +set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc") +set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h") +set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc") +set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h") +add_custom_command( + OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}" + COMMAND ${_PROTOBUF_PROTOC} + ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" + --cpp_out "${CMAKE_CURRENT_BINARY_DIR}" + -I "${hw_proto_path}" + --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}" + "${hw_proto}" + DEPENDS "${hw_proto}") + +# Include generated *.pb.h files +include_directories("${CMAKE_CURRENT_BINARY_DIR}") + +# hw_grpc_proto +add_library(hw_grpc_proto + ${hw_grpc_srcs} + ${hw_grpc_hdrs} + ${hw_proto_srcs} + ${hw_proto_hdrs}) +target_link_libraries(hw_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) + +# Targets greeter_(client|server) +foreach(_target + greeter_client greeter_server) + add_executable(${_target} "${_target}.cc") + target_link_libraries(${_target} + hw_grpc_proto + ${_REFLECTION} + ${_GRPC_GRPCPP} + ${_PROTOBUF_LIBPROTOBUF}) +endforeach() diff --git a/examples/cpp/metadata/greeter_client.cc b/examples/cpp/metadata/greeter_client.cc index 246c4af2739..3784d2fa26a 100644 --- a/examples/cpp/metadata/greeter_client.cc +++ b/examples/cpp/metadata/greeter_client.cc @@ -31,9 +31,9 @@ using grpc::Channel; using grpc::ClientContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; class CustomHeaderClient { public: @@ -57,9 +57,8 @@ class CustomHeaderClient { // Setting custom metadata to be sent to the server context.AddMetadata("custom-header", "Custom Value"); - // Setting custom binary metadata - char bytes[8] = {'\0', '\1', '\2', '\3', - '\4', '\5', '\6', '\7'}; + // Setting custom binary metadata + char bytes[8] = {'\0', '\1', '\2', '\3', '\4', '\5', '\6', '\7'}; context.AddMetadata("custom-bin", std::string(bytes, 8)); // The actual RPC. @@ -67,8 +66,16 @@ class CustomHeaderClient { // Act upon its status. if (status.ok()) { - std::cout << "Client received initial metadata from server: " << context.GetServerInitialMetadata().find("custom-server-metadata")->second << std::endl; - std::cout << "Client received trailing metadata from server: " << context.GetServerTrailingMetadata().find("custom-trailing-metadata")->second << std::endl; + std::cout << "Client received initial metadata from server: " + << context.GetServerInitialMetadata() + .find("custom-server-metadata") + ->second + << std::endl; + std::cout << "Client received trailing metadata from server: " + << context.GetServerTrailingMetadata() + .find("custom-trailing-metadata") + ->second + << std::endl; return reply.message(); } else { std::cout << status.error_code() << ": " << status.error_message() diff --git a/examples/cpp/metadata/greeter_server.cc b/examples/cpp/metadata/greeter_server.cc index a9a4f33cb0b..19d8bb0d01d 100644 --- a/examples/cpp/metadata/greeter_server.cc +++ b/examples/cpp/metadata/greeter_server.cc @@ -32,9 +32,9 @@ using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; -using helloworld::HelloRequest; -using helloworld::HelloReply; using helloworld::Greeter; +using helloworld::HelloReply; +using helloworld::HelloRequest; // Logic and data behind the server's behavior. class GreeterServiceImpl final : public Greeter::Service { @@ -44,25 +44,28 @@ class GreeterServiceImpl final : public Greeter::Service { // Get the client's initial metadata std::cout << "Client metadata: " << std::endl; - const std::multimap metadata = context->client_metadata(); + const std::multimap metadata = + context->client_metadata(); for (auto iter = metadata.begin(); iter != metadata.end(); ++iter) { std::cout << "Header key: " << iter->first << ", value: "; // Check for binary value size_t isbin = iter->first.find("-bin"); if ((isbin != std::string::npos) && (isbin + 4 == iter->first.size())) { - std::cout << std::hex; + std::cout << std::hex; for (auto c : iter->second) { std::cout << static_cast(c); } - std::cout << std::dec; + std::cout << std::dec; } else { std::cout << iter->second; } std::cout << std::endl; } - context->AddInitialMetadata("custom-server-metadata", "initial metadata value"); - context->AddTrailingMetadata("custom-trailing-metadata", "trailing metadata value"); + context->AddInitialMetadata("custom-server-metadata", + "initial metadata value"); + context->AddTrailingMetadata("custom-trailing-metadata", + "trailing metadata value"); reply->set_message(prefix + request->name()); return Status::OK; } diff --git a/examples/cpp/route_guide/helper.h b/examples/cpp/route_guide/helper.h index 2d38209dde3..9ca7d271d52 100644 --- a/examples/cpp/route_guide/helper.h +++ b/examples/cpp/route_guide/helper.h @@ -32,4 +32,3 @@ void ParseDb(const std::string& db, std::vector* feature_list); } // namespace routeguide #endif // GRPC_COMMON_CPP_ROUTE_GUIDE_HELPER_H_ - diff --git a/examples/cpp/route_guide/route_guide_client.cc b/examples/cpp/route_guide/route_guide_client.cc index 439edb0dbdf..e30636c28ff 100644 --- a/examples/cpp/route_guide/route_guide_client.cc +++ b/examples/cpp/route_guide/route_guide_client.cc @@ -41,12 +41,12 @@ using grpc::ClientReader; using grpc::ClientReaderWriter; using grpc::ClientWriter; using grpc::Status; -using routeguide::Point; using routeguide::Feature; +using routeguide::Point; using routeguide::Rectangle; -using routeguide::RouteSummary; -using routeguide::RouteNote; using routeguide::RouteGuide; +using routeguide::RouteNote; +using routeguide::RouteSummary; Point MakePoint(long latitude, long longitude) { Point p; @@ -55,16 +55,15 @@ Point MakePoint(long latitude, long longitude) { return p; } -Feature MakeFeature(const std::string& name, - long latitude, long longitude) { +Feature MakeFeature(const std::string& name, long latitude, long longitude) { Feature f; f.set_name(name); f.mutable_location()->CopyFrom(MakePoint(latitude, longitude)); return f; } -RouteNote MakeRouteNote(const std::string& message, - long latitude, long longitude) { +RouteNote MakeRouteNote(const std::string& message, long latitude, + long longitude) { RouteNote n; n.set_message(message); n.mutable_location()->CopyFrom(MakePoint(latitude, longitude)); @@ -102,10 +101,9 @@ class RouteGuideClient { std::unique_ptr > reader( stub_->ListFeatures(&context, rect)); while (reader->Read(&feature)) { - std::cout << "Found feature called " - << feature.name() << " at " - << feature.location().latitude()/kCoordFactor_ << ", " - << feature.location().longitude()/kCoordFactor_ << std::endl; + std::cout << "Found feature called " << feature.name() << " at " + << feature.location().latitude() / kCoordFactor_ << ", " + << feature.location().longitude() / kCoordFactor_ << std::endl; } Status status = reader->Finish(); if (status.ok()) { @@ -125,22 +123,21 @@ class RouteGuideClient { std::default_random_engine generator(seed); std::uniform_int_distribution feature_distribution( 0, feature_list_.size() - 1); - std::uniform_int_distribution delay_distribution( - 500, 1500); + std::uniform_int_distribution delay_distribution(500, 1500); std::unique_ptr > writer( stub_->RecordRoute(&context, &stats)); for (int i = 0; i < kPoints; i++) { const Feature& f = feature_list_[feature_distribution(generator)]; - std::cout << "Visiting point " - << f.location().latitude()/kCoordFactor_ << ", " - << f.location().longitude()/kCoordFactor_ << std::endl; + std::cout << "Visiting point " << f.location().latitude() / kCoordFactor_ + << ", " << f.location().longitude() / kCoordFactor_ + << std::endl; if (!writer->Write(f.location())) { // Broken stream. break; } - std::this_thread::sleep_for(std::chrono::milliseconds( - delay_distribution(generator))); + std::this_thread::sleep_for( + std::chrono::milliseconds(delay_distribution(generator))); } writer->WritesDone(); Status status = writer->Finish(); @@ -162,14 +159,13 @@ class RouteGuideClient { stub_->RouteChat(&context)); std::thread writer([stream]() { - std::vector notes{ - MakeRouteNote("First message", 0, 0), - MakeRouteNote("Second message", 0, 1), - MakeRouteNote("Third message", 1, 0), - MakeRouteNote("Fourth message", 0, 0)}; + std::vector notes{MakeRouteNote("First message", 0, 0), + MakeRouteNote("Second message", 0, 1), + MakeRouteNote("Third message", 1, 0), + MakeRouteNote("Fourth message", 0, 0)}; for (const RouteNote& note : notes) { - std::cout << "Sending message " << note.message() - << " at " << note.location().latitude() << ", " + std::cout << "Sending message " << note.message() << " at " + << note.location().latitude() << ", " << note.location().longitude() << std::endl; stream->Write(note); } @@ -178,8 +174,8 @@ class RouteGuideClient { RouteNote server_note; while (stream->Read(&server_note)) { - std::cout << "Got message " << server_note.message() - << " at " << server_note.location().latitude() << ", " + std::cout << "Got message " << server_note.message() << " at " + << server_note.location().latitude() << ", " << server_note.location().longitude() << std::endl; } writer.join(); @@ -190,7 +186,6 @@ class RouteGuideClient { } private: - bool GetOneFeature(const Point& point, Feature* feature) { ClientContext context; Status status = stub_->GetFeature(&context, point, feature); @@ -204,12 +199,12 @@ class RouteGuideClient { } if (feature->name().empty()) { std::cout << "Found no feature at " - << feature->location().latitude()/kCoordFactor_ << ", " - << feature->location().longitude()/kCoordFactor_ << std::endl; + << feature->location().latitude() / kCoordFactor_ << ", " + << feature->location().longitude() / kCoordFactor_ << std::endl; } else { - std::cout << "Found feature called " << feature->name() << " at " - << feature->location().latitude()/kCoordFactor_ << ", " - << feature->location().longitude()/kCoordFactor_ << std::endl; + std::cout << "Found feature called " << feature->name() << " at " + << feature->location().latitude() / kCoordFactor_ << ", " + << feature->location().longitude() / kCoordFactor_ << std::endl; } return true; } diff --git a/examples/cpp/route_guide/route_guide_server.cc b/examples/cpp/route_guide/route_guide_server.cc index 49239665179..58ec2089590 100644 --- a/examples/cpp/route_guide/route_guide_server.cc +++ b/examples/cpp/route_guide/route_guide_server.cc @@ -24,10 +24,10 @@ #include #include +#include #include #include #include -#include #include "helper.h" #ifdef BAZEL_BUILD #include "examples/protos/route_guide.grpc.pb.h" @@ -42,18 +42,15 @@ using grpc::ServerReader; using grpc::ServerReaderWriter; using grpc::ServerWriter; using grpc::Status; -using routeguide::Point; using routeguide::Feature; +using routeguide::Point; using routeguide::Rectangle; -using routeguide::RouteSummary; -using routeguide::RouteNote; using routeguide::RouteGuide; +using routeguide::RouteNote; +using routeguide::RouteSummary; using std::chrono::system_clock; - -float ConvertToRadians(float num) { - return num * 3.1415926 /180; -} +float ConvertToRadians(float num) { return num * 3.1415926 / 180; } // The formula is based on http://mathforum.org/library/drmath/view/51879.html float GetDistance(const Point& start, const Point& end) { @@ -64,13 +61,13 @@ float GetDistance(const Point& start, const Point& end) { float lon_2 = end.longitude() / kCoordFactor; float lat_rad_1 = ConvertToRadians(lat_1); float lat_rad_2 = ConvertToRadians(lat_2); - float delta_lat_rad = ConvertToRadians(lat_2-lat_1); - float delta_lon_rad = ConvertToRadians(lon_2-lon_1); + float delta_lat_rad = ConvertToRadians(lat_2 - lat_1); + float delta_lon_rad = ConvertToRadians(lon_2 - lon_1); - float a = pow(sin(delta_lat_rad/2), 2) + cos(lat_rad_1) * cos(lat_rad_2) * - pow(sin(delta_lon_rad/2), 2); - float c = 2 * atan2(sqrt(a), sqrt(1-a)); - int R = 6371000; // metres + float a = pow(sin(delta_lat_rad / 2), 2) + + cos(lat_rad_1) * cos(lat_rad_2) * pow(sin(delta_lon_rad / 2), 2); + float c = 2 * atan2(sqrt(a), sqrt(1 - a)); + int R = 6371000; // metres return R * c; } @@ -111,8 +108,7 @@ class RouteGuideImpl final : public RouteGuide::Service { for (const Feature& f : feature_list_) { if (f.location().longitude() >= left && f.location().longitude() <= right && - f.location().latitude() >= bottom && - f.location().latitude() <= top) { + f.location().latitude() >= bottom && f.location().latitude() <= top) { writer->Write(f); } } @@ -142,8 +138,8 @@ class RouteGuideImpl final : public RouteGuide::Service { summary->set_point_count(point_count); summary->set_feature_count(feature_count); summary->set_distance(static_cast(distance)); - auto secs = std::chrono::duration_cast( - end_time - start_time); + auto secs = + std::chrono::duration_cast(end_time - start_time); summary->set_elapsed_time(secs.count()); return Status::OK; diff --git a/examples/objective-c/auth_sample/Podfile b/examples/objective-c/auth_sample/Podfile index a25d20f477d..3195a323e0f 100644 --- a/examples/objective-c/auth_sample/Podfile +++ b/examples/objective-c/auth_sample/Podfile @@ -1,5 +1,5 @@ source 'https://github.com/CocoaPods/Specs.git' -platform :ios, '8.0' +platform :ios, '9.0' install! 'cocoapods', :deterministic_uuids => false diff --git a/examples/php/GPBMetadata/Helloworld.php b/examples/php/GPBMetadata/Helloworld.php new file mode 100644 index 00000000000..0927516af00 Binary files /dev/null and b/examples/php/GPBMetadata/Helloworld.php differ diff --git a/examples/php/Helloworld/GreeterClient.php b/examples/php/Helloworld/GreeterClient.php new file mode 100644 index 00000000000..f90303aab6b --- /dev/null +++ b/examples/php/Helloworld/GreeterClient.php @@ -0,0 +1,50 @@ +_simpleRequest('/helloworld.Greeter/SayHello', + $argument, + ['\Helloworld\HelloReply', 'decode'], + $metadata, $options); + } + +} diff --git a/examples/php/Helloworld/GreeterStub.php b/examples/php/Helloworld/GreeterStub.php new file mode 100644 index 00000000000..6667f18854d --- /dev/null +++ b/examples/php/Helloworld/GreeterStub.php @@ -0,0 +1,58 @@ +setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/helloworld.Greeter/SayHello' => new \Grpc\MethodDescriptor( + $this, + 'SayHello', + '\Helloworld\HelloRequest', + \Grpc\MethodDescriptor::UNARY_CALL + ), + ]; + } + +} diff --git a/examples/php/Helloworld/HelloReply.php b/examples/php/Helloworld/HelloReply.php new file mode 100644 index 00000000000..74c7f877003 --- /dev/null +++ b/examples/php/Helloworld/HelloReply.php @@ -0,0 +1,60 @@ +helloworld.HelloReply + */ +class HelloReply extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field string message = 1; + */ + protected $message = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $message + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Helloworld::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field string message = 1; + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * Generated from protobuf field string message = 1; + * @param string $var + * @return $this + */ + public function setMessage($var) + { + GPBUtil::checkString($var, True); + $this->message = $var; + + return $this; + } + +} + diff --git a/examples/php/Helloworld/HelloRequest.php b/examples/php/Helloworld/HelloRequest.php new file mode 100644 index 00000000000..d0b52784a25 --- /dev/null +++ b/examples/php/Helloworld/HelloRequest.php @@ -0,0 +1,60 @@ +helloworld.HelloRequest + */ +class HelloRequest extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\Helloworld::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + +} + diff --git a/examples/php/README.md b/examples/php/README.md index 2182e39628a..e027d3270c9 100644 --- a/examples/php/README.md +++ b/examples/php/README.md @@ -1,56 +1,9 @@ -# gRPC PHP Quick Start Example +# gRPC PHP examples +This directory contains the sources for the following PHP examples: -## Prerequisites +- [Quick start][] +- [Basics tutorial][] -This requires `php` >= 5.5, `pecl`, `composer` - -## Install - - - Install the `grpc` extension - - ```sh - $ [sudo] pecl install grpc - ``` - - - Install the `protoc` compiler plugin `grpc_php_plugin` - - ```sh - $ git clone -b RELEASE_TAG_HERE https://github.com/grpc/grpc - $ cd grpc - $ make grpc_php_plugin - ``` - - - Install the `grpc/grpc` composer package - - ``` - $ cd examples/php - $ composer install - ``` - -## Try it! - - - Run the server - - Please follow the instruction in [Node][] to run the server - ``` - $ cd examples/node - $ npm install - $ cd dynamic_codegen or cd static_codegen - $ node greeter_server.js - ``` - - - Generate proto files and run the client - - ``` - $ cd examples/php - $ ./greeter_proto_gen.sh - $ ./run_greeter_client.sh - ``` - -## In-depth Tutorial - -You can find a more detailed tutorial in [gRPC Basics: PHP][] - -[Node]:https://github.com/grpc/grpc/tree/master/examples/node -[gRPC Basics: PHP]:https://grpc.io/docs/languages/php/basics +[Quick start]: https://grpc.io/docs/languages/php/quickstart/ +[Basics tutorial]: https://grpc.io/docs/languages/php/basics/ diff --git a/examples/php/composer.json b/examples/php/composer.json index 927f7df2ad3..1d44bba0a6a 100644 --- a/examples/php/composer.json +++ b/examples/php/composer.json @@ -2,8 +2,8 @@ "name": "grpc/grpc-demo", "description": "gRPC example for PHP", "require": { - "grpc/grpc": "^v1.3.0", - "google/protobuf": "^v3.3.0" + "grpc/grpc": "^v1.30.0", + "google/protobuf": "^v3.12.2" }, "autoload": { "psr-4": { diff --git a/examples/php/echo/composer.json b/examples/php/echo/composer.json index c74e5527389..541d91a50e4 100644 --- a/examples/php/echo/composer.json +++ b/examples/php/echo/composer.json @@ -1,8 +1,8 @@ { "name": "grpc-php/echo-example", "require": { - "grpc/grpc": "^v1.22.0", - "google/protobuf": "^3.7.0" + "grpc/grpc": "^v1.30.0", + "google/protobuf": "^3.12.2" }, "autoload": { "psr-4": { diff --git a/examples/php/greeter_and_routeguide_multi_server.php b/examples/php/greeter_and_routeguide_multi_server.php new file mode 100644 index 00000000000..1bdc1d7e2f8 --- /dev/null +++ b/examples/php/greeter_and_routeguide_multi_server.php @@ -0,0 +1,47 @@ +getName(); + $response = new \Helloworld\HelloReply(); + $response->setMessage("Hello " . $name); + return $response; + } +} + + +$server = new \Grpc\RpcServer(); +$server->addHttp2Port('0.0.0.0:50051'); +$server->handle(new RouteGuideService(null)); +$server->handle(new Greeter()); +$server->run(); diff --git a/examples/php/greeter_proto_gen.sh b/examples/php/greeter_proto_gen.sh index 4322bbda2e3..07c7e61b68b 100755 --- a/examples/php/greeter_proto_gen.sh +++ b/examples/php/greeter_proto_gen.sh @@ -13,4 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -protoc --proto_path=../protos --php_out=. --grpc_out=. --plugin=protoc-gen-grpc=../../bins/opt/grpc_php_plugin ../protos/helloworld.proto +set -e + +cd $(dirname $0)/../.. + +# protoc and grpc_*_plugin binaries can be obtained by running +# $ bazel build @com_google_protobuf//:protoc //src/compiler:all +PROTOC=bazel-bin/external/com_google_protobuf/protoc +PLUGIN=protoc-gen-grpc=bazel-bin/src/compiler/grpc_php_plugin + +$PROTOC --proto_path=examples/protos \ + --php_out=examples/php \ + --grpc_out=generate_server:examples/php \ + --plugin=$PLUGIN examples/protos/helloworld.proto diff --git a/examples/php/greeter_server.php b/examples/php/greeter_server.php new file mode 100644 index 00000000000..a5d749bee96 --- /dev/null +++ b/examples/php/greeter_server.php @@ -0,0 +1,44 @@ +getName(); + $response = new \Helloworld\HelloReply(); + $response->setMessage("Hello " . $name); + return $response; + } +} + +$server = new \Grpc\RpcServer(); +$server->addHttp2Port('0.0.0.0:50051'); +$server->handle(new Greeter()); +$server->run(); diff --git a/examples/php/route_guide/GPBMetadata/RouteGuide.php b/examples/php/route_guide/GPBMetadata/RouteGuide.php new file mode 100644 index 00000000000..ffd390b3157 Binary files /dev/null and b/examples/php/route_guide/GPBMetadata/RouteGuide.php differ diff --git a/examples/php/route_guide/RouteGuideService.php b/examples/php/route_guide/RouteGuideService.php new file mode 100644 index 00000000000..ac1894c7433 --- /dev/null +++ b/examples/php/route_guide/RouteGuideService.php @@ -0,0 +1,182 @@ +featureList, new Routeguide\Feature([ + 'name' => $feature->name, + 'location' => new Routeguide\Point([ + 'latitude' => $feature->location->latitude, + 'longitude' => $feature->location->longitude, + ]), + ])); + } + } + + private function findFeature(\Routeguide\Point $point) + { + foreach ($this->featureList as $feature) { + $location = $feature->getLocation(); + if ( + $location->getLatitude() === $point->getLatitude() + && $location->getLongitude() === $point->getLongitude() + ) { + return $feature; + } + } + return null; + } + + // The formula is based on http://mathforum.org/library/drmath/view/51879.html + private function calculateDistance( + \Routeguide\Point $start, + \Routeguide\Point $end + ) { + $toRadians = function (float $num) { + return $num * 3.1415926 / 180; + }; + $coordFactor = 10000000.0; + $R = 6371000; // metres + + $lat_1 = $start->getLatitude() / $coordFactor; + $lat_2 = $end->getLatitude() / $coordFactor; + $lon_1 = $start->getLongitude() / $coordFactor; + $lon_2 = $end->getLongitude() / $coordFactor; + $lat_rad_1 = $toRadians($lat_1); + $lat_rad_2 = $toRadians($lat_2); + $delta_lat_rad = $toRadians($lat_2 - $lat_1); + $delta_lon_rad = $toRadians($lon_2 - $lon_1); + + $a = pow(sin($delta_lat_rad / 2), 2) + + cos($lat_rad_1) * cos($lat_rad_2) * pow(sin($delta_lon_rad / 2), 2); + $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); + + return $R * $c; + } + + public function GetFeature( + \Routeguide\Point $request, + \Grpc\ServerContext $serverContext + ): ?\Routeguide\Feature { + $feature = $this->findFeature($request); + $notFoundFeature = new Routeguide\Feature([ + 'name' => '', + 'location' => $request, + ]); + return $feature ?? $notFoundFeature; + } + + public function ListFeatures( + \Routeguide\Rectangle $request, + \Grpc\ServerCallWriter $writer, + \Grpc\ServerContext $serverContext + ): void { + $lo = $request->getLo(); + $hi = $request->getHi(); + $left = min($lo->getLongitude(), $hi->getLongitude()); + $right = max($lo->getLongitude(), $hi->getLongitude()); + $top = max($lo->getLatitude(), $hi->getLatitude()); + $bottom = min($lo->getLatitude(), $hi->getLatitude()); + + foreach ($this->featureList as $feature) { + $longitude = $feature->getLocation()->getLongitude(); + $latitude = $feature->getLocation()->getLatitude(); + if ( + $longitude >= $left && $longitude <= $right + && $latitude >= $bottom && $latitude <= $top + ) { + $writer->write($feature); + } + } + + $writer->finish(); + } + + public function RecordRoute( + \Grpc\ServerCallReader $reader, + \Grpc\ServerContext $serverContext + ): ?\Routeguide\RouteSummary { + $point_count = 0; + $feature_count = 0; + $distance = 0; + $previous = null; + + $start_time = time(); + while ($point = $reader->read()) { + $point_count++; + $feature = $this->findFeature($point); + if ($feature) { + $feature_count++; + if ($previous) { + $distance += $this->calculateDistance($previous, $point); + } + $previous = $point; + } + } + + $summary = new \Routeguide\RouteSummary(); + $summary->setPointCount($point_count); + $summary->setFeatureCount($feature_count); + $summary->setDistance($distance); + $summary->setElapsedTime(time() - $start_time); + + return $summary; + } + + public function RouteChat( + \Grpc\ServerCallReader $reader, + \Grpc\ServerCallWriter $writer, + \Grpc\ServerContext $serverContext + ): void { + while ($note = $reader->read()) { + foreach ($this->received_notes as $n) { + if ( + $n->getLocation()->getLatitude() === + $note->getLocation()->getLatitude() + && $n->getLocation()->getLongitude() === + $note->getLocation()->getLongitude() + ) { + $writer->write($n); + } + } + array_push($this->received_notes, $note); + } + $writer->finish(); + } + + private $received_notes = []; + private $featureList = []; +} diff --git a/examples/php/route_guide/Routeguide/Feature.php b/examples/php/route_guide/Routeguide/Feature.php new file mode 100644 index 00000000000..43362f19229 --- /dev/null +++ b/examples/php/route_guide/Routeguide/Feature.php @@ -0,0 +1,112 @@ +routeguide.Feature + */ +class Feature extends \Google\Protobuf\Internal\Message +{ + /** + * The name of the feature. + * + * Generated from protobuf field string name = 1; + */ + protected $name = ''; + /** + * The point where the feature is detected. + * + * Generated from protobuf field .routeguide.Point location = 2; + */ + protected $location = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type string $name + * The name of the feature. + * @type \Routeguide\Point $location + * The point where the feature is detected. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\RouteGuide::initOnce(); + parent::__construct($data); + } + + /** + * The name of the feature. + * + * Generated from protobuf field string name = 1; + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * The name of the feature. + * + * Generated from protobuf field string name = 1; + * @param string $var + * @return $this + */ + public function setName($var) + { + GPBUtil::checkString($var, True); + $this->name = $var; + + return $this; + } + + /** + * The point where the feature is detected. + * + * Generated from protobuf field .routeguide.Point location = 2; + * @return \Routeguide\Point|null + */ + public function getLocation() + { + return isset($this->location) ? $this->location : null; + } + + public function hasLocation() + { + return isset($this->location); + } + + public function clearLocation() + { + unset($this->location); + } + + /** + * The point where the feature is detected. + * + * Generated from protobuf field .routeguide.Point location = 2; + * @param \Routeguide\Point $var + * @return $this + */ + public function setLocation($var) + { + GPBUtil::checkMessage($var, \Routeguide\Point::class); + $this->location = $var; + + return $this; + } + +} + diff --git a/examples/php/route_guide/Routeguide/Point.php b/examples/php/route_guide/Routeguide/Point.php new file mode 100644 index 00000000000..094939fff7d --- /dev/null +++ b/examples/php/route_guide/Routeguide/Point.php @@ -0,0 +1,90 @@ +routeguide.Point + */ +class Point extends \Google\Protobuf\Internal\Message +{ + /** + * Generated from protobuf field int32 latitude = 1; + */ + protected $latitude = 0; + /** + * Generated from protobuf field int32 longitude = 2; + */ + protected $longitude = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $latitude + * @type int $longitude + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\RouteGuide::initOnce(); + parent::__construct($data); + } + + /** + * Generated from protobuf field int32 latitude = 1; + * @return int + */ + public function getLatitude() + { + return $this->latitude; + } + + /** + * Generated from protobuf field int32 latitude = 1; + * @param int $var + * @return $this + */ + public function setLatitude($var) + { + GPBUtil::checkInt32($var); + $this->latitude = $var; + + return $this; + } + + /** + * Generated from protobuf field int32 longitude = 2; + * @return int + */ + public function getLongitude() + { + return $this->longitude; + } + + /** + * Generated from protobuf field int32 longitude = 2; + * @param int $var + * @return $this + */ + public function setLongitude($var) + { + GPBUtil::checkInt32($var); + $this->longitude = $var; + + return $this; + } + +} + diff --git a/examples/php/route_guide/Routeguide/Rectangle.php b/examples/php/route_guide/Routeguide/Rectangle.php new file mode 100644 index 00000000000..29292cc450e --- /dev/null +++ b/examples/php/route_guide/Routeguide/Rectangle.php @@ -0,0 +1,122 @@ +routeguide.Rectangle + */ +class Rectangle extends \Google\Protobuf\Internal\Message +{ + /** + * One corner of the rectangle. + * + * Generated from protobuf field .routeguide.Point lo = 1; + */ + protected $lo = null; + /** + * The other corner of the rectangle. + * + * Generated from protobuf field .routeguide.Point hi = 2; + */ + protected $hi = null; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Routeguide\Point $lo + * One corner of the rectangle. + * @type \Routeguide\Point $hi + * The other corner of the rectangle. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\RouteGuide::initOnce(); + parent::__construct($data); + } + + /** + * One corner of the rectangle. + * + * Generated from protobuf field .routeguide.Point lo = 1; + * @return \Routeguide\Point|null + */ + public function getLo() + { + return isset($this->lo) ? $this->lo : null; + } + + public function hasLo() + { + return isset($this->lo); + } + + public function clearLo() + { + unset($this->lo); + } + + /** + * One corner of the rectangle. + * + * Generated from protobuf field .routeguide.Point lo = 1; + * @param \Routeguide\Point $var + * @return $this + */ + public function setLo($var) + { + GPBUtil::checkMessage($var, \Routeguide\Point::class); + $this->lo = $var; + + return $this; + } + + /** + * The other corner of the rectangle. + * + * Generated from protobuf field .routeguide.Point hi = 2; + * @return \Routeguide\Point|null + */ + public function getHi() + { + return isset($this->hi) ? $this->hi : null; + } + + public function hasHi() + { + return isset($this->hi); + } + + public function clearHi() + { + unset($this->hi); + } + + /** + * The other corner of the rectangle. + * + * Generated from protobuf field .routeguide.Point hi = 2; + * @param \Routeguide\Point $var + * @return $this + */ + public function setHi($var) + { + GPBUtil::checkMessage($var, \Routeguide\Point::class); + $this->hi = $var; + + return $this; + } + +} + diff --git a/examples/php/route_guide/Routeguide/RouteGuideClient.php b/examples/php/route_guide/Routeguide/RouteGuideClient.php new file mode 100644 index 00000000000..c0d466ddc85 --- /dev/null +++ b/examples/php/route_guide/Routeguide/RouteGuideClient.php @@ -0,0 +1,105 @@ +_simpleRequest('/routeguide.RouteGuide/GetFeature', + $argument, + ['\Routeguide\Feature', 'decode'], + $metadata, $options); + } + + /** + * A server-to-client streaming RPC. + * + * Obtains the Features available within the given Rectangle. Results are + * streamed rather than returned at once (e.g. in a response message with a + * repeated field), as the rectangle may cover a large area and contain a + * huge number of features. + * @param \Routeguide\Rectangle $argument input argument + * @param array $metadata metadata + * @param array $options call options + * @return \Grpc\ServerStreamingCall + */ + public function ListFeatures(\Routeguide\Rectangle $argument, + $metadata = [], $options = []) { + return $this->_serverStreamRequest('/routeguide.RouteGuide/ListFeatures', + $argument, + ['\Routeguide\Feature', 'decode'], + $metadata, $options); + } + + /** + * A client-to-server streaming RPC. + * + * Accepts a stream of Points on a route being traversed, returning a + * RouteSummary when traversal is completed. + * @param array $metadata metadata + * @param array $options call options + * @return \Grpc\ClientStreamingCall + */ + public function RecordRoute($metadata = [], $options = []) { + return $this->_clientStreamRequest('/routeguide.RouteGuide/RecordRoute', + ['\Routeguide\RouteSummary','decode'], + $metadata, $options); + } + + /** + * A Bidirectional streaming RPC. + * + * Accepts a stream of RouteNotes sent while a route is being traversed, + * while receiving other RouteNotes (e.g. from other users). + * @param array $metadata metadata + * @param array $options call options + * @return \Grpc\BidiStreamingCall + */ + public function RouteChat($metadata = [], $options = []) { + return $this->_bidiRequest('/routeguide.RouteGuide/RouteChat', + ['\Routeguide\RouteNote','decode'], + $metadata, $options); + } + +} diff --git a/examples/php/route_guide/Routeguide/RouteGuideStub.php b/examples/php/route_guide/Routeguide/RouteGuideStub.php new file mode 100644 index 00000000000..6beb57c2ebf --- /dev/null +++ b/examples/php/route_guide/Routeguide/RouteGuideStub.php @@ -0,0 +1,139 @@ +setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * A server-to-client streaming RPC. + * + * Obtains the Features available within the given Rectangle. Results are + * streamed rather than returned at once (e.g. in a response message with a + * repeated field), as the rectangle may cover a large area and contain a + * huge number of features. + * @param \Routeguide\Rectangle $request client request + * @param \Grpc\ServerCallWriter $writer write response data of \Routeguide\Feature + * @param \Grpc\ServerContext $context server request context + * @return void + */ + public function ListFeatures( + \Routeguide\Rectangle $request, + \Grpc\ServerCallWriter $writer, + \Grpc\ServerContext $context + ): void { + $context->setStatus(\Grpc\Status::unimplemented()); + $writer->finish(); + } + + /** + * A client-to-server streaming RPC. + * + * Accepts a stream of Points on a route being traversed, returning a + * RouteSummary when traversal is completed. + * @param \Grpc\ServerCallReader $reader read client request data of \Routeguide\Point + * @param \Grpc\ServerContext $context server request context + * @return \Routeguide\RouteSummary for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function RecordRoute( + \Grpc\ServerCallReader $reader, + \Grpc\ServerContext $context + ): ?\Routeguide\RouteSummary { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * A Bidirectional streaming RPC. + * + * Accepts a stream of RouteNotes sent while a route is being traversed, + * while receiving other RouteNotes (e.g. from other users). + * @param \Grpc\ServerCallReader $reader read client request data of \Routeguide\RouteNote + * @param \Grpc\ServerCallWriter $writer write response data of \Routeguide\RouteNote + * @param \Grpc\ServerContext $context server request context + * @return void + */ + public function RouteChat( + \Grpc\ServerCallReader $reader, + \Grpc\ServerCallWriter $writer, + \Grpc\ServerContext $context + ): void { + $context->setStatus(\Grpc\Status::unimplemented()); + $writer->finish(); + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/routeguide.RouteGuide/GetFeature' => new \Grpc\MethodDescriptor( + $this, + 'GetFeature', + '\Routeguide\Point', + \Grpc\MethodDescriptor::UNARY_CALL + ), + '/routeguide.RouteGuide/ListFeatures' => new \Grpc\MethodDescriptor( + $this, + 'ListFeatures', + '\Routeguide\Rectangle', + \Grpc\MethodDescriptor::SERVER_STREAMING_CALL + ), + '/routeguide.RouteGuide/RecordRoute' => new \Grpc\MethodDescriptor( + $this, + 'RecordRoute', + '\Routeguide\Point', + \Grpc\MethodDescriptor::CLIENT_STREAMING_CALL + ), + '/routeguide.RouteGuide/RouteChat' => new \Grpc\MethodDescriptor( + $this, + 'RouteChat', + '\Routeguide\RouteNote', + \Grpc\MethodDescriptor::BIDI_STREAMING_CALL + ), + ]; + } + +} diff --git a/examples/php/route_guide/Routeguide/RouteNote.php b/examples/php/route_guide/Routeguide/RouteNote.php new file mode 100644 index 00000000000..153c0a29e19 --- /dev/null +++ b/examples/php/route_guide/Routeguide/RouteNote.php @@ -0,0 +1,111 @@ +routeguide.RouteNote + */ +class RouteNote extends \Google\Protobuf\Internal\Message +{ + /** + * The location from which the message is sent. + * + * Generated from protobuf field .routeguide.Point location = 1; + */ + protected $location = null; + /** + * The message to be sent. + * + * Generated from protobuf field string message = 2; + */ + protected $message = ''; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type \Routeguide\Point $location + * The location from which the message is sent. + * @type string $message + * The message to be sent. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\RouteGuide::initOnce(); + parent::__construct($data); + } + + /** + * The location from which the message is sent. + * + * Generated from protobuf field .routeguide.Point location = 1; + * @return \Routeguide\Point|null + */ + public function getLocation() + { + return isset($this->location) ? $this->location : null; + } + + public function hasLocation() + { + return isset($this->location); + } + + public function clearLocation() + { + unset($this->location); + } + + /** + * The location from which the message is sent. + * + * Generated from protobuf field .routeguide.Point location = 1; + * @param \Routeguide\Point $var + * @return $this + */ + public function setLocation($var) + { + GPBUtil::checkMessage($var, \Routeguide\Point::class); + $this->location = $var; + + return $this; + } + + /** + * The message to be sent. + * + * Generated from protobuf field string message = 2; + * @return string + */ + public function getMessage() + { + return $this->message; + } + + /** + * The message to be sent. + * + * Generated from protobuf field string message = 2; + * @param string $var + * @return $this + */ + public function setMessage($var) + { + GPBUtil::checkString($var, True); + $this->message = $var; + + return $this; + } + +} + diff --git a/examples/php/route_guide/Routeguide/RouteSummary.php b/examples/php/route_guide/Routeguide/RouteSummary.php new file mode 100644 index 00000000000..23c264aa8fa --- /dev/null +++ b/examples/php/route_guide/Routeguide/RouteSummary.php @@ -0,0 +1,172 @@ +routeguide.RouteSummary + */ +class RouteSummary extends \Google\Protobuf\Internal\Message +{ + /** + * The number of points received. + * + * Generated from protobuf field int32 point_count = 1; + */ + protected $point_count = 0; + /** + * The number of known features passed while traversing the route. + * + * Generated from protobuf field int32 feature_count = 2; + */ + protected $feature_count = 0; + /** + * The distance covered in metres. + * + * Generated from protobuf field int32 distance = 3; + */ + protected $distance = 0; + /** + * The duration of the traversal in seconds. + * + * Generated from protobuf field int32 elapsed_time = 4; + */ + protected $elapsed_time = 0; + + /** + * Constructor. + * + * @param array $data { + * Optional. Data for populating the Message object. + * + * @type int $point_count + * The number of points received. + * @type int $feature_count + * The number of known features passed while traversing the route. + * @type int $distance + * The distance covered in metres. + * @type int $elapsed_time + * The duration of the traversal in seconds. + * } + */ + public function __construct($data = NULL) { + \GPBMetadata\RouteGuide::initOnce(); + parent::__construct($data); + } + + /** + * The number of points received. + * + * Generated from protobuf field int32 point_count = 1; + * @return int + */ + public function getPointCount() + { + return $this->point_count; + } + + /** + * The number of points received. + * + * Generated from protobuf field int32 point_count = 1; + * @param int $var + * @return $this + */ + public function setPointCount($var) + { + GPBUtil::checkInt32($var); + $this->point_count = $var; + + return $this; + } + + /** + * The number of known features passed while traversing the route. + * + * Generated from protobuf field int32 feature_count = 2; + * @return int + */ + public function getFeatureCount() + { + return $this->feature_count; + } + + /** + * The number of known features passed while traversing the route. + * + * Generated from protobuf field int32 feature_count = 2; + * @param int $var + * @return $this + */ + public function setFeatureCount($var) + { + GPBUtil::checkInt32($var); + $this->feature_count = $var; + + return $this; + } + + /** + * The distance covered in metres. + * + * Generated from protobuf field int32 distance = 3; + * @return int + */ + public function getDistance() + { + return $this->distance; + } + + /** + * The distance covered in metres. + * + * Generated from protobuf field int32 distance = 3; + * @param int $var + * @return $this + */ + public function setDistance($var) + { + GPBUtil::checkInt32($var); + $this->distance = $var; + + return $this; + } + + /** + * The duration of the traversal in seconds. + * + * Generated from protobuf field int32 elapsed_time = 4; + * @return int + */ + public function getElapsedTime() + { + return $this->elapsed_time; + } + + /** + * The duration of the traversal in seconds. + * + * Generated from protobuf field int32 elapsed_time = 4; + * @param int $var + * @return $this + */ + public function setElapsedTime($var) + { + GPBUtil::checkInt32($var); + $this->elapsed_time = $var; + + return $this; + } + +} + diff --git a/examples/php/route_guide/route_guide_db.json b/examples/php/route_guide/route_guide_db.json new file mode 100644 index 00000000000..9d6a980ab7d --- /dev/null +++ b/examples/php/route_guide/route_guide_db.json @@ -0,0 +1,601 @@ +[{ + "location": { + "latitude": 407838351, + "longitude": -746143763 + }, + "name": "Patriots Path, Mendham, NJ 07945, USA" +}, { + "location": { + "latitude": 408122808, + "longitude": -743999179 + }, + "name": "101 New Jersey 10, Whippany, NJ 07981, USA" +}, { + "location": { + "latitude": 413628156, + "longitude": -749015468 + }, + "name": "U.S. 6, Shohola, PA 18458, USA" +}, { + "location": { + "latitude": 419999544, + "longitude": -740371136 + }, + "name": "5 Conners Road, Kingston, NY 12401, USA" +}, { + "location": { + "latitude": 414008389, + "longitude": -743951297 + }, + "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA" +}, { + "location": { + "latitude": 419611318, + "longitude": -746524769 + }, + "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA" +}, { + "location": { + "latitude": 406109563, + "longitude": -742186778 + }, + "name": "4001 Tremley Point Road, Linden, NJ 07036, USA" +}, { + "location": { + "latitude": 416802456, + "longitude": -742370183 + }, + "name": "352 South Mountain Road, Wallkill, NY 12589, USA" +}, { + "location": { + "latitude": 412950425, + "longitude": -741077389 + }, + "name": "Bailey Turn Road, Harriman, NY 10926, USA" +}, { + "location": { + "latitude": 412144655, + "longitude": -743949739 + }, + "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA" +}, { + "location": { + "latitude": 415736605, + "longitude": -742847522 + }, + "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA" +}, { + "location": { + "latitude": 413843930, + "longitude": -740501726 + }, + "name": "162 Merrill Road, Highland Mills, NY 10930, USA" +}, { + "location": { + "latitude": 410873075, + "longitude": -744459023 + }, + "name": "Clinton Road, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 412346009, + "longitude": -744026814 + }, + "name": "16 Old Brook Lane, Warwick, NY 10990, USA" +}, { + "location": { + "latitude": 402948455, + "longitude": -747903913 + }, + "name": "3 Drake Lane, Pennington, NJ 08534, USA" +}, { + "location": { + "latitude": 406337092, + "longitude": -740122226 + }, + "name": "6324 8th Avenue, Brooklyn, NY 11220, USA" +}, { + "location": { + "latitude": 406421967, + "longitude": -747727624 + }, + "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA" +}, { + "location": { + "latitude": 416318082, + "longitude": -749677716 + }, + "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA" +}, { + "location": { + "latitude": 415301720, + "longitude": -748416257 + }, + "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA" +}, { + "location": { + "latitude": 402647019, + "longitude": -747071791 + }, + "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA" +}, { + "location": { + "latitude": 412567807, + "longitude": -741058078 + }, + "name": "New York State Reference Route 987E, Southfields, NY 10975, USA" +}, { + "location": { + "latitude": 416855156, + "longitude": -744420597 + }, + "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA" +}, { + "location": { + "latitude": 404663628, + "longitude": -744820157 + }, + "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA" +}, { + "location": { + "latitude": 407113723, + "longitude": -749746483 + }, + "name": "" +}, { + "location": { + "latitude": 402133926, + "longitude": -743613249 + }, + "name": "" +}, { + "location": { + "latitude": 400273442, + "longitude": -741220915 + }, + "name": "" +}, { + "location": { + "latitude": 411236786, + "longitude": -744070769 + }, + "name": "" +}, { + "location": { + "latitude": 411633782, + "longitude": -746784970 + }, + "name": "211-225 Plains Road, Augusta, NJ 07822, USA" +}, { + "location": { + "latitude": 415830701, + "longitude": -742952812 + }, + "name": "" +}, { + "location": { + "latitude": 413447164, + "longitude": -748712898 + }, + "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA" +}, { + "location": { + "latitude": 405047245, + "longitude": -749800722 + }, + "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA" +}, { + "location": { + "latitude": 418858923, + "longitude": -746156790 + }, + "name": "" +}, { + "location": { + "latitude": 417951888, + "longitude": -748484944 + }, + "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA" +}, { + "location": { + "latitude": 407033786, + "longitude": -743977337 + }, + "name": "26 East 3rd Street, New Providence, NJ 07974, USA" +}, { + "location": { + "latitude": 417548014, + "longitude": -740075041 + }, + "name": "" +}, { + "location": { + "latitude": 410395868, + "longitude": -744972325 + }, + "name": "" +}, { + "location": { + "latitude": 404615353, + "longitude": -745129803 + }, + "name": "" +}, { + "location": { + "latitude": 406589790, + "longitude": -743560121 + }, + "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA" +}, { + "location": { + "latitude": 414653148, + "longitude": -740477477 + }, + "name": "18 Lannis Avenue, New Windsor, NY 12553, USA" +}, { + "location": { + "latitude": 405957808, + "longitude": -743255336 + }, + "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA" +}, { + "location": { + "latitude": 411733589, + "longitude": -741648093 + }, + "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA" +}, { + "location": { + "latitude": 412676291, + "longitude": -742606606 + }, + "name": "1270 Lakes Road, Monroe, NY 10950, USA" +}, { + "location": { + "latitude": 409224445, + "longitude": -748286738 + }, + "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA" +}, { + "location": { + "latitude": 406523420, + "longitude": -742135517 + }, + "name": "652 Garden Street, Elizabeth, NJ 07202, USA" +}, { + "location": { + "latitude": 401827388, + "longitude": -740294537 + }, + "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA" +}, { + "location": { + "latitude": 410564152, + "longitude": -743685054 + }, + "name": "13-17 Stanley Street, West Milford, NJ 07480, USA" +}, { + "location": { + "latitude": 408472324, + "longitude": -740726046 + }, + "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA" +}, { + "location": { + "latitude": 412452168, + "longitude": -740214052 + }, + "name": "5 White Oak Lane, Stony Point, NY 10980, USA" +}, { + "location": { + "latitude": 409146138, + "longitude": -746188906 + }, + "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA" +}, { + "location": { + "latitude": 404701380, + "longitude": -744781745 + }, + "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 409642566, + "longitude": -746017679 + }, + "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA" +}, { + "location": { + "latitude": 408031728, + "longitude": -748645385 + }, + "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA" +}, { + "location": { + "latitude": 413700272, + "longitude": -742135189 + }, + "name": "367 Prospect Road, Chester, NY 10918, USA" +}, { + "location": { + "latitude": 404310607, + "longitude": -740282632 + }, + "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA" +}, { + "location": { + "latitude": 409319800, + "longitude": -746201391 + }, + "name": "11 Ward Street, Mount Arlington, NJ 07856, USA" +}, { + "location": { + "latitude": 406685311, + "longitude": -742108603 + }, + "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA" +}, { + "location": { + "latitude": 419018117, + "longitude": -749142781 + }, + "name": "43 Dreher Road, Roscoe, NY 12776, USA" +}, { + "location": { + "latitude": 412856162, + "longitude": -745148837 + }, + "name": "Swan Street, Pine Island, NY 10969, USA" +}, { + "location": { + "latitude": 416560744, + "longitude": -746721964 + }, + "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA" +}, { + "location": { + "latitude": 405314270, + "longitude": -749836354 + }, + "name": "" +}, { + "location": { + "latitude": 414219548, + "longitude": -743327440 + }, + "name": "" +}, { + "location": { + "latitude": 415534177, + "longitude": -742900616 + }, + "name": "565 Winding Hills Road, Montgomery, NY 12549, USA" +}, { + "location": { + "latitude": 406898530, + "longitude": -749127080 + }, + "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA" +}, { + "location": { + "latitude": 407586880, + "longitude": -741670168 + }, + "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA" +}, { + "location": { + "latitude": 400106455, + "longitude": -742870190 + }, + "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA" +}, { + "location": { + "latitude": 400066188, + "longitude": -746793294 + }, + "name": "" +}, { + "location": { + "latitude": 418803880, + "longitude": -744102673 + }, + "name": "40 Mountain Road, Napanoch, NY 12458, USA" +}, { + "location": { + "latitude": 414204288, + "longitude": -747895140 + }, + "name": "" +}, { + "location": { + "latitude": 414777405, + "longitude": -740615601 + }, + "name": "" +}, { + "location": { + "latitude": 415464475, + "longitude": -747175374 + }, + "name": "48 North Road, Forestburgh, NY 12777, USA" +}, { + "location": { + "latitude": 404062378, + "longitude": -746376177 + }, + "name": "" +}, { + "location": { + "latitude": 405688272, + "longitude": -749285130 + }, + "name": "" +}, { + "location": { + "latitude": 400342070, + "longitude": -748788996 + }, + "name": "" +}, { + "location": { + "latitude": 401809022, + "longitude": -744157964 + }, + "name": "" +}, { + "location": { + "latitude": 404226644, + "longitude": -740517141 + }, + "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA" +}, { + "location": { + "latitude": 410322033, + "longitude": -747871659 + }, + "name": "" +}, { + "location": { + "latitude": 407100674, + "longitude": -747742727 + }, + "name": "" +}, { + "location": { + "latitude": 418811433, + "longitude": -741718005 + }, + "name": "213 Bush Road, Stone Ridge, NY 12484, USA" +}, { + "location": { + "latitude": 415034302, + "longitude": -743850945 + }, + "name": "" +}, { + "location": { + "latitude": 411349992, + "longitude": -743694161 + }, + "name": "" +}, { + "location": { + "latitude": 404839914, + "longitude": -744759616 + }, + "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA" +}, { + "location": { + "latitude": 414638017, + "longitude": -745957854 + }, + "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA" +}, { + "location": { + "latitude": 412127800, + "longitude": -740173578 + }, + "name": "" +}, { + "location": { + "latitude": 401263460, + "longitude": -747964303 + }, + "name": "" +}, { + "location": { + "latitude": 412843391, + "longitude": -749086026 + }, + "name": "" +}, { + "location": { + "latitude": 418512773, + "longitude": -743067823 + }, + "name": "" +}, { + "location": { + "latitude": 404318328, + "longitude": -740835638 + }, + "name": "42-102 Main Street, Belford, NJ 07718, USA" +}, { + "location": { + "latitude": 419020746, + "longitude": -741172328 + }, + "name": "" +}, { + "location": { + "latitude": 404080723, + "longitude": -746119569 + }, + "name": "" +}, { + "location": { + "latitude": 401012643, + "longitude": -744035134 + }, + "name": "" +}, { + "location": { + "latitude": 404306372, + "longitude": -741079661 + }, + "name": "" +}, { + "location": { + "latitude": 403966326, + "longitude": -748519297 + }, + "name": "" +}, { + "location": { + "latitude": 405002031, + "longitude": -748407866 + }, + "name": "" +}, { + "location": { + "latitude": 409532885, + "longitude": -742200683 + }, + "name": "" +}, { + "location": { + "latitude": 416851321, + "longitude": -742674555 + }, + "name": "" +}, { + "location": { + "latitude": 406411633, + "longitude": -741722051 + }, + "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA" +}, { + "location": { + "latitude": 413069058, + "longitude": -744597778 + }, + "name": "261 Van Sickle Road, Goshen, NY 10924, USA" +}, { + "location": { + "latitude": 418465462, + "longitude": -746859398 + }, + "name": "" +}, { + "location": { + "latitude": 411733222, + "longitude": -744228360 + }, + "name": "" +}, { + "location": { + "latitude": 410248224, + "longitude": -747127767 + }, + "name": "3 Hasta Way, Newton, NJ 07860, USA" +}] diff --git a/examples/php/route_guide/route_guide_proto_gen.sh b/examples/php/route_guide/route_guide_proto_gen.sh index bfd7cdb725c..8b7e61c42f2 100755 --- a/examples/php/route_guide/route_guide_proto_gen.sh +++ b/examples/php/route_guide/route_guide_proto_gen.sh @@ -13,4 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -protoc --proto_path=./../../protos --php_out=./ --grpc_out=./ --plugin=protoc-gen-grpc=./../../../bins/opt/grpc_php_plugin ./../../protos/route_guide.proto +set -e + +cd $(dirname $0)/../../.. + +# protoc and grpc_*_plugin binaries can be obtained by running +# $ bazel build @com_google_protobuf//:protoc //src/compiler:all +PROTOC=bazel-bin/external/com_google_protobuf/protoc +PLUGIN=protoc-gen-grpc=bazel-bin/src/compiler/grpc_php_plugin + +$PROTOC --proto_path=examples/protos \ + --php_out=examples/php/route_guide \ + --grpc_out=generate_server:examples/php/route_guide \ + --plugin=$PLUGIN examples/protos/route_guide.proto diff --git a/examples/php/route_guide/route_guide_server.php b/examples/php/route_guide/route_guide_server.php new file mode 100644 index 00000000000..29b086f182d --- /dev/null +++ b/examples/php/route_guide/route_guide_server.php @@ -0,0 +1,34 @@ +addHttp2Port('0.0.0.0:50051'); +$server->handle(new RouteGuideService($routeDbFile)); +$server->run(); diff --git a/examples/python/xds/README.md b/examples/python/xds/README.md index cd9587a421c..cba8c0691b9 100644 --- a/examples/python/xds/README.md +++ b/examples/python/xds/README.md @@ -56,7 +56,7 @@ export GRPC_XDS_BOOTSTRAP=/etc/xds-bootstrap.json 3. Run the client: ``` -python client.py xds-experimental:///my-backend +python client.py xds:///my-backend ``` ### Verifying Configuration with a CLI Tool @@ -101,3 +101,23 @@ grpc.health.v1.Health/Check "status": "SERVING" } ``` + +### Running with Proxyless Security + +#### Run the Server with Secure Credentials + +Add the `--secure true` flag to the invocation outlined above. + +```sh +python server.py --secure true +``` + +#### Run the Client with Secure Credentials + +Add the `--secure true` flag to the invocation outlined above. + +3. Run the client: + +``` +python client.py xds:///my-backend --secure true +``` diff --git a/examples/python/xds/client.py b/examples/python/xds/client.py index ee300265a92..a969b603fad 100644 --- a/examples/python/xds/client.py +++ b/examples/python/xds/client.py @@ -18,6 +18,7 @@ import logging import argparse import grpc +import grpc.experimental import helloworld_pb2 import helloworld_pb2_grpc @@ -25,11 +26,17 @@ import helloworld_pb2_grpc _DESCRIPTION = "Get a greeting from a server." -def run(server_address): - with grpc.insecure_channel(server_address) as channel: +def run(server_address, secure): + if secure: + fallback_creds = grpc.experimental.insecure_channel_credentials() + channel_creds = grpc.xds_channel_credentials(fallback_creds) + channel = grpc.secure_channel(server_address, channel_creds) + else: + channel = grpc.insecure_channel(server_address) + with channel: stub = helloworld_pb2_grpc.GreeterStub(channel) response = stub.SayHello(helloworld_pb2.HelloRequest(name='you')) - print("Greeter client received: " + response.message) + print("Greeter client received: " + response.message) if __name__ == '__main__': @@ -37,6 +44,10 @@ if __name__ == '__main__': parser.add_argument("server", default=None, help="The address of the server.") + parser.add_argument( + "--xds-creds", + action="store_true", + help="If specified, uses xDS credentials to connect to the server.") args = parser.parse_args() logging.basicConfig() - run(args.server) + run(args.server, args.xds_creds) diff --git a/examples/python/xds/requirements.txt b/examples/python/xds/requirements.txt index 7ba651e351a..6be56983639 100644 --- a/examples/python/xds/requirements.txt +++ b/examples/python/xds/requirements.txt @@ -1,4 +1,4 @@ -grpcio>=1.28.1 +grpcio>=1.37.1 protobuf grpcio-reflection grpcio-health-checking diff --git a/examples/python/xds/server.py b/examples/python/xds/server.py index 196e2c11f3a..82fabf26641 100644 --- a/examples/python/xds/server.py +++ b/examples/python/xds/server.py @@ -16,7 +16,6 @@ from concurrent import futures import argparse import logging -import multiprocessing import socket import grpc @@ -31,6 +30,16 @@ from grpc_health.v1 import health_pb2_grpc _DESCRIPTION = "A general purpose phony server." +_LISTEN_HOST = "[::]" + +_THREAD_POOL_SIZE = 256 + +logger = logging.getLogger() +console_handler = logging.StreamHandler() +formatter = logging.Formatter(fmt='%(asctime)s: %(levelname)-8s %(message)s') +console_handler.setFormatter(formatter) +logger.addHandler(console_handler) + class Greeter(helloworld_pb2_grpc.GreeterServicer): @@ -43,19 +52,17 @@ class Greeter(helloworld_pb2_grpc.GreeterServicer): message=f"Hello {request.name} from {self._hostname}!") -def serve(port: int, hostname: str): - server = grpc.server( - futures.ThreadPoolExecutor(max_workers=multiprocessing.cpu_count())) - - # Add the application servicer to the server. - helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(hostname), server) +def _configure_maintenance_server(server: grpc.Server, + maintenance_port: int) -> None: + listen_address = f"{_LISTEN_HOST}:{maintenance_port}" + server.add_insecure_port(listen_address) # Create a health check servicer. We use the non-blocking implementation # to avoid thread starvation. health_servicer = health.HealthServicer( experimental_non_blocking=True, - experimental_thread_pool=futures.ThreadPoolExecutor(max_workers=1)) - health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server) + experimental_thread_pool=futures.ThreadPoolExecutor( + max_workers=_THREAD_POOL_SIZE)) # Create a tuple of all of the services we want to export via reflection. services = tuple( @@ -63,18 +70,57 @@ def serve(port: int, hostname: str): for service in helloworld_pb2.DESCRIPTOR.services_by_name.values()) + ( reflection.SERVICE_NAME, health.SERVICE_NAME) - # Add the reflection service to the server. - reflection.enable_server_reflection(services, server) - server.add_insecure_port(f"[::]:{port}") - server.start() - # Mark all services as healthy. - overall_server_health = "" - for service in services + (overall_server_health,): + health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server) + for service in services: health_servicer.set(service, health_pb2.HealthCheckResponse.SERVING) + reflection.enable_server_reflection(services, server) - # Park the main application thread. - server.wait_for_termination() + +def _configure_greeter_server(server: grpc.Server, port: int, secure_mode: bool, + hostname) -> None: + # Add the application servicer to the server. + helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(hostname), server) + listen_address = f"{_LISTEN_HOST}:{port}" + if not secure_mode: + server.add_insecure_port(listen_address) + else: + # Use xDS credentials. + logger.info("Running with xDS Server credentials") + + # Fall back to insecure credentials. + server_fallback_creds = grpc.insecure_server_credentials() + server_creds = grpc.xds_server_credentials(server_fallback_creds) + server.add_secure_port(listen_address, server_creds) + + +def serve(port: int, hostname: str, maintenance_port: int, + secure_mode: bool) -> None: + if port == maintenance_port: + # If maintenance port and port are the same, start a single server. + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=_THREAD_POOL_SIZE)) + _configure_greeter_server(server, port, secure_mode, hostname) + _configure_maintenance_server(server, maintenance_port) + server.start() + logger.info("Greeter server listening on port %d", port) + logger.info("Maintenance server listening on port %d", maintenance_port) + server.wait_for_termination() + else: + # Otherwise, start two different servers. + greeter_server = grpc.server( + futures.ThreadPoolExecutor(max_workers=_THREAD_POOL_SIZE), + xds=secure_mode) + _configure_greeter_server(greeter_server, port, secure_mode, hostname) + greeter_server.start() + logger.info("Greeter server listening on port %d", port) + maintenance_server = grpc.server( + futures.ThreadPoolExecutor(max_workers=_THREAD_POOL_SIZE)) + _configure_maintenance_server(maintenance_server, maintenance_port) + maintenance_server.start() + logger.info("Maintenance server listening on port %d", maintenance_port) + greeter_server.wait_for_termination() + maintenance_server.wait_for_termination() if __name__ == '__main__': @@ -89,6 +135,11 @@ if __name__ == '__main__': default=None, nargs="?", help="The name clients will see in responses.") + parser.add_argument( + "--xds-creds", + action="store_true", + help="If specified, uses xDS credentials to connect to the server.") args = parser.parse_args() logging.basicConfig() - serve(args.port, args.hostname) + logger.setLevel(logging.INFO) + serve(args.port, args.hostname, args.port + 1, args.xds_creds) diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec index 69f5b8290e0..e7cb9bc1b2d 100644 --- a/gRPC-C++.podspec +++ b/gRPC-C++.podspec @@ -22,7 +22,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-C++' # TODO (mxyan): use version that match gRPC version when pod is stabilized - version = '1.37.0-dev' + version = '1.38.0-dev' s.version = version s.summary = 'gRPC C++ library' s.homepage = 'https://grpc.io' @@ -118,6 +118,7 @@ Pod::Spec.new do |s| 'include/grpcpp/impl/codegen/message_allocator.h', 'include/grpcpp/impl/codegen/metadata_map.h', 'include/grpcpp/impl/codegen/method_handler.h', + 'include/grpcpp/impl/codegen/method_handler_impl.h', 'include/grpcpp/impl/codegen/rpc_method.h', 'include/grpcpp/impl/codegen/rpc_service_method.h', 'include/grpcpp/impl/codegen/security/auth_context.h', @@ -185,10 +186,9 @@ Pod::Spec.new do |s| ss.header_mappings_dir = '.' ss.dependency "#{s.name}/Interface", version ss.dependency 'gRPC-Core', version - abseil_version = '1.20200923.3' + abseil_version = '1.20210324.0' ss.dependency 'abseil/base/base', abseil_version ss.dependency 'abseil/container/flat_hash_map', abseil_version - ss.dependency 'abseil/container/flat_hash_set', abseil_version ss.dependency 'abseil/container/inlined_vector', abseil_version ss.dependency 'abseil/functional/bind_front', abseil_version ss.dependency 'abseil/memory/memory', abseil_version @@ -221,6 +221,7 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', + 'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h', 'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h', @@ -238,6 +239,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver_factory.h', 'src/core/ext/filters/client_channel/resolver_registry.h', 'src/core/ext/filters/client_channel/resolver_result_parsing.h', + 'src/core/ext/filters/client_channel/retry_filter.h', + 'src/core/ext/filters/client_channel/retry_service_config.h', 'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/server_address.h', 'src/core/ext/filters/client_channel/service_config.h', @@ -247,6 +250,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/subchannel_interface.h', 'src/core/ext/filters/client_channel/subchannel_pool_interface.h', 'src/core/ext/filters/deadline/deadline_filter.h', + 'src/core/ext/filters/fault_injection/fault_injection_filter.h', + 'src/core/ext/filters/fault_injection/service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/http/message_compress/message_compress_filter.h', @@ -282,9 +287,11 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/transport/stream_map.h', 'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/inproc/inproc_transport.h', + 'src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h', 'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h', 'src/core/ext/upb-generated/envoy/annotations/resource.upb.h', 'src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h', + 'src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.h', @@ -309,12 +316,16 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h', 'src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h', 'src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h', + 'src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h', + 'src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h', 'src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h', 'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h', 'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h', @@ -329,11 +340,14 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.h', 'src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h', 'src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h', + 'src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h', 'src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.h', 'src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.h', @@ -372,9 +386,11 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/xds/core/v3/resource.upb.h', 'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h', 'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h', + 'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.h', @@ -399,11 +415,15 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h', @@ -418,11 +438,14 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.h', @@ -463,7 +486,10 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_channel_args.h', 'src/core/ext/xds/xds_client.h', 'src/core/ext/xds/xds_client_stats.h', + 'src/core/ext/xds/xds_http_fault_filter.h', 'src/core/ext/xds/xds_http_filters.h', + 'src/core/lib/address_utils/parse_address.h', + 'src/core/lib/address_utils/sockaddr_utils.h', 'src/core/lib/avl/avl.h', 'src/core/lib/backoff/backoff.h', 'src/core/lib/channel/channel_args.h', @@ -521,6 +547,7 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/ref_counted.h', 'src/core/lib/gprpp/ref_counted_ptr.h', 'src/core/lib/gprpp/stat.h', + 'src/core/lib/gprpp/status_helper.h', 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/gprpp/time_util.h', @@ -560,8 +587,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/parse_address.h', - 'src/core/lib/iomgr/poller/eventmanager_libuv.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_custom.h', @@ -578,7 +603,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/sockaddr.h', 'src/core/lib/iomgr/sockaddr_custom.h', 'src/core/lib/iomgr/sockaddr_posix.h', - 'src/core/lib/iomgr/sockaddr_utils.h', 'src/core/lib/iomgr/sockaddr_windows.h', 'src/core/lib/iomgr/socket_factory_posix.h', 'src/core/lib/iomgr/socket_mutator.h', @@ -606,16 +630,8 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/work_serializer.h', 'src/core/lib/json/json.h', 'src/core/lib/json/json_util.h', + 'src/core/lib/matchers/matchers.h', 'src/core/lib/profiling/timers.h', - 'src/core/lib/security/authorization/authorization_engine.h', - 'src/core/lib/security/authorization/evaluate_args.h', - 'src/core/lib/security/authorization/matchers.h', - 'src/core/lib/security/authorization/mock_cel/activation.h', - 'src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h', - 'src/core/lib/security/authorization/mock_cel/cel_expression.h', - 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/authorization/mock_cel/evaluator_core.h', - 'src/core/lib/security/authorization/mock_cel/flat_expr_builder.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.h', 'src/core/lib/security/credentials/alts/check_gcp_environment.h', @@ -814,8 +830,6 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.h', 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.h', - 'third_party/upb/upb/json_decode.h', - 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/port_def.inc', 'third_party/upb/upb/port_undef.inc', @@ -824,7 +838,8 @@ Pod::Spec.new do |s| 'third_party/upb/upb/text_encode.h', 'third_party/upb/upb/upb.h', 'third_party/upb/upb/upb.hpp', - 'third_party/upb/upb/upb.int.h' + 'third_party/upb/upb/upb.int.h', + 'third_party/xxhash/xxhash.h' ss.private_header_files = 'src/core/ext/filters/client_channel/backend_metric.h', 'src/core/ext/filters/client_channel/backup_poller.h', @@ -847,6 +862,7 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', + 'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h', 'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h', @@ -864,6 +880,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver_factory.h', 'src/core/ext/filters/client_channel/resolver_registry.h', 'src/core/ext/filters/client_channel/resolver_result_parsing.h', + 'src/core/ext/filters/client_channel/retry_filter.h', + 'src/core/ext/filters/client_channel/retry_service_config.h', 'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/server_address.h', 'src/core/ext/filters/client_channel/service_config.h', @@ -873,6 +891,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/subchannel_interface.h', 'src/core/ext/filters/client_channel/subchannel_pool_interface.h', 'src/core/ext/filters/deadline/deadline_filter.h', + 'src/core/ext/filters/fault_injection/fault_injection_filter.h', + 'src/core/ext/filters/fault_injection/service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/http/message_compress/message_compress_filter.h', @@ -908,9 +928,11 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/transport/stream_map.h', 'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/inproc/inproc_transport.h', + 'src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h', 'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h', 'src/core/ext/upb-generated/envoy/annotations/resource.upb.h', 'src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h', + 'src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.h', @@ -935,12 +957,16 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h', 'src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h', 'src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h', + 'src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h', + 'src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h', 'src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h', 'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h', 'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h', @@ -955,11 +981,14 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.h', 'src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h', 'src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h', + 'src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h', 'src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.h', 'src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.h', @@ -998,9 +1027,11 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/xds/core/v3/resource.upb.h', 'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h', 'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h', + 'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.h', @@ -1025,11 +1056,15 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h', @@ -1044,11 +1079,14 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.h', @@ -1089,7 +1127,10 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_channel_args.h', 'src/core/ext/xds/xds_client.h', 'src/core/ext/xds/xds_client_stats.h', + 'src/core/ext/xds/xds_http_fault_filter.h', 'src/core/ext/xds/xds_http_filters.h', + 'src/core/lib/address_utils/parse_address.h', + 'src/core/lib/address_utils/sockaddr_utils.h', 'src/core/lib/avl/avl.h', 'src/core/lib/backoff/backoff.h', 'src/core/lib/channel/channel_args.h', @@ -1147,6 +1188,7 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/ref_counted.h', 'src/core/lib/gprpp/ref_counted_ptr.h', 'src/core/lib/gprpp/stat.h', + 'src/core/lib/gprpp/status_helper.h', 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/gprpp/time_util.h', @@ -1186,8 +1228,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/parse_address.h', - 'src/core/lib/iomgr/poller/eventmanager_libuv.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_custom.h', @@ -1204,7 +1244,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/sockaddr.h', 'src/core/lib/iomgr/sockaddr_custom.h', 'src/core/lib/iomgr/sockaddr_posix.h', - 'src/core/lib/iomgr/sockaddr_utils.h', 'src/core/lib/iomgr/sockaddr_windows.h', 'src/core/lib/iomgr/socket_factory_posix.h', 'src/core/lib/iomgr/socket_mutator.h', @@ -1232,16 +1271,8 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/work_serializer.h', 'src/core/lib/json/json.h', 'src/core/lib/json/json_util.h', + 'src/core/lib/matchers/matchers.h', 'src/core/lib/profiling/timers.h', - 'src/core/lib/security/authorization/authorization_engine.h', - 'src/core/lib/security/authorization/evaluate_args.h', - 'src/core/lib/security/authorization/matchers.h', - 'src/core/lib/security/authorization/mock_cel/activation.h', - 'src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h', - 'src/core/lib/security/authorization/mock_cel/cel_expression.h', - 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/authorization/mock_cel/evaluator_core.h', - 'src/core/lib/security/authorization/mock_cel/flat_expr_builder.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.h', 'src/core/lib/security/credentials/alts/check_gcp_environment.h', @@ -1390,8 +1421,6 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.h', 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.h', - 'third_party/upb/upb/json_decode.h', - 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/port_def.inc', 'third_party/upb/upb/port_undef.inc', @@ -1400,7 +1429,8 @@ Pod::Spec.new do |s| 'third_party/upb/upb/text_encode.h', 'third_party/upb/upb/upb.h', 'third_party/upb/upb/upb.hpp', - 'third_party/upb/upb/upb.int.h' + 'third_party/upb/upb/upb.int.h', + 'third_party/xxhash/xxhash.h' end s.subspec 'Protobuf' do |ss| @@ -1442,5 +1472,8 @@ Pod::Spec.new do |s| find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/util/\\1"\\\n#else\\\n #include "util/\\1"\\\n#endif;g' find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g' find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm + find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n #include "third_party/xxhash/xxhash.h"\\\n#else\\\n #include "xxhash.h"\\\n#endif;g' + find third_party/xxhash -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g' + find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm END_OF_COMMAND end diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec index afc596f7290..2c9f8288802 100644 --- a/gRPC-Core.podspec +++ b/gRPC-Core.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-Core' - version = '1.37.0-dev' + version = '1.38.0-dev' s.version = version s.summary = 'Core cross-platform gRPC library, written in C' s.homepage = 'https://grpc.io' @@ -46,7 +46,7 @@ Pod::Spec.new do |s| s.requires_arc = false name = 'grpc' - abseil_version = '1.20200923.3' + abseil_version = '1.20210324.0' # When creating a dynamic framework, name it grpc.framework instead of gRPC-Core.framework. # This lets users write their includes like `#include ` as opposed to `#include @@ -173,10 +173,9 @@ Pod::Spec.new do |s| ss.header_mappings_dir = '.' ss.libraries = 'z' ss.dependency "#{s.name}/Interface", version - ss.dependency 'BoringSSL-GRPC', '0.0.17' + ss.dependency 'BoringSSL-GRPC', '0.0.18' ss.dependency 'abseil/base/base', abseil_version ss.dependency 'abseil/container/flat_hash_map', abseil_version - ss.dependency 'abseil/container/flat_hash_set', abseil_version ss.dependency 'abseil/container/inlined_vector', abseil_version ss.dependency 'abseil/functional/bind_front', abseil_version ss.dependency 'abseil/memory/memory', abseil_version @@ -235,6 +234,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', 'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc', 'src/core/ext/filters/client_channel/lb_policy/priority/priority.cc', + 'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc', + 'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h', 'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc', 'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h', 'src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc', @@ -278,6 +279,10 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver_registry.h', 'src/core/ext/filters/client_channel/resolver_result_parsing.cc', 'src/core/ext/filters/client_channel/resolver_result_parsing.h', + 'src/core/ext/filters/client_channel/retry_filter.cc', + 'src/core/ext/filters/client_channel/retry_filter.h', + 'src/core/ext/filters/client_channel/retry_service_config.cc', + 'src/core/ext/filters/client_channel/retry_service_config.h', 'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/server_address.cc', @@ -296,6 +301,10 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_idle/client_idle_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.h', + 'src/core/ext/filters/fault_injection/fault_injection_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_filter.h', + 'src/core/ext/filters/fault_injection/service_config_parser.cc', + 'src/core/ext/filters/fault_injection/service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.cc', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.cc', @@ -376,12 +385,16 @@ Pod::Spec.new do |s| 'src/core/ext/transport/inproc/inproc_plugin.cc', 'src/core/ext/transport/inproc/inproc_transport.cc', 'src/core/ext/transport/inproc/inproc_transport.h', + 'src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c', + 'src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h', 'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c', 'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h', 'src/core/ext/upb-generated/envoy/annotations/resource.upb.c', 'src/core/ext/upb-generated/envoy/annotations/resource.upb.h', 'src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c', 'src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h', + 'src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c', + 'src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c', 'src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c', @@ -430,6 +443,10 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h', 'src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c', 'src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h', + 'src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c', + 'src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h', + 'src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c', + 'src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h', 'src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c', 'src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c', @@ -442,6 +459,10 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h', 'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c', 'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c', @@ -470,8 +491,12 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h', 'src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c', 'src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h', + 'src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c', + 'src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c', @@ -480,6 +505,8 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h', 'src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c', @@ -556,12 +583,16 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h', 'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c', 'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h', + 'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c', @@ -610,6 +641,10 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c', @@ -620,6 +655,10 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c', @@ -648,8 +687,12 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c', @@ -658,6 +701,8 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c', @@ -736,9 +781,15 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_client.h', 'src/core/ext/xds/xds_client_stats.cc', 'src/core/ext/xds/xds_client_stats.h', + 'src/core/ext/xds/xds_http_fault_filter.cc', + 'src/core/ext/xds/xds_http_fault_filter.h', 'src/core/ext/xds/xds_http_filters.cc', 'src/core/ext/xds/xds_http_filters.h', 'src/core/ext/xds/xds_server_config_fetcher.cc', + 'src/core/lib/address_utils/parse_address.cc', + 'src/core/lib/address_utils/parse_address.h', + 'src/core/lib/address_utils/sockaddr_utils.cc', + 'src/core/lib/address_utils/sockaddr_utils.h', 'src/core/lib/avl/avl.cc', 'src/core/lib/avl/avl.h', 'src/core/lib/backoff/backoff.cc', @@ -858,6 +909,8 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/stat.h', 'src/core/lib/gprpp/stat_posix.cc', 'src/core/lib/gprpp/stat_windows.cc', + 'src/core/lib/gprpp/status_helper.cc', + 'src/core/lib/gprpp/status_helper.h', 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/gprpp/thd_posix.cc', @@ -945,10 +998,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/lockfree_event.cc', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/parse_address.cc', - 'src/core/lib/iomgr/parse_address.h', - 'src/core/lib/iomgr/poller/eventmanager_libuv.cc', - 'src/core/lib/iomgr/poller/eventmanager_libuv.h', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.cc', @@ -978,8 +1027,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/sockaddr.h', 'src/core/lib/iomgr/sockaddr_custom.h', 'src/core/lib/iomgr/sockaddr_posix.h', - 'src/core/lib/iomgr/sockaddr_utils.cc', - 'src/core/lib/iomgr/sockaddr_utils.h', 'src/core/lib/iomgr/sockaddr_windows.h', 'src/core/lib/iomgr/socket_factory_posix.cc', 'src/core/lib/iomgr/socket_factory_posix.h', @@ -1049,21 +1096,11 @@ Pod::Spec.new do |s| 'src/core/lib/json/json_util.cc', 'src/core/lib/json/json_util.h', 'src/core/lib/json/json_writer.cc', + 'src/core/lib/matchers/matchers.cc', + 'src/core/lib/matchers/matchers.h', 'src/core/lib/profiling/basic_timers.cc', 'src/core/lib/profiling/stap_timers.cc', 'src/core/lib/profiling/timers.h', - 'src/core/lib/security/authorization/authorization_engine.cc', - 'src/core/lib/security/authorization/authorization_engine.h', - 'src/core/lib/security/authorization/evaluate_args.cc', - 'src/core/lib/security/authorization/evaluate_args.h', - 'src/core/lib/security/authorization/matchers.cc', - 'src/core/lib/security/authorization/matchers.h', - 'src/core/lib/security/authorization/mock_cel/activation.h', - 'src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h', - 'src/core/lib/security/authorization/mock_cel/cel_expression.h', - 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/authorization/mock_cel/evaluator_core.h', - 'src/core/lib/security/authorization/mock_cel/flat_expr_builder.h', 'src/core/lib/security/context/security_context.cc', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.cc', @@ -1349,10 +1386,6 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.c', 'third_party/upb/upb/encode.h', - 'third_party/upb/upb/json_decode.c', - 'third_party/upb/upb/json_decode.h', - 'third_party/upb/upb/json_encode.c', - 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.c', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/port_def.inc', @@ -1366,7 +1399,8 @@ Pod::Spec.new do |s| 'third_party/upb/upb/upb.c', 'third_party/upb/upb/upb.h', 'third_party/upb/upb/upb.hpp', - 'third_party/upb/upb/upb.int.h' + 'third_party/upb/upb/upb.int.h', + 'third_party/xxhash/xxhash.h' ss.private_header_files = 'src/core/ext/filters/client_channel/backend_metric.h', 'src/core/ext/filters/client_channel/backup_poller.h', 'src/core/ext/filters/client_channel/client_channel.h', @@ -1388,6 +1422,7 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h', 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h', + 'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h', 'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds.h', 'src/core/ext/filters/client_channel/lb_policy/xds/xds_channel_args.h', @@ -1405,6 +1440,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/resolver_factory.h', 'src/core/ext/filters/client_channel/resolver_registry.h', 'src/core/ext/filters/client_channel/resolver_result_parsing.h', + 'src/core/ext/filters/client_channel/retry_filter.h', + 'src/core/ext/filters/client_channel/retry_service_config.h', 'src/core/ext/filters/client_channel/retry_throttle.h', 'src/core/ext/filters/client_channel/server_address.h', 'src/core/ext/filters/client_channel/service_config.h', @@ -1414,6 +1451,8 @@ Pod::Spec.new do |s| 'src/core/ext/filters/client_channel/subchannel_interface.h', 'src/core/ext/filters/client_channel/subchannel_pool_interface.h', 'src/core/ext/filters/deadline/deadline_filter.h', + 'src/core/ext/filters/fault_injection/fault_injection_filter.h', + 'src/core/ext/filters/fault_injection/service_config_parser.h', 'src/core/ext/filters/http/client/http_client_filter.h', 'src/core/ext/filters/http/client_authority_filter.h', 'src/core/ext/filters/http/message_compress/message_compress_filter.h', @@ -1449,9 +1488,11 @@ Pod::Spec.new do |s| 'src/core/ext/transport/chttp2/transport/stream_map.h', 'src/core/ext/transport/chttp2/transport/varint.h', 'src/core/ext/transport/inproc/inproc_transport.h', + 'src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h', 'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h', 'src/core/ext/upb-generated/envoy/annotations/resource.upb.h', 'src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h', + 'src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.h', 'src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.h', @@ -1476,12 +1517,16 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.h', 'src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h', 'src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h', + 'src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h', + 'src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h', 'src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/route.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h', 'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.h', 'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h', 'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h', + 'src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.h', @@ -1496,11 +1541,14 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.h', 'src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h', 'src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h', + 'src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h', 'src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h', 'src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.h', 'src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.h', @@ -1539,9 +1587,11 @@ Pod::Spec.new do |s| 'src/core/ext/upb-generated/xds/core/v3/resource.upb.h', 'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h', 'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h', + 'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.h', @@ -1566,11 +1616,15 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.h', @@ -1585,11 +1639,14 @@ Pod::Spec.new do |s| 'src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.h', 'src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.h', @@ -1630,7 +1687,10 @@ Pod::Spec.new do |s| 'src/core/ext/xds/xds_channel_args.h', 'src/core/ext/xds/xds_client.h', 'src/core/ext/xds/xds_client_stats.h', + 'src/core/ext/xds/xds_http_fault_filter.h', 'src/core/ext/xds/xds_http_filters.h', + 'src/core/lib/address_utils/parse_address.h', + 'src/core/lib/address_utils/sockaddr_utils.h', 'src/core/lib/avl/avl.h', 'src/core/lib/backoff/backoff.h', 'src/core/lib/channel/channel_args.h', @@ -1688,6 +1748,7 @@ Pod::Spec.new do |s| 'src/core/lib/gprpp/ref_counted.h', 'src/core/lib/gprpp/ref_counted_ptr.h', 'src/core/lib/gprpp/stat.h', + 'src/core/lib/gprpp/status_helper.h', 'src/core/lib/gprpp/sync.h', 'src/core/lib/gprpp/thd.h', 'src/core/lib/gprpp/time_util.h', @@ -1727,8 +1788,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/load_file.h', 'src/core/lib/iomgr/lockfree_event.h', 'src/core/lib/iomgr/nameser.h', - 'src/core/lib/iomgr/parse_address.h', - 'src/core/lib/iomgr/poller/eventmanager_libuv.h', 'src/core/lib/iomgr/polling_entity.h', 'src/core/lib/iomgr/pollset.h', 'src/core/lib/iomgr/pollset_custom.h', @@ -1745,7 +1804,6 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/sockaddr.h', 'src/core/lib/iomgr/sockaddr_custom.h', 'src/core/lib/iomgr/sockaddr_posix.h', - 'src/core/lib/iomgr/sockaddr_utils.h', 'src/core/lib/iomgr/sockaddr_windows.h', 'src/core/lib/iomgr/socket_factory_posix.h', 'src/core/lib/iomgr/socket_mutator.h', @@ -1773,16 +1831,8 @@ Pod::Spec.new do |s| 'src/core/lib/iomgr/work_serializer.h', 'src/core/lib/json/json.h', 'src/core/lib/json/json_util.h', + 'src/core/lib/matchers/matchers.h', 'src/core/lib/profiling/timers.h', - 'src/core/lib/security/authorization/authorization_engine.h', - 'src/core/lib/security/authorization/evaluate_args.h', - 'src/core/lib/security/authorization/matchers.h', - 'src/core/lib/security/authorization/mock_cel/activation.h', - 'src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h', - 'src/core/lib/security/authorization/mock_cel/cel_expression.h', - 'src/core/lib/security/authorization/mock_cel/cel_value.h', - 'src/core/lib/security/authorization/mock_cel/evaluator_core.h', - 'src/core/lib/security/authorization/mock_cel/flat_expr_builder.h', 'src/core/lib/security/context/security_context.h', 'src/core/lib/security/credentials/alts/alts_credentials.h', 'src/core/lib/security/credentials/alts/check_gcp_environment.h', @@ -1920,8 +1970,6 @@ Pod::Spec.new do |s| 'third_party/upb/upb/def.h', 'third_party/upb/upb/def.hpp', 'third_party/upb/upb/encode.h', - 'third_party/upb/upb/json_decode.h', - 'third_party/upb/upb/json_encode.h', 'third_party/upb/upb/msg.h', 'third_party/upb/upb/port_def.inc', 'third_party/upb/upb/port_undef.inc', @@ -1930,7 +1978,8 @@ Pod::Spec.new do |s| 'third_party/upb/upb/text_encode.h', 'third_party/upb/upb/upb.h', 'third_party/upb/upb/upb.hpp', - 'third_party/upb/upb/upb.int.h' + 'third_party/upb/upb/upb.int.h', + 'third_party/xxhash/xxhash.h' end # CFStream is now default. Leaving this subspec only for compatibility purpose. @@ -2034,10 +2083,12 @@ Pod::Spec.new do |s| 'test/core/end2end/tests/request_with_payload.cc', 'test/core/end2end/tests/resource_quota_server.cc', 'test/core/end2end/tests/retry.cc', + 'test/core/end2end/tests/retry_cancel_during_delay.cc', 'test/core/end2end/tests/retry_cancellation.cc', 'test/core/end2end/tests/retry_disabled.cc', 'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc', 'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc', + 'test/core/end2end/tests/retry_lb_drop.cc', 'test/core/end2end/tests/retry_non_retriable_status.cc', 'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc', 'test/core/end2end/tests/retry_recv_initial_metadata.cc', @@ -2067,8 +2118,7 @@ Pod::Spec.new do |s| 'test/core/end2end/tests/write_buffering_at_end.cc', 'test/core/util/cmdline.cc', 'test/core/util/cmdline.h', - 'test/core/util/eval_args_mock_endpoint.cc', - 'test/core/util/eval_args_mock_endpoint.h', + 'test/core/util/evaluate_args_test_util.h', 'test/core/util/fuzzer_util.cc', 'test/core/util/fuzzer_util.h', 'test/core/util/grpc_profiler.cc', @@ -2077,6 +2127,7 @@ Pod::Spec.new do |s| 'test/core/util/histogram.h', 'test/core/util/memory_counters.cc', 'test/core/util/memory_counters.h', + 'test/core/util/mock_authorization_endpoint.h', 'test/core/util/mock_endpoint.cc', 'test/core/util/mock_endpoint.h', 'test/core/util/parse_hexstring.cc', @@ -2100,6 +2151,8 @@ Pod::Spec.new do |s| 'test/core/util/subprocess_windows.cc', 'test/core/util/test_config.cc', 'test/core/util/test_config.h', + 'test/core/util/test_lb_policies.cc', + 'test/core/util/test_lb_policies.h', 'test/core/util/test_tcp_server.cc', 'test/core/util/test_tcp_server.h', 'test/core/util/tls_utils.cc', @@ -2122,5 +2175,8 @@ Pod::Spec.new do |s| find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/util/\\1"\\\n#else\\\n #include "util/\\1"\\\n#endif;g' find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g' find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm + find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n #include "third_party/xxhash/xxhash.h"\\\n#else\\\n #include "xxhash.h"\\\n#endif;g' + find third_party/xxhash -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g' + find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm END_OF_COMMAND end diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec index 036de37cfe8..0f3d5a5acb8 100644 --- a/gRPC-ProtoRPC.podspec +++ b/gRPC-ProtoRPC.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-ProtoRPC' - version = '1.37.0-dev' + version = '1.38.0-dev' s.version = version s.summary = 'RPC library for Protocol Buffers, based on gRPC' s.homepage = 'https://grpc.io' diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec index 9a71e30e2b8..0fe38c90ca8 100644 --- a/gRPC-RxLibrary.podspec +++ b/gRPC-RxLibrary.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.name = 'gRPC-RxLibrary' - version = '1.37.0-dev' + version = '1.38.0-dev' s.version = version s.summary = 'Reactive Extensions library for iOS/OSX.' s.homepage = 'https://grpc.io' diff --git a/gRPC.podspec b/gRPC.podspec index 842a4188b26..0465f81c1ce 100644 --- a/gRPC.podspec +++ b/gRPC.podspec @@ -20,7 +20,7 @@ Pod::Spec.new do |s| s.name = 'gRPC' - version = '1.37.0-dev' + version = '1.38.0-dev' s.version = version s.summary = 'gRPC client library for iOS/OSX' s.homepage = 'https://grpc.io' diff --git a/grpc.def b/grpc.def index 4dcb9edffb8..7be77a61868 100644 --- a/grpc.def +++ b/grpc.def @@ -75,6 +75,7 @@ EXPORTS grpc_resource_quota_unref grpc_resource_quota_resize grpc_resource_quota_set_max_threads + grpc_dump_xds_configs grpc_resource_quota_arg_vtable grpc_channelz_get_top_channels grpc_channelz_get_servers diff --git a/grpc.gemspec b/grpc.gemspec index 2017718df9c..2185cbf0894 100644 --- a/grpc.gemspec +++ b/grpc.gemspec @@ -53,6 +53,10 @@ Gem::Specification.new do |s| s.files += %w( include/grpc/byte_buffer_reader.h ) s.files += %w( include/grpc/census.h ) s.files += %w( include/grpc/compression.h ) + s.files += %w( include/grpc/event_engine/channel_args.h ) + s.files += %w( include/grpc/event_engine/event_engine.h ) + s.files += %w( include/grpc/event_engine/port.h ) + s.files += %w( include/grpc/event_engine/slice_allocator.h ) s.files += %w( include/grpc/fork.h ) s.files += %w( include/grpc/grpc.h ) s.files += %w( include/grpc/grpc_posix.h ) @@ -150,6 +154,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/priority/priority.cc ) + s.files += %w( src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc ) + s.files += %w( src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.h ) s.files += %w( src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc ) @@ -193,6 +199,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_channel/resolver_registry.h ) s.files += %w( src/core/ext/filters/client_channel/resolver_result_parsing.cc ) s.files += %w( src/core/ext/filters/client_channel/resolver_result_parsing.h ) + s.files += %w( src/core/ext/filters/client_channel/retry_filter.cc ) + s.files += %w( src/core/ext/filters/client_channel/retry_filter.h ) + s.files += %w( src/core/ext/filters/client_channel/retry_service_config.cc ) + s.files += %w( src/core/ext/filters/client_channel/retry_service_config.h ) s.files += %w( src/core/ext/filters/client_channel/retry_throttle.cc ) s.files += %w( src/core/ext/filters/client_channel/retry_throttle.h ) s.files += %w( src/core/ext/filters/client_channel/server_address.cc ) @@ -211,6 +221,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/filters/client_idle/client_idle_filter.cc ) s.files += %w( src/core/ext/filters/deadline/deadline_filter.cc ) s.files += %w( src/core/ext/filters/deadline/deadline_filter.h ) + s.files += %w( src/core/ext/filters/fault_injection/fault_injection_filter.cc ) + s.files += %w( src/core/ext/filters/fault_injection/fault_injection_filter.h ) + s.files += %w( src/core/ext/filters/fault_injection/service_config_parser.cc ) + s.files += %w( src/core/ext/filters/fault_injection/service_config_parser.h ) s.files += %w( src/core/ext/filters/http/client/http_client_filter.cc ) s.files += %w( src/core/ext/filters/http/client/http_client_filter.h ) s.files += %w( src/core/ext/filters/http/client_authority_filter.cc ) @@ -291,12 +305,16 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/transport/inproc/inproc_plugin.cc ) s.files += %w( src/core/ext/transport/inproc/inproc_transport.cc ) s.files += %w( src/core/ext/transport/inproc/inproc_transport.h ) + s.files += %w( src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/annotations/deprecation.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/annotations/resource.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/annotations/resource.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c ) @@ -345,6 +363,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c ) @@ -357,6 +379,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c ) @@ -385,8 +411,12 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c ) @@ -395,6 +425,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.h ) + s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c ) + s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c ) s.files += %w( src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.h ) s.files += %w( src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c ) @@ -471,12 +503,16 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.h ) s.files += %w( src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c ) s.files += %w( src/core/ext/upb-generated/xds/core/v3/resource_name.upb.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c ) @@ -525,6 +561,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c ) @@ -535,6 +575,10 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c ) @@ -563,8 +607,12 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c ) @@ -573,6 +621,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.h ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c ) + s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.h ) s.files += %w( src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c ) @@ -651,9 +701,15 @@ Gem::Specification.new do |s| s.files += %w( src/core/ext/xds/xds_client.h ) s.files += %w( src/core/ext/xds/xds_client_stats.cc ) s.files += %w( src/core/ext/xds/xds_client_stats.h ) + s.files += %w( src/core/ext/xds/xds_http_fault_filter.cc ) + s.files += %w( src/core/ext/xds/xds_http_fault_filter.h ) s.files += %w( src/core/ext/xds/xds_http_filters.cc ) s.files += %w( src/core/ext/xds/xds_http_filters.h ) s.files += %w( src/core/ext/xds/xds_server_config_fetcher.cc ) + s.files += %w( src/core/lib/address_utils/parse_address.cc ) + s.files += %w( src/core/lib/address_utils/parse_address.h ) + s.files += %w( src/core/lib/address_utils/sockaddr_utils.cc ) + s.files += %w( src/core/lib/address_utils/sockaddr_utils.h ) s.files += %w( src/core/lib/avl/avl.cc ) s.files += %w( src/core/lib/avl/avl.h ) s.files += %w( src/core/lib/backoff/backoff.cc ) @@ -700,6 +756,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/debug/stats_data.h ) s.files += %w( src/core/lib/debug/trace.cc ) s.files += %w( src/core/lib/debug/trace.h ) + s.files += %w( src/core/lib/event_engine/slice_allocator.cc ) + s.files += %w( src/core/lib/event_engine/sockaddr.cc ) s.files += %w( src/core/lib/gpr/alloc.cc ) s.files += %w( src/core/lib/gpr/alloc.h ) s.files += %w( src/core/lib/gpr/arena.h ) @@ -773,6 +831,8 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/gprpp/stat.h ) s.files += %w( src/core/lib/gprpp/stat_posix.cc ) s.files += %w( src/core/lib/gprpp/stat_windows.cc ) + s.files += %w( src/core/lib/gprpp/status_helper.cc ) + s.files += %w( src/core/lib/gprpp/status_helper.h ) s.files += %w( src/core/lib/gprpp/sync.h ) s.files += %w( src/core/lib/gprpp/thd.h ) s.files += %w( src/core/lib/gprpp/thd_posix.cc ) @@ -860,10 +920,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/lockfree_event.cc ) s.files += %w( src/core/lib/iomgr/lockfree_event.h ) s.files += %w( src/core/lib/iomgr/nameser.h ) - s.files += %w( src/core/lib/iomgr/parse_address.cc ) - s.files += %w( src/core/lib/iomgr/parse_address.h ) - s.files += %w( src/core/lib/iomgr/poller/eventmanager_libuv.cc ) - s.files += %w( src/core/lib/iomgr/poller/eventmanager_libuv.h ) s.files += %w( src/core/lib/iomgr/polling_entity.cc ) s.files += %w( src/core/lib/iomgr/polling_entity.h ) s.files += %w( src/core/lib/iomgr/pollset.cc ) @@ -893,8 +949,6 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/iomgr/sockaddr.h ) s.files += %w( src/core/lib/iomgr/sockaddr_custom.h ) s.files += %w( src/core/lib/iomgr/sockaddr_posix.h ) - s.files += %w( src/core/lib/iomgr/sockaddr_utils.cc ) - s.files += %w( src/core/lib/iomgr/sockaddr_utils.h ) s.files += %w( src/core/lib/iomgr/sockaddr_windows.h ) s.files += %w( src/core/lib/iomgr/socket_factory_posix.cc ) s.files += %w( src/core/lib/iomgr/socket_factory_posix.h ) @@ -964,21 +1018,11 @@ Gem::Specification.new do |s| s.files += %w( src/core/lib/json/json_util.cc ) s.files += %w( src/core/lib/json/json_util.h ) s.files += %w( src/core/lib/json/json_writer.cc ) + s.files += %w( src/core/lib/matchers/matchers.cc ) + s.files += %w( src/core/lib/matchers/matchers.h ) s.files += %w( src/core/lib/profiling/basic_timers.cc ) s.files += %w( src/core/lib/profiling/stap_timers.cc ) s.files += %w( src/core/lib/profiling/timers.h ) - s.files += %w( src/core/lib/security/authorization/authorization_engine.cc ) - s.files += %w( src/core/lib/security/authorization/authorization_engine.h ) - s.files += %w( src/core/lib/security/authorization/evaluate_args.cc ) - s.files += %w( src/core/lib/security/authorization/evaluate_args.h ) - s.files += %w( src/core/lib/security/authorization/matchers.cc ) - s.files += %w( src/core/lib/security/authorization/matchers.h ) - s.files += %w( src/core/lib/security/authorization/mock_cel/activation.h ) - s.files += %w( src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h ) - s.files += %w( src/core/lib/security/authorization/mock_cel/cel_expression.h ) - s.files += %w( src/core/lib/security/authorization/mock_cel/cel_value.h ) - s.files += %w( src/core/lib/security/authorization/mock_cel/evaluator_core.h ) - s.files += %w( src/core/lib/security/authorization/mock_cel/flat_expr_builder.h ) s.files += %w( src/core/lib/security/context/security_context.cc ) s.files += %w( src/core/lib/security/context/security_context.h ) s.files += %w( src/core/lib/security/credentials/alts/alts_credentials.cc ) @@ -1213,7 +1257,6 @@ Gem::Specification.new do |s| s.files += %w( third_party/abseil-cpp/absl/base/const_init.h ) s.files += %w( third_party/abseil-cpp/absl/base/dynamic_annotations.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/atomic_hook.h ) - s.files += %w( third_party/abseil-cpp/absl/base/internal/bits.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.cc ) s.files += %w( third_party/abseil-cpp/absl/base/internal/cycleclock.h ) s.files += %w( third_party/abseil-cpp/absl/base/internal/direct_mmap.h ) @@ -1262,7 +1305,6 @@ Gem::Specification.new do |s| s.files += %w( third_party/abseil-cpp/absl/base/thread_annotations.h ) s.files += %w( third_party/abseil-cpp/absl/container/fixed_array.h ) s.files += %w( third_party/abseil-cpp/absl/container/flat_hash_map.h ) - s.files += %w( third_party/abseil-cpp/absl/container/flat_hash_set.h ) s.files += %w( third_party/abseil-cpp/absl/container/inlined_vector.h ) s.files += %w( third_party/abseil-cpp/absl/container/internal/common.h ) s.files += %w( third_party/abseil-cpp/absl/container/internal/compressed_tuple.h ) @@ -1313,12 +1355,17 @@ Gem::Specification.new do |s| s.files += %w( third_party/abseil-cpp/absl/hash/internal/city.h ) s.files += %w( third_party/abseil-cpp/absl/hash/internal/hash.cc ) s.files += %w( third_party/abseil-cpp/absl/hash/internal/hash.h ) + s.files += %w( third_party/abseil-cpp/absl/hash/internal/wyhash.cc ) + s.files += %w( third_party/abseil-cpp/absl/hash/internal/wyhash.h ) s.files += %w( third_party/abseil-cpp/absl/memory/memory.h ) s.files += %w( third_party/abseil-cpp/absl/meta/type_traits.h ) + s.files += %w( third_party/abseil-cpp/absl/numeric/bits.h ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128.cc ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128.h ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc ) s.files += %w( third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc ) + s.files += %w( third_party/abseil-cpp/absl/numeric/internal/bits.h ) + s.files += %w( third_party/abseil-cpp/absl/numeric/internal/representation.h ) s.files += %w( third_party/abseil-cpp/absl/status/internal/status_internal.h ) s.files += %w( third_party/abseil-cpp/absl/status/internal/statusor_internal.h ) s.files += %w( third_party/abseil-cpp/absl/status/status.cc ) @@ -1340,7 +1387,12 @@ Gem::Specification.new do |s| s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/charconv_parse.h ) + s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_internal.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_internal.h ) + s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h ) + s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc ) + s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.h ) + s.files += %w( third_party/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/escaping.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/memutil.cc ) @@ -1364,6 +1416,7 @@ Gem::Specification.new do |s| s.files += %w( third_party/abseil-cpp/absl/strings/internal/str_format/parser.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/str_join_internal.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/str_split_internal.h ) + s.files += %w( third_party/abseil-cpp/absl/strings/internal/string_constant.h ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/utf8.cc ) s.files += %w( third_party/abseil-cpp/absl/strings/internal/utf8.h ) s.files += %w( third_party/abseil-cpp/absl/strings/match.cc ) @@ -1389,10 +1442,10 @@ Gem::Specification.new do |s| s.files += %w( third_party/abseil-cpp/absl/synchronization/blocking_counter.h ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.h ) + s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/futex.h ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/graphcycles.h ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h ) - s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h ) s.files += %w( third_party/abseil-cpp/absl/synchronization/internal/waiter.cc ) @@ -1629,9 +1682,9 @@ Gem::Specification.new do |s| s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ec/wnaf.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdh/ecdh.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/ecdsa.c ) + s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/ecdsa/internal.h ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/hmac/hmac.c ) - s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/md4/md4.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/md5/internal.h ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/md5/md5.c ) @@ -1655,6 +1708,7 @@ Gem::Specification.new do |s| s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/padding.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/rsa/rsa_impl.c ) + s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/self_check/fips.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/self_check/self_check.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/internal.h ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/fipsmodule/sha/sha1-altivec.c ) @@ -1741,7 +1795,6 @@ Gem::Specification.new do |s| s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/x509_lu.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c ) - s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/x509_r2x.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c ) s.files += %w( third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c ) @@ -1838,6 +1891,7 @@ Gem::Specification.new do |s| s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/engine.h ) s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/err.h ) s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/evp.h ) + s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/evp_errors.h ) s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/ex_data.h ) s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/hkdf.h ) s.files += %w( third_party/boringssl-with-bazel/src/include/openssl/hmac.h ) @@ -1886,6 +1940,7 @@ Gem::Specification.new do |s| s.files += %w( third_party/boringssl-with-bazel/src/ssl/d1_srtp.cc ) s.files += %w( third_party/boringssl-with-bazel/src/ssl/dtls_method.cc ) s.files += %w( third_party/boringssl-with-bazel/src/ssl/dtls_record.cc ) + s.files += %w( third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc ) s.files += %w( third_party/boringssl-with-bazel/src/ssl/handoff.cc ) s.files += %w( third_party/boringssl-with-bazel/src/ssl/handshake.cc ) s.files += %w( third_party/boringssl-with-bazel/src/ssl/handshake_client.cc ) @@ -2057,10 +2112,6 @@ Gem::Specification.new do |s| s.files += %w( third_party/upb/upb/def.hpp ) s.files += %w( third_party/upb/upb/encode.c ) s.files += %w( third_party/upb/upb/encode.h ) - s.files += %w( third_party/upb/upb/json_decode.c ) - s.files += %w( third_party/upb/upb/json_decode.h ) - s.files += %w( third_party/upb/upb/json_encode.c ) - s.files += %w( third_party/upb/upb/json_encode.h ) s.files += %w( third_party/upb/upb/msg.c ) s.files += %w( third_party/upb/upb/msg.h ) s.files += %w( third_party/upb/upb/port_def.inc ) @@ -2075,6 +2126,7 @@ Gem::Specification.new do |s| s.files += %w( third_party/upb/upb/upb.h ) s.files += %w( third_party/upb/upb/upb.hpp ) s.files += %w( third_party/upb/upb/upb.int.h ) + s.files += %w( third_party/xxhash/xxhash.h ) s.files += %w( third_party/zlib/adler32.c ) s.files += %w( third_party/zlib/compress.c ) s.files += %w( third_party/zlib/crc32.c ) diff --git a/grpc.gyp b/grpc.gyp index 70a6e72ff21..2418290d261 100644 --- a/grpc.gyp +++ b/grpc.gyp @@ -60,6 +60,7 @@ '-Ithird_party/upb', '-Isrc/core/ext/upb-generated', '-Isrc/core/ext/upbdefs-generated', + '-Ithird_party/xxhash', ], 'ldflags': [ '-g', @@ -139,6 +140,7 @@ '-Ithird_party/upb', '-Isrc/core/ext/upb-generated', '-Isrc/core/ext/upbdefs-generated', + '-Ithird_party/xxhash', ], 'OTHER_CPLUSPLUSFLAGS': [ '-g', @@ -150,6 +152,7 @@ '-Ithird_party/upb', '-Isrc/core/ext/upb-generated', '-Isrc/core/ext/upbdefs-generated', + '-Ithird_party/xxhash', '-stdlib=libc++', '-std=c++11', '-Wno-error=deprecated-declarations', @@ -175,10 +178,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc_test_util', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'test/core/end2end/cq_verifier.cc', @@ -239,10 +238,12 @@ 'test/core/end2end/tests/request_with_payload.cc', 'test/core/end2end/tests/resource_quota_server.cc', 'test/core/end2end/tests/retry.cc', + 'test/core/end2end/tests/retry_cancel_during_delay.cc', 'test/core/end2end/tests/retry_cancellation.cc', 'test/core/end2end/tests/retry_disabled.cc', 'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc', 'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc', + 'test/core/end2end/tests/retry_lb_drop.cc', 'test/core/end2end/tests/retry_non_retriable_status.cc', 'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc', 'test/core/end2end/tests/retry_recv_initial_metadata.cc', @@ -270,6 +271,7 @@ 'test/core/end2end/tests/workaround_cronet_compression.cc', 'test/core/end2end/tests/write_buffering.cc', 'test/core/end2end/tests/write_buffering_at_end.cc', + 'test/core/util/test_lb_policies.cc', ], }, { @@ -277,10 +279,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc_test_util', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'test/core/end2end/cq_verifier.cc', @@ -342,10 +340,12 @@ 'test/core/end2end/tests/request_with_payload.cc', 'test/core/end2end/tests/resource_quota_server.cc', 'test/core/end2end/tests/retry.cc', + 'test/core/end2end/tests/retry_cancel_during_delay.cc', 'test/core/end2end/tests/retry_cancellation.cc', 'test/core/end2end/tests/retry_disabled.cc', 'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc', 'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc', + 'test/core/end2end/tests/retry_lb_drop.cc', 'test/core/end2end/tests/retry_non_retriable_status.cc', 'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc', 'test/core/end2end/tests/retry_recv_initial_metadata.cc', @@ -373,22 +373,35 @@ 'test/core/end2end/tests/workaround_cronet_compression.cc', 'test/core/end2end/tests/write_buffering.cc', 'test/core/end2end/tests/write_buffering_at_end.cc', + 'test/core/util/test_lb_policies.cc', ], }, { 'target_name': 'gpr', 'type': 'static_library', 'dependencies': [ - 'absl/types:optional', - 'absl/time:time', - 'absl/synchronization:synchronization', - 'absl/strings:strings', - 'absl/strings:str_format', - 'absl/status:status', - 'absl/memory:memory', 'absl/base:base', + 'absl/memory:memory', + 'absl/status:status', + 'absl/strings:str_format', + 'absl/strings:strings', + 'absl/synchronization:synchronization', + 'absl/time:time', + 'absl/types:optional', + 'upb', ], 'sources': [ + 'src/core/ext/upb-generated/google/api/annotations.upb.c', + 'src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c', + 'src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c', + 'src/core/ext/upb-generated/google/api/http.upb.c', + 'src/core/ext/upb-generated/google/protobuf/any.upb.c', + 'src/core/ext/upb-generated/google/protobuf/duration.upb.c', + 'src/core/ext/upb-generated/google/protobuf/empty.upb.c', + 'src/core/ext/upb-generated/google/protobuf/struct.upb.c', + 'src/core/ext/upb-generated/google/protobuf/timestamp.upb.c', + 'src/core/ext/upb-generated/google/protobuf/wrappers.upb.c', + 'src/core/ext/upb-generated/google/rpc/status.upb.c', 'src/core/lib/gpr/alloc.cc', 'src/core/lib/gpr/atm.cc', 'src/core/lib/gpr/cpu_iphone.cc', @@ -429,6 +442,7 @@ 'src/core/lib/gprpp/mpscq.cc', 'src/core/lib/gprpp/stat_posix.cc', 'src/core/lib/gprpp/stat_windows.cc', + 'src/core/lib/gprpp/status_helper.cc', 'src/core/lib/gprpp/thd_posix.cc', 'src/core/lib/gprpp/thd_windows.cc', 'src/core/lib/gprpp/time_util.cc', @@ -440,17 +454,12 @@ 'target_name': 'grpc', 'type': 'static_library', 'dependencies': [ + 'absl/container:flat_hash_map', + 'absl/container:inlined_vector', + 'absl/functional:bind_front', + 'absl/status:statusor', 'gpr', 'address_sorting', - 'upb', - 'absl/types:optional', - 'absl/strings:strings', - 'absl/status:statusor', - 'absl/status:status', - 'absl/functional:bind_front', - 'absl/container:inlined_vector', - 'absl/container:flat_hash_set', - 'absl/container:flat_hash_map', ], 'sources': [ 'src/core/ext/filters/census/grpc_context.cc', @@ -478,6 +487,7 @@ 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc', 'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc', 'src/core/ext/filters/client_channel/lb_policy/priority/priority.cc', + 'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc', 'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc', 'src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc', 'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc', @@ -504,6 +514,8 @@ 'src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc', 'src/core/ext/filters/client_channel/resolver_registry.cc', 'src/core/ext/filters/client_channel/resolver_result_parsing.cc', + 'src/core/ext/filters/client_channel/retry_filter.cc', + 'src/core/ext/filters/client_channel/retry_service_config.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/service_config.cc', @@ -513,6 +525,8 @@ 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_idle/client_idle_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_filter.cc', + 'src/core/ext/filters/fault_injection/service_config_parser.cc', 'src/core/ext/filters/http/client/http_client_filter.cc', 'src/core/ext/filters/http/client_authority_filter.cc', 'src/core/ext/filters/http/http_filters_plugin.cc', @@ -558,9 +572,11 @@ 'src/core/ext/transport/chttp2/transport/writing.cc', 'src/core/ext/transport/inproc/inproc_plugin.cc', 'src/core/ext/transport/inproc/inproc_transport.cc', + 'src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c', 'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c', 'src/core/ext/upb-generated/envoy/annotations/resource.upb.c', 'src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c', + 'src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c', 'src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c', 'src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c', 'src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c', @@ -585,12 +601,16 @@ 'src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c', 'src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c', 'src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c', + 'src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c', + 'src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c', 'src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c', 'src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c', 'src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c', 'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c', 'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c', 'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c', @@ -605,11 +625,14 @@ 'src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c', 'src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c', 'src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c', + 'src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c', 'src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c', 'src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c', @@ -617,17 +640,6 @@ 'src/core/ext/upb-generated/envoy/type/v3/percent.upb.c', 'src/core/ext/upb-generated/envoy/type/v3/range.upb.c', 'src/core/ext/upb-generated/envoy/type/v3/semantic_version.upb.c', - 'src/core/ext/upb-generated/google/api/annotations.upb.c', - 'src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c', - 'src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c', - 'src/core/ext/upb-generated/google/api/http.upb.c', - 'src/core/ext/upb-generated/google/protobuf/any.upb.c', - 'src/core/ext/upb-generated/google/protobuf/duration.upb.c', - 'src/core/ext/upb-generated/google/protobuf/empty.upb.c', - 'src/core/ext/upb-generated/google/protobuf/struct.upb.c', - 'src/core/ext/upb-generated/google/protobuf/timestamp.upb.c', - 'src/core/ext/upb-generated/google/protobuf/wrappers.upb.c', - 'src/core/ext/upb-generated/google/rpc/status.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/gcp/altscontext.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/gcp/handshaker.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/gcp/transport_security_common.upb.c', @@ -647,9 +659,11 @@ 'src/core/ext/upb-generated/xds/core/v3/resource.upb.c', 'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c', 'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c', + 'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c', @@ -674,11 +688,15 @@ 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c', @@ -693,11 +711,14 @@ 'src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c', @@ -735,8 +756,11 @@ 'src/core/ext/xds/xds_certificate_provider.cc', 'src/core/ext/xds/xds_client.cc', 'src/core/ext/xds/xds_client_stats.cc', + 'src/core/ext/xds/xds_http_fault_filter.cc', 'src/core/ext/xds/xds_http_filters.cc', 'src/core/ext/xds/xds_server_config_fetcher.cc', + 'src/core/lib/address_utils/parse_address.cc', + 'src/core/lib/address_utils/sockaddr_utils.cc', 'src/core/lib/avl/avl.cc', 'src/core/lib/backoff/backoff.cc', 'src/core/lib/channel/channel_args.cc', @@ -759,6 +783,8 @@ 'src/core/lib/debug/stats.cc', 'src/core/lib/debug/stats_data.cc', 'src/core/lib/debug/trace.cc', + 'src/core/lib/event_engine/slice_allocator.cc', + 'src/core/lib/event_engine/sockaddr.cc', 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/httpcli_security_connector.cc', @@ -804,8 +830,6 @@ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/parse_address.cc', - 'src/core/lib/iomgr/poller/eventmanager_libuv.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -819,7 +843,6 @@ 'src/core/lib/iomgr/resolve_address_posix.cc', 'src/core/lib/iomgr/resolve_address_windows.cc', 'src/core/lib/iomgr/resource_quota.cc', - 'src/core/lib/iomgr/sockaddr_utils.cc', 'src/core/lib/iomgr/socket_factory_posix.cc', 'src/core/lib/iomgr/socket_mutator.cc', 'src/core/lib/iomgr/socket_utils_common_posix.cc', @@ -862,9 +885,7 @@ 'src/core/lib/json/json_reader.cc', 'src/core/lib/json/json_util.cc', 'src/core/lib/json/json_writer.cc', - 'src/core/lib/security/authorization/authorization_engine.cc', - 'src/core/lib/security/authorization/evaluate_args.cc', - 'src/core/lib/security/authorization/matchers.cc', + 'src/core/lib/matchers/matchers.cc', 'src/core/lib/security/context/security_context.cc', 'src/core/lib/security/credentials/alts/alts_credentials.cc', 'src/core/lib/security/credentials/alts/check_gcp_environment.cc', @@ -993,9 +1014,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'src/csharp/ext/grpc_csharp_ext.c', @@ -1005,17 +1023,13 @@ 'target_name': 'grpc_test_util', 'type': 'static_library', 'dependencies': [ - 'grpc', - 'gpr', - 'address_sorting', - 'upb', - 'absl/debugging:symbolize', - 'absl/debugging:stacktrace', 'absl/debugging:failure_signal_handler', + 'absl/debugging:stacktrace', + 'absl/debugging:symbolize', + 'grpc', ], 'sources': [ 'test/core/util/cmdline.cc', - 'test/core/util/eval_args_mock_endpoint.cc', 'test/core/util/fuzzer_util.cc', 'test/core/util/grpc_profiler.cc', 'test/core/util/histogram.cc', @@ -1043,17 +1057,13 @@ 'target_name': 'grpc_test_util_unsecure', 'type': 'static_library', 'dependencies': [ - 'grpc_unsecure', - 'gpr', - 'address_sorting', - 'upb', - 'absl/debugging:symbolize', - 'absl/debugging:stacktrace', 'absl/debugging:failure_signal_handler', + 'absl/debugging:stacktrace', + 'absl/debugging:symbolize', + 'grpc_unsecure', ], 'sources': [ 'test/core/util/cmdline.cc', - 'test/core/util/eval_args_mock_endpoint.cc', 'test/core/util/fuzzer_util.cc', 'test/core/util/grpc_profiler.cc', 'test/core/util/histogram.cc', @@ -1080,15 +1090,11 @@ 'target_name': 'grpc_unsecure', 'type': 'static_library', 'dependencies': [ + 'absl/container:flat_hash_map', + 'absl/container:inlined_vector', + 'absl/status:statusor', 'gpr', 'address_sorting', - 'upb', - 'absl/types:optional', - 'absl/strings:strings', - 'absl/status:statusor', - 'absl/status:status', - 'absl/container:inlined_vector', - 'absl/container:flat_hash_map', ], 'sources': [ 'src/core/ext/filters/census/grpc_context.cc', @@ -1136,6 +1142,8 @@ 'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc', 'src/core/ext/filters/client_channel/resolver_registry.cc', 'src/core/ext/filters/client_channel/resolver_result_parsing.cc', + 'src/core/ext/filters/client_channel/retry_filter.cc', + 'src/core/ext/filters/client_channel/retry_service_config.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/service_config.cc', @@ -1145,6 +1153,8 @@ 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_idle/client_idle_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_filter.cc', + 'src/core/ext/filters/fault_injection/service_config_parser.cc', 'src/core/ext/filters/http/client/http_client_filter.cc', 'src/core/ext/filters/http/client_authority_filter.cc', 'src/core/ext/filters/http/http_filters_plugin.cc', @@ -1188,21 +1198,12 @@ 'src/core/ext/transport/chttp2/transport/writing.cc', 'src/core/ext/transport/inproc/inproc_plugin.cc', 'src/core/ext/transport/inproc/inproc_transport.cc', - 'src/core/ext/upb-generated/google/api/annotations.upb.c', - 'src/core/ext/upb-generated/google/api/expr/v1alpha1/checked.upb.c', - 'src/core/ext/upb-generated/google/api/expr/v1alpha1/syntax.upb.c', - 'src/core/ext/upb-generated/google/api/http.upb.c', - 'src/core/ext/upb-generated/google/protobuf/any.upb.c', - 'src/core/ext/upb-generated/google/protobuf/duration.upb.c', - 'src/core/ext/upb-generated/google/protobuf/empty.upb.c', - 'src/core/ext/upb-generated/google/protobuf/struct.upb.c', - 'src/core/ext/upb-generated/google/protobuf/timestamp.upb.c', - 'src/core/ext/upb-generated/google/protobuf/wrappers.upb.c', - 'src/core/ext/upb-generated/google/rpc/status.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/health/v1/health.upb.c', 'src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c', 'src/core/ext/upb-generated/udpa/data/orca/v1/orca_load_report.upb.c', 'src/core/ext/upb-generated/validate/validate.upb.c', + 'src/core/lib/address_utils/parse_address.cc', + 'src/core/lib/address_utils/sockaddr_utils.cc', 'src/core/lib/avl/avl.cc', 'src/core/lib/backoff/backoff.cc', 'src/core/lib/channel/channel_args.cc', @@ -1225,6 +1226,8 @@ 'src/core/lib/debug/stats.cc', 'src/core/lib/debug/stats_data.cc', 'src/core/lib/debug/trace.cc', + 'src/core/lib/event_engine/slice_allocator.cc', + 'src/core/lib/event_engine/sockaddr.cc', 'src/core/lib/http/format_request.cc', 'src/core/lib/http/httpcli.cc', 'src/core/lib/http/parser.cc', @@ -1269,8 +1272,6 @@ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/parse_address.cc', - 'src/core/lib/iomgr/poller/eventmanager_libuv.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -1284,7 +1285,6 @@ 'src/core/lib/iomgr/resolve_address_posix.cc', 'src/core/lib/iomgr/resolve_address_windows.cc', 'src/core/lib/iomgr/resource_quota.cc', - 'src/core/lib/iomgr/sockaddr_utils.cc', 'src/core/lib/iomgr/socket_factory_posix.cc', 'src/core/lib/iomgr/socket_mutator.cc', 'src/core/lib/iomgr/socket_utils_common_posix.cc', @@ -1375,14 +1375,10 @@ 'target_name': 'benchmark_helpers', 'type': 'static_library', 'dependencies': [ - 'grpc_test_util_unsecure', + 'benchmark', 'grpc++_unsecure', - 'grpc_unsecure', + 'grpc_test_util_unsecure', 'grpc++_test_config', - 'gpr', - 'address_sorting', - 'upb', - 'benchmark', ], 'sources': [ 'src/proto/grpc/testing/echo.proto', @@ -1396,10 +1392,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc', - 'gpr', - 'address_sorting', - 'upb', - 'absl/synchronization:synchronization', ], 'sources': [ 'src/cpp/client/channel_cc.cc', @@ -1459,10 +1451,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc++', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'src/cpp/common/alts_context.cc', @@ -1474,10 +1462,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc++', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'src/cpp/util/error_details.cc', @@ -1488,10 +1472,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc++', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'src/proto/grpc/reflection/v1alpha/reflection.proto', @@ -1504,10 +1484,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc++', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'src/cpp/client/channel_test_peer.cc', @@ -1517,8 +1493,8 @@ 'target_name': 'grpc++_test_config', 'type': 'static_library', 'dependencies': [ - 'gpr', 'absl/flags:parse', + 'gpr', ], 'sources': [ 'test/cpp/util/test_config_cc.cc', @@ -1528,13 +1504,9 @@ 'target_name': 'grpc++_test_util', 'type': 'static_library', 'dependencies': [ - 'grpc_test_util', - 'grpc++', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', 'absl/flags:flag', + 'grpc++', + 'grpc_test_util', ], 'sources': [ 'test/core/end2end/data/client_certs.cc', @@ -1553,10 +1525,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc_unsecure', - 'gpr', - 'address_sorting', - 'upb', - 'absl/synchronization:synchronization', ], 'sources': [ 'src/cpp/client/channel_cc.cc', @@ -1621,10 +1589,6 @@ 'type': 'static_library', 'dependencies': [ 'grpc++', - 'grpc', - 'gpr', - 'address_sorting', - 'upb', ], 'sources': [ 'src/proto/grpc/channelz/channelz.proto', @@ -1745,7 +1709,6 @@ 'third_party/boringssl-with-bazel/src/crypto/ex_data.c', 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c', 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c', - 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c', 'third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c', 'third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c', 'third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c', @@ -1812,7 +1775,6 @@ 'third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_lu.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c', - 'third_party/boringssl-with-bazel/src/crypto/x509/x509_r2x.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c', @@ -1877,6 +1839,7 @@ 'third_party/boringssl-with-bazel/src/ssl/d1_srtp.cc', 'third_party/boringssl-with-bazel/src/ssl/dtls_method.cc', 'third_party/boringssl-with-bazel/src/ssl/dtls_record.cc', + 'third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc', 'third_party/boringssl-with-bazel/src/ssl/handoff.cc', 'third_party/boringssl-with-bazel/src/ssl/handshake.cc', 'third_party/boringssl-with-bazel/src/ssl/handshake_client.cc', @@ -1988,8 +1951,6 @@ 'third_party/upb/upb/decode.c', 'third_party/upb/upb/def.c', 'third_party/upb/upb/encode.c', - 'third_party/upb/upb/json_decode.c', - 'third_party/upb/upb/json_encode.c', 'third_party/upb/upb/msg.c', 'third_party/upb/upb/reflection.c', 'third_party/upb/upb/table.c', diff --git a/include/grpc/event_engine/README.md b/include/grpc/event_engine/README.md new file mode 100644 index 00000000000..b2d4fef83b3 --- /dev/null +++ b/include/grpc/event_engine/README.md @@ -0,0 +1,38 @@ +# gRPC EventEngine + +An EventEngine handles all cross-platform I/O, task execution, and DNS +resolution for gRPC. A default, cross-platform implementation is provided with +gRPC, but part of the intent here is to provide an interface for external +integrators to bring their own functionality. This allows for integration with +external event loops, siloing I/O and task execution between channels or +servers, and other custom integrations that were previously unsupported. + +*WARNING*: This is experimental code and is subject to change. + +## High level expectations of an EventEngine implementation + +### Provide their own I/O threads +EventEngines are expected to internally create whatever threads are required to +perform I/O and execute callbacks. For example, an EventEngine implementation +may want to spawn separate thread pools for polling and callback execution. + +### Provisioning data buffers via Slice allocation +At a high level, gRPC provides a `ResourceQuota` system that allows gRPC to +reclaim memory and degrade gracefully when memory reaches application-defined +thresholds. To enable this feature, the memory allocation of read/write buffers +within an EventEngine must be acquired in the form of Slices from +SliceAllocators. This is covered more fully in the gRFC and code. + +### Documentating expectations around callback execution +Some callbacks may be expensive to run. EventEngines should decide on and +document whether callback execution might block polling operations. This way, +application developers can plan accordingly (e.g., run their expensive callbacks +on a separate thread if necessary). + +### Handling concurrent usage +Assume that gRPC may use an EventEngine concurrently across multiple threads. + +## TODO: documentation + +* Example usage +* Link to gRFC diff --git a/include/grpc/event_engine/channel_args.h b/include/grpc/event_engine/channel_args.h new file mode 100644 index 00000000000..d809b1fb9f5 --- /dev/null +++ b/include/grpc/event_engine/channel_args.h @@ -0,0 +1,28 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_EVENT_ENGINE_CHANNEL_ARGS_H +#define GRPC_EVENT_ENGINE_CHANNEL_ARGS_H + +#include + +namespace grpc_event_engine { +namespace experimental { + +// TODO(hork): define +class ChannelArgs; + +} // namespace experimental +} // namespace grpc_event_engine + +#endif // GRPC_EVENT_ENGINE_CHANNEL_ARGS_H diff --git a/include/grpc/event_engine/event_engine.h b/include/grpc/event_engine/event_engine.h new file mode 100644 index 00000000000..c2d0c404903 --- /dev/null +++ b/include/grpc/event_engine/event_engine.h @@ -0,0 +1,280 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_EVENT_ENGINE_EVENT_ENGINE_H +#define GRPC_EVENT_ENGINE_EVENT_ENGINE_H + +#include + +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/time/time.h" + +#include "grpc/event_engine/channel_args.h" +#include "grpc/event_engine/port.h" +#include "grpc/event_engine/slice_allocator.h" + +// TODO(hork): explicitly define lifetimes and ownership of all objects. +// TODO(hork): Define the Endpoint::Write metrics collection system + +namespace grpc_event_engine { +namespace experimental { + +//////////////////////////////////////////////////////////////////////////////// +/// The EventEngine encapsulates all platform-specific behaviors related to low +/// level network I/O, timers, asynchronous execution, and DNS resolution. +/// +/// This interface allows developers to provide their own event management and +/// network stacks. Motivating uses cases for supporting custom EventEngines +/// include the ability to hook into external event loops, and using different +/// EventEngine instances for each channel to better insulate network I/O and +/// callback processing from other channels. +/// +/// A default cross-platform EventEngine instance is provided by gRPC. +/// +/// LIFESPAN AND OWNERSHIP +/// +/// gRPC takes shared ownership of EventEngines via std::shared_ptrs to ensure +/// that the engines remain available until they are no longer needed. Depending +/// on the use case, engines may live until gRPC is shut down. +/// +/// EXAMPLE USAGE (Not yet implemented) +/// +/// Custom EventEngines can be specified per channel, and allow configuration +/// for both clients and servers. To set a custom EventEngine for a client +/// channel, you can do something like the following: +/// +/// ChannelArguments args; +/// std::shared_ptr engine = std::make_shared(...); +/// args.SetEventEngine(engine); +/// MyAppClient client(grpc::CreateCustomChannel( +/// "localhost:50051", grpc::InsecureChannelCredentials(), args)); +/// +/// A gRPC server can use a custom EventEngine by calling the +/// ServerBuilder::SetEventEngine method: +/// +/// ServerBuilder builder; +/// std::shared_ptr engine = std::make_shared(...); +/// builder.SetEventEngine(engine); +/// std::unique_ptr server(builder.BuildAndStart()); +/// server->Wait(); +/// +//////////////////////////////////////////////////////////////////////////////// +class EventEngine { + public: + /// A basic callable function. The first argument to all callbacks is an + /// absl::Status indicating the status of the operation associated with this + /// callback. Each EventEngine method that takes a callback parameter, defines + /// the expected sets and meanings of statuses for that use case. + using Callback = std::function; + struct TaskHandle { + intptr_t key; + }; + /// A thin wrapper around a platform-specific sockaddr type. A sockaddr struct + /// exists on all platforms that gRPC supports. + /// + /// Platforms are expected to provide definitions for: + /// * sockaddr + /// * sockaddr_in + /// * sockaddr_in6 + class ResolvedAddress { + public: + static constexpr socklen_t MAX_SIZE_BYTES = 128; + + ResolvedAddress(const sockaddr* address, socklen_t size); + const struct sockaddr* address() const; + socklen_t size() const; + + private: + char address_[MAX_SIZE_BYTES]; + socklen_t size_; + }; + + /// An Endpoint represents one end of a connection between a gRPC client and + /// server. Endpoints are created when connections are established, and + /// Endpoint operations are gRPC's primary means of communication. + /// + /// Endpoints must use the provided SliceAllocator for all data buffer memory + /// allocations. gRPC allows applications to set memory constraints per + /// Channel or Server, and the implementation depends on all dynamic memory + /// allocation being handled by the quota system. + class Endpoint { + public: + virtual ~Endpoint() = 0; + + // TODO(hork): define status codes for the callback + /// Read data from the Endpoint. + /// + /// When data is available on the connection, that data is moved into the + /// \a buffer, and the \a on_read callback is called. The caller must ensure + /// that the callback has access to the buffer when executed later. + /// Ownership of the buffer is not transferred. Valid slices *may* be placed + /// into the buffer even if the callback is invoked with Status != OK. + virtual void Read(Callback on_read, SliceBuffer* buffer, + absl::Time deadline) = 0; + // TODO(hork): define status codes for the callback + /// Write data out on the connection. + /// + /// \a on_writable is called when the connection is ready for more data. The + /// Slices within the \a data buffer may be mutated at will by the Endpoint + /// until \a on_writable is called. The \a data SliceBuffer will remain + /// valid after calling \a Write, but its state is otherwise undefined. + virtual void Write(Callback on_writable, SliceBuffer* data, + absl::Time deadline) = 0; + // TODO(hork): define status codes for the callback + // TODO(hork): define cleanup operations, lifetimes, responsibilities. + virtual void Close(Callback on_close) = 0; + /// These methods return an address in the format described in DNSResolver. + /// The returned values are owned by the Endpoint and are expected to remain + /// valid for the life of the Endpoint. + virtual const ResolvedAddress* GetPeerAddress() const = 0; + virtual const ResolvedAddress* GetLocalAddress() const = 0; + }; + + /// Called when a new connection is established. This callback takes ownership + /// of the Endpoint and is responsible for its destruction. + using OnConnectCallback = std::function; + + /// An EventEngine Listener listens for incoming connection requests from gRPC + /// clients and initiates request processing once connections are established. + class Listener { + public: + /// A callback handle, used to cancel a callback. Called when the listener + /// has accepted a new client connection. This callback takes ownership of + /// the Endpoint and is responsible its destruction. + using AcceptCallback = std::function; + + virtual ~Listener() = 0; + + // TODO(hork): define return status codes + /// Bind an address/port to this Listener. It is expected that multiple + /// addresses/ports can be bound to this Listener before Listener::Start has + /// been called. Returns the bound port or an error status. + virtual absl::StatusOr Bind(const ResolvedAddress& addr) = 0; + virtual absl::Status Start() = 0; + }; + + // TODO(hork): define status codes for the callback + // TODO(hork): define return status codes + // TODO(hork): document status arg meanings for on_accept and on_shutdown + /// Factory method to create a network listener. + virtual absl::StatusOr> CreateListener( + Listener::AcceptCallback on_accept, Callback on_shutdown, + const ChannelArgs& args, + SliceAllocatorFactory slice_allocator_factory) = 0; + // TODO(hork): define status codes for the callback + // TODO(hork): define return status codes + /// Creates a network connection to a remote network listener. + virtual absl::Status Connect(OnConnectCallback on_connect, + const ResolvedAddress& addr, + const ChannelArgs& args, + SliceAllocator slice_allocator, + absl::Time deadline) = 0; + + /// The DNSResolver that provides asynchronous resolution. + class DNSResolver { + public: + /// A task handle for DNS Resolution requests. + struct LookupTaskHandle { + intptr_t key; + }; + /// A DNS SRV record type. + struct SRVRecord { + std::string host; + int port = 0; + int priority = 0; + int weight = 0; + }; + /// Called with the collection of sockaddrs that were resolved from a given + /// target address. + using LookupHostnameCallback = + std::function)>; + /// Called with a collection of SRV records. + using LookupSRVCallback = + std::function)>; + /// Called with the result of a TXT record lookup + using LookupTXTCallback = std::function; + + virtual ~DNSResolver() = 0; + + // TODO(hork): define status codes for the callback + /// Asynchronously resolve an address. \a default_port may be a non-numeric + /// named service port, and will only be used if \a address does not already + /// contain a port component. + virtual LookupTaskHandle LookupHostname(LookupHostnameCallback on_resolve, + absl::string_view address, + absl::string_view default_port, + absl::Time deadline) = 0; + // TODO(hork): define status codes for the callback + virtual LookupTaskHandle LookupSRV(LookupSRVCallback on_resolve, + absl::string_view name, + absl::Time deadline) = 0; + // TODO(hork): define status codes for the callback + virtual LookupTaskHandle LookupTXT(LookupTXTCallback on_resolve, + absl::string_view name, + absl::Time deadline) = 0; + /// Cancel an asynchronous lookup operation. + virtual void TryCancelLookup(LookupTaskHandle handle) = 0; + }; + + virtual ~EventEngine() = 0; + + // TODO(hork): define return status codes + /// Retrieves an instance of a DNSResolver. + virtual absl::StatusOr> GetDNSResolver() = 0; + + /// Intended for future expansion of Task run functionality. + struct RunOptions {}; + // TODO(hork): define status codes for the callback + // TODO(hork): consider recommendation to make TaskHandle an output arg + /// Run a callback as soon as possible. + virtual TaskHandle Run(Callback fn, RunOptions opts) = 0; + // TODO(hork): define status codes for the callback + /// Synonymous with scheduling an alarm to run at time \a when. + virtual TaskHandle RunAt(absl::Time when, Callback fn, RunOptions opts) = 0; + /// Immediately tries to cancel a callback. + /// Note that this is a "best effort" cancellation. No guarantee is made that + /// the callback will be cancelled, the call could be in any stage. + /// + /// There are three scenarios in which we may cancel a scheduled function: + /// 1. We cancel the execution before it has run. + /// 2. The callback has already run. + /// 3. We can't cancel it because it is "in flight". + /// + /// In all cases, the cancellation is still considered successful, the + /// callback will be run exactly once from either cancellation or from its + /// activation. + virtual void TryCancel(TaskHandle handle) = 0; + // TODO(hork): define return status codes + // TODO(hork): Carefully evaluate shutdown requirements, determine if we need + // a callback parameter to be added to this method. + /// Immediately run all callbacks with status indicating the shutdown. Every + /// EventEngine is expected to shut down exactly once. No new callbacks/tasks + /// should be scheduled after shutdown has begun. Any registered callbacks + /// must be executed. + virtual absl::Status Shutdown() = 0; +}; + +// Lazily instantiate and return a default global EventEngine instance if no +// custom instance is provided. If a custom EventEngine is provided for every +// channel/server via ChannelArgs, this method should never be called, and the +// default instance will never be instantiated. +std::shared_ptr GetDefaultEventEngine(); + +} // namespace experimental +} // namespace grpc_event_engine + +#endif // GRPC_EVENT_ENGINE_EVENT_ENGINE_H diff --git a/include/grpc/event_engine/port.h b/include/grpc/event_engine/port.h new file mode 100644 index 00000000000..c24b8f90245 --- /dev/null +++ b/include/grpc/event_engine/port.h @@ -0,0 +1,39 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_EVENT_ENGINE_PORT_H +#define GRPC_EVENT_ENGINE_PORT_H + +#include + +// Platform-specific sockaddr includes +#ifdef GRPC_UV +#include +#elif defined(GPR_ANDROID) || defined(GPR_LINUX) || defined(GPR_APPLE) || \ + defined(GPR_FREEBSD) || defined(GPR_OPENBSD) || defined(GPR_SOLARIS) || \ + defined(GPR_AIX) || defined(GPR_NACL) || defined(GPR_FUCHSIA) || \ + defined(GRPC_POSIX_SOCKET) +#define GRPC_EVENT_ENGINE_POSIX +#include +#include +#include +#elif defined(GPR_WINDOWS) +#include +#include +// must be included after the above +#include +#else +#error UNKNOWN PLATFORM +#endif + +#endif // GRPC_EVENT_ENGINE_PORT_H diff --git a/include/grpc/event_engine/slice_allocator.h b/include/grpc/event_engine/slice_allocator.h new file mode 100644 index 00000000000..4370cd519ad --- /dev/null +++ b/include/grpc/event_engine/slice_allocator.h @@ -0,0 +1,81 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef GRPC_EVENT_ENGINE_SLICE_ALLOCATOR_H +#define GRPC_EVENT_ENGINE_SLICE_ALLOCATOR_H + +#include + +#include + +#include "absl/status/status.h" + +// forward-declaring an internal struct, not used publicly. +struct grpc_resource_quota; +struct grpc_resource_user; + +namespace grpc_event_engine { +namespace experimental { + +// TODO(nnoble): forward declared here, needs definition. +class SliceBuffer; + +class SliceAllocator { + public: + // gRPC-internal constructor + explicit SliceAllocator(grpc_resource_user* user); + // Not copyable + SliceAllocator(SliceAllocator& other) = delete; + SliceAllocator& operator=(const SliceAllocator& other) = delete; + // Moveable + SliceAllocator(SliceAllocator&& other) = default; + SliceAllocator& operator=(SliceAllocator&& other) = default; + ~SliceAllocator(); + + using AllocateCallback = + std::function; + // TODO(hork): explain what happens under resource exhaustion. + /// Requests \a size bytes from gRPC, and populates \a dest with the allocated + /// slices. Ownership of the \a SliceBuffer is not transferred. + absl::Status Allocate(size_t size, SliceBuffer* dest, + SliceAllocator::AllocateCallback cb); + + private: + grpc_resource_user* resource_user_; +}; + +class SliceAllocatorFactory { + public: + // gRPC-internal constructor + explicit SliceAllocatorFactory(grpc_resource_quota* quota); + // Not copyable + SliceAllocatorFactory(SliceAllocatorFactory& other) = delete; + SliceAllocatorFactory& operator=(const SliceAllocatorFactory& other) = delete; + // Moveable + SliceAllocatorFactory(SliceAllocatorFactory&& other) = default; + SliceAllocatorFactory& operator=(SliceAllocatorFactory&& other) = default; + ~SliceAllocatorFactory(); + + /// On Endpoint creation, call \a CreateSliceAllocator with the name of the + /// endpoint peer (a URI string, most likely). Note: \a peer_name must outlive + /// the Endpoint. + SliceAllocator CreateSliceAllocator(absl::string_view peer_name); + + private: + grpc_resource_quota* resource_quota_; +}; + +} // namespace experimental +} // namespace grpc_event_engine + +#endif // GRPC_EVENT_ENGINE_SLICE_ALLOCATOR_H diff --git a/include/grpc/grpc.h b/include/grpc/grpc.h index 09bb1061922..f4408e111f5 100644 --- a/include/grpc/grpc.h +++ b/include/grpc/grpc.h @@ -411,10 +411,20 @@ GRPCAPI void grpc_server_register_completion_queue(grpc_server* server, grpc_completion_queue* cq, void* reserved); +// There might be more methods added later, so users should take care to memset +// this to 0 before using it. +typedef struct { + void (*on_serving_status_update)(void* user_data, const char* uri, + grpc_status_code code, + const char* error_message); + void* user_data; +} grpc_server_xds_status_notifier; + typedef struct grpc_server_config_fetcher grpc_server_config_fetcher; /** EXPERIMENTAL. Creates an xDS config fetcher. */ -GRPCAPI grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create(); +GRPCAPI grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create( + grpc_server_xds_status_notifier notifier, const grpc_channel_args* args); /** EXPERIMENTAL. Destroys a config fetcher. */ GRPCAPI void grpc_server_config_fetcher_destroy( @@ -495,6 +505,10 @@ GRPCAPI void grpc_resource_quota_resize(grpc_resource_quota* resource_quota, GRPCAPI void grpc_resource_quota_set_max_threads( grpc_resource_quota* resource_quota, int new_max_threads); +/** EXPERIMENTAL. Dumps xDS configs as a serialized ClientConfig proto. + The full name of the proto is envoy.service.status.v3.ClientConfig. */ +GRPCAPI grpc_slice grpc_dump_xds_configs(); + /** Fetch a vtable for a grpc_channel_arg that points to a grpc_resource_quota */ GRPCAPI const grpc_arg_pointer_vtable* grpc_resource_quota_arg_vtable(void); diff --git a/include/grpc/grpc_security_constants.h b/include/grpc/grpc_security_constants.h index a62f76753b9..4d7f0788e7a 100644 --- a/include/grpc/grpc_security_constants.h +++ b/include/grpc/grpc_security_constants.h @@ -29,10 +29,24 @@ extern "C" { #define GRPC_X509_CN_PROPERTY_NAME "x509_common_name" #define GRPC_X509_SAN_PROPERTY_NAME "x509_subject_alternative_name" #define GRPC_X509_PEM_CERT_PROPERTY_NAME "x509_pem_cert" +// Please note that internally, we just faithfully pass whatever value we got by +// calling SSL_get_peer_cert_chain() in OpenSSL/BoringSSL. This will mean in +// OpenSSL, the following conditions might apply: +// 1. On the client side, this property returns the full certificate chain. On +// the server side, this property will return the certificate chain without the +// leaf certificate. Application can use GRPC_X509_PEM_CERT_PROPERTY_NAME to +// get the peer leaf certificate. +// 2. If the session is resumed, this property could be empty for OpenSSL (but +// not for BoringSSL). +// For more, please refer to the official OpenSSL manual: +// https://www.openssl.org/docs/man1.1.0/man3/SSL_get_peer_cert_chain.html. #define GRPC_X509_PEM_CERT_CHAIN_PROPERTY_NAME "x509_pem_cert_chain" #define GRPC_SSL_SESSION_REUSED_PROPERTY "ssl_session_reused" #define GRPC_TRANSPORT_SECURITY_LEVEL_PROPERTY_NAME "security_level" +#define GRPC_PEER_DNS_PROPERTY_NAME "peer_dns" #define GRPC_PEER_SPIFFE_ID_PROPERTY_NAME "peer_spiffe_id" +#define GRPC_PEER_EMAIL_PROPERTY_NAME "peer_email" +#define GRPC_PEER_IP_PROPERTY_NAME "peer_ip" /** Environment variable that points to the default SSL roots file. This file must be a PEM encoded file with all the roots such as the one that can be diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index d67a9e97458..9cf6d8372e5 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -353,6 +353,17 @@ typedef struct { /* Timeout in milliseconds to use for calls to the grpclb load balancer. If 0 or unset, the balancer calls will have no deadline. */ #define GRPC_ARG_GRPCLB_CALL_TIMEOUT_MS "grpc.grpclb_call_timeout_ms" +/* Specifies the xDS bootstrap config as a JSON string. + FOR TESTING PURPOSES ONLY -- DO NOT USE IN PRODUCTION. + This option allows controlling the bootstrap configuration on a + per-channel basis, which is useful in tests. However, this results + in having a separate xDS client instance per channel rather than + using the global instance, which is not the intended way to use xDS. + Currently, this will (a) add unnecessary load on the xDS server and + (b) break use of CSDS, and there may be additional side effects in + the future. */ +#define GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG \ + "grpc.TEST_ONLY_DO_NOT_USE_IN_PROD.xds_bootstrap_config" /* Timeout in milliseconds to wait for the serverlist from the grpclb load balancer before using fallback backend addresses from the resolver. If 0, enter fallback mode immediately. Default value is 10000. */ diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h index cd0310d88ca..387639bf833 100644 --- a/include/grpc/impl/codegen/port_platform.h +++ b/include/grpc/impl/codegen/port_platform.h @@ -39,6 +39,11 @@ #endif #endif // GPR_ABSEIL_SYNC +/* + * Defines GRPC_ERROR_IS_ABSEIL_STATUS to use absl::Status for grpc_error_handle + */ +// #define GRPC_ERROR_IS_ABSEIL_STATUS 1 + /* Get windows.h included everywhere (we need it) */ #if defined(_WIN64) || defined(WIN64) || defined(_WIN32) || defined(WIN32) #ifndef WIN32_LEAN_AND_MEAN diff --git a/include/grpc/module.modulemap b/include/grpc/module.modulemap index 06c1e977361..40606e5601d 100644 --- a/include/grpc/module.modulemap +++ b/include/grpc/module.modulemap @@ -2,6 +2,15 @@ framework module grpc { umbrella header "grpc.h" +header "byte_buffer.h" + header "byte_buffer_reader.h" + header "census.h" + header "compression.h" + header "fork.h" + header "grpc.h" + header "grpc_posix.h" + header "grpc_security.h" + header "grpc_security_constants.h" header "impl/codegen/atm.h" header "impl/codegen/byte_buffer.h" header "impl/codegen/byte_buffer_reader.h" @@ -19,6 +28,10 @@ framework module grpc { header "impl/codegen/sync.h" header "impl/codegen/sync_abseil.h" header "impl/codegen/sync_generic.h" + header "load_reporting.h" + header "slice.h" + header "slice_buffer.h" + header "status.h" header "support/alloc.h" header "support/atm.h" header "support/cpu.h" @@ -31,22 +44,9 @@ framework module grpc { header "support/sync_generic.h" header "support/thd_id.h" header "support/time.h" - header "byte_buffer.h" - header "byte_buffer_reader.h" - header "census.h" - header "compression.h" - header "fork.h" - header "grpc.h" - header "grpc_posix.h" - header "grpc_security.h" - header "grpc_security_constants.h" - header "load_reporting.h" - header "slice.h" - header "slice_buffer.h" - header "status.h" header "support/workaround_list.h" - textual header "impl/codegen/atm_gcc_atomic.h" +textual header "impl/codegen/atm_gcc_atomic.h" textual header "impl/codegen/atm_gcc_sync.h" textual header "impl/codegen/atm_windows.h" textual header "impl/codegen/sync_custom.h" diff --git a/include/grpcpp/alarm.h b/include/grpcpp/alarm.h index 1405590c985..6723e136c4f 100644 --- a/include/grpcpp/alarm.h +++ b/include/grpcpp/alarm.h @@ -56,6 +56,10 @@ class Alarm : private ::grpc::GrpcLibraryCodegen { /// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel), /// an event with tag \a tag will be added to \a cq. If the alarm expired, the /// event's success bit will be true, false otherwise (ie, upon cancellation). + // + // USAGE NOTE: This is frequently used to inject arbitrary tags into \a cq by + // setting an immediate deadline. Such usage allows synchronizing an external + // event with an application's \a grpc::CompletionQueue::Next loop. template void Set(::grpc::CompletionQueue* cq, const T& deadline, void* tag) { SetInternal(cq, ::grpc::TimePoint(deadline).raw_time(), tag); diff --git a/include/grpcpp/channel.h b/include/grpcpp/channel.h index 5e67c642a47..65cc46d151f 100644 --- a/include/grpcpp/channel.h +++ b/include/grpcpp/channel.h @@ -114,7 +114,7 @@ class Channel final : public ::grpc::ChannelInterface, // with this channel (if any). It is set on the first call to CallbackCQ(). // It is _not owned_ by the channel; ownership belongs with its internal // shutdown callback tag (invoked when the CQ is fully shutdown). - ::grpc::CompletionQueue* callback_cq_ = nullptr; + std::atomic callback_cq_{nullptr}; std::vector< std::unique_ptr<::grpc::experimental::ClientInterceptorFactoryInterface>> diff --git a/include/grpcpp/ext/admin_services.h b/include/grpcpp/ext/admin_services.h new file mode 100644 index 00000000000..898a87e5f0a --- /dev/null +++ b/include/grpcpp/ext/admin_services.h @@ -0,0 +1,33 @@ +// +// +// Copyright 2021 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 GRPCPP_EXT_ADMIN_SERVICES_H +#define GRPCPP_EXT_ADMIN_SERVICES_H + +#include + +namespace grpc { + +// Registers admin services to the given ServerBuilder. This function will add +// admin services based on build time dependencies, for example, it only adds +// CSDS service if xDS is enabled in this binary. +void AddAdminServices(grpc::ServerBuilder* builder); + +} // namespace grpc + +#endif // GRPCPP_EXT_ADMIN_SERVICES_H diff --git a/include/grpcpp/generic/generic_stub.h b/include/grpcpp/generic/generic_stub.h index e4576af1a4d..e9564c33e7e 100644 --- a/include/grpcpp/generic/generic_stub.h +++ b/include/grpcpp/generic/generic_stub.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -53,7 +54,8 @@ class TemplatedGenericStub final { std::unique_ptr> PrepareCall(ClientContext* context, const std::string& method, ::grpc::CompletionQueue* cq) { - return CallInternal(channel_.get(), context, method, cq, false, nullptr); + return CallInternal(channel_.get(), context, method, /*options=*/{}, cq, + false, nullptr); } /// Setup a unary call to a named method \a method using \a context, and don't @@ -67,6 +69,7 @@ class TemplatedGenericStub final { internal::ClientAsyncResponseReaderHelper::Create( channel_.get(), cq, grpc::internal::RpcMethod(method.c_str(), + /*suffix_for_stats=*/nullptr, grpc::internal::RpcMethod::NORMAL_RPC), context, request)); } @@ -80,7 +83,8 @@ class TemplatedGenericStub final { std::unique_ptr> Call( ClientContext* context, const std::string& method, ::grpc::CompletionQueue* cq, void* tag) { - return CallInternal(channel_.get(), context, method, cq, true, tag); + return CallInternal(channel_.get(), context, method, /*options=*/{}, cq, + true, tag); } #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL @@ -89,7 +93,7 @@ class TemplatedGenericStub final { void UnaryCall(ClientContext* context, const std::string& method, const RequestType* request, ResponseType* response, std::function on_completion) { - UnaryCallInternal(context, method, request, response, + UnaryCallInternal(context, method, /*options=*/{}, request, response, std::move(on_completion)); } @@ -100,7 +104,8 @@ class TemplatedGenericStub final { void PrepareUnaryCall(ClientContext* context, const std::string& method, const RequestType* request, ResponseType* response, ClientUnaryReactor* reactor) { - PrepareUnaryCallInternal(context, method, request, response, reactor); + PrepareUnaryCallInternal(context, method, /*options=*/{}, request, response, + reactor); } /// Setup a call to a named method \a method using \a context and tied to @@ -109,7 +114,7 @@ class TemplatedGenericStub final { void PrepareBidiStreamingCall( ClientContext* context, const std::string& method, ClientBidiReactor* reactor) { - PrepareBidiStreamingCallInternal(context, method, reactor); + PrepareBidiStreamingCallInternal(context, method, /*options=*/{}, reactor); } #endif @@ -123,9 +128,10 @@ class TemplatedGenericStub final { /// Setup and start a unary call to a named method \a method using /// \a context and specifying the \a request and \a response buffers. void UnaryCall(ClientContext* context, const std::string& method, - const RequestType* request, ResponseType* response, + StubOptions options, const RequestType* request, + ResponseType* response, std::function on_completion) { - stub_->UnaryCallInternal(context, method, request, response, + stub_->UnaryCallInternal(context, method, options, request, response, std::move(on_completion)); } @@ -134,19 +140,20 @@ class TemplatedGenericStub final { /// Like any other reactor-based RPC, it will not be activated until /// StartCall is invoked on its reactor. void PrepareUnaryCall(ClientContext* context, const std::string& method, - const RequestType* request, ResponseType* response, - ClientUnaryReactor* reactor) { - stub_->PrepareUnaryCallInternal(context, method, request, response, - reactor); + StubOptions options, const RequestType* request, + ResponseType* response, ClientUnaryReactor* reactor) { + stub_->PrepareUnaryCallInternal(context, method, options, request, + response, reactor); } /// Setup a call to a named method \a method using \a context and tied to /// \a reactor . Like any other bidi streaming RPC, it will not be activated /// until StartCall is invoked on its reactor. void PrepareBidiStreamingCall( - ClientContext* context, const std::string& method, + ClientContext* context, const std::string& method, StubOptions options, ClientBidiReactor* reactor) { - stub_->PrepareBidiStreamingCallInternal(context, method, reactor); + stub_->PrepareBidiStreamingCallInternal(context, method, options, + reactor); } private: @@ -162,48 +169,50 @@ class TemplatedGenericStub final { std::shared_ptr channel_; void UnaryCallInternal(ClientContext* context, const std::string& method, - const RequestType* request, ResponseType* response, + StubOptions options, const RequestType* request, + ResponseType* response, std::function on_completion) { internal::CallbackUnaryCall( channel_.get(), - grpc::internal::RpcMethod(method.c_str(), + grpc::internal::RpcMethod(method.c_str(), options.suffix_for_stats(), grpc::internal::RpcMethod::NORMAL_RPC), context, request, response, std::move(on_completion)); } void PrepareUnaryCallInternal(ClientContext* context, - const std::string& method, + const std::string& method, StubOptions options, const RequestType* request, ResponseType* response, ClientUnaryReactor* reactor) { internal::ClientCallbackUnaryFactory::Create( channel_.get(), - grpc::internal::RpcMethod(method.c_str(), + grpc::internal::RpcMethod(method.c_str(), options.suffix_for_stats(), grpc::internal::RpcMethod::NORMAL_RPC), context, request, response, reactor); } void PrepareBidiStreamingCallInternal( - ClientContext* context, const std::string& method, + ClientContext* context, const std::string& method, StubOptions options, ClientBidiReactor* reactor) { internal::ClientCallbackReaderWriterFactory:: Create(channel_.get(), grpc::internal::RpcMethod( - method.c_str(), grpc::internal::RpcMethod::BIDI_STREAMING), + method.c_str(), options.suffix_for_stats(), + grpc::internal::RpcMethod::BIDI_STREAMING), context, reactor); } std::unique_ptr> CallInternal(grpc::ChannelInterface* channel, ClientContext* context, - const std::string& method, ::grpc::CompletionQueue* cq, - bool start, void* tag) { + const std::string& method, StubOptions options, + ::grpc::CompletionQueue* cq, bool start, void* tag) { return std::unique_ptr>( internal::ClientAsyncReaderWriterFactory:: - Create( - channel, cq, - grpc::internal::RpcMethod( - method.c_str(), grpc::internal::RpcMethod::BIDI_STREAMING), - context, start, tag)); + Create(channel, cq, + grpc::internal::RpcMethod( + method.c_str(), options.suffix_for_stats(), + grpc::internal::RpcMethod::BIDI_STREAMING), + context, start, tag)); } }; diff --git a/include/grpcpp/impl/codegen/call_op_set.h b/include/grpcpp/impl/codegen/call_op_set.h index 370d51967d0..7fde1edbb92 100644 --- a/include/grpcpp/impl/codegen/call_op_set.h +++ b/include/grpcpp/impl/codegen/call_op_set.h @@ -878,6 +878,9 @@ class CallOpSet : public CallOpSetInterface, interceptor_methods_(InterceptorBatchMethodsImpl()) {} CallOpSet& operator=(const CallOpSet& other) { + if (&other == this) { + return *this; + } core_cq_tag_ = this; return_tag_ = this; call_ = other.call_; diff --git a/include/grpcpp/impl/codegen/client_callback.h b/include/grpcpp/impl/codegen/client_callback.h index f6bd6108af4..ba802909e04 100644 --- a/include/grpcpp/impl/codegen/client_callback.h +++ b/include/grpcpp/impl/codegen/client_callback.h @@ -27,6 +27,7 @@ #include #include #include +#include namespace grpc { class Channel; @@ -472,7 +473,7 @@ class ClientCallbackReaderWriterImpl // there are no tests catching the compiler warning. static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); } - void StartCall() override { + void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override { // This call initiates two batches, plus any backlog, each with a callback // 1. Send initial metadata (unless corked) + recv initial metadata // 2. Any read backlog @@ -521,7 +522,8 @@ class ClientCallbackReaderWriterImpl call_.PerformOps(&read_ops_); } - void Write(const Request* msg, ::grpc::WriteOptions options) override { + void Write(const Request* msg, ::grpc::WriteOptions options) + ABSL_LOCKS_EXCLUDED(start_mu_) override { if (options.is_last_message()) { options.set_buffer_hint(); write_ops_.ClientSendClose(); @@ -544,7 +546,7 @@ class ClientCallbackReaderWriterImpl } call_.PerformOps(&write_ops_); } - void WritesDone() override { + void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override { writes_done_ops_.ClientSendClose(); writes_done_tag_.Set( call_.call(), @@ -685,7 +687,7 @@ class ClientCallbackReaderWriterImpl bool writes_done_ops = false; bool read_ops = false; }; - StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */; + StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_); // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish std::atomic callbacks_outstanding_{3}; @@ -843,7 +845,7 @@ class ClientCallbackReaderImpl : public ClientCallbackReader { struct StartCallBacklog { bool read_ops = false; }; - StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */; + StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_); // Minimum of 2 callbacks to pre-register for start and finish std::atomic callbacks_outstanding_{2}; @@ -884,7 +886,7 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter { // there are no tests catching the compiler warning. static void operator delete(void*, void*) { GPR_CODEGEN_ASSERT(false); } - void StartCall() override { + void StartCall() ABSL_LOCKS_EXCLUDED(start_mu_) override { // This call initiates two batches, plus any backlog, each with a callback // 1. Send initial metadata (unless corked) + recv initial metadata // 2. Any backlog @@ -916,7 +918,8 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter { this->MaybeFinish(/*from_reaction=*/false); } - void Write(const Request* msg, ::grpc::WriteOptions options) override { + void Write(const Request* msg, ::grpc::WriteOptions options) + ABSL_LOCKS_EXCLUDED(start_mu_) override { if (GPR_UNLIKELY(options.is_last_message())) { options.set_buffer_hint(); write_ops_.ClientSendClose(); @@ -941,7 +944,7 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter { call_.PerformOps(&write_ops_); } - void WritesDone() override { + void WritesDone() ABSL_LOCKS_EXCLUDED(start_mu_) override { writes_done_ops_.ClientSendClose(); writes_done_tag_.Set( call_.call(), @@ -1070,7 +1073,7 @@ class ClientCallbackWriterImpl : public ClientCallbackWriter { bool write_ops = false; bool writes_done_ops = false; }; - StartCallBacklog backlog_ /* GUARDED_BY(start_mu_) */; + StartCallBacklog backlog_ ABSL_GUARDED_BY(start_mu_); // Minimum of 3 callbacks to pre-register for start ops, StartCall, and finish std::atomic callbacks_outstanding_{3}; diff --git a/include/grpcpp/impl/codegen/client_context.h b/include/grpcpp/impl/codegen/client_context.h index 708b7a47493..763a836e424 100644 --- a/include/grpcpp/impl/codegen/client_context.h +++ b/include/grpcpp/impl/codegen/client_context.h @@ -466,12 +466,13 @@ class ClientContext { const std::shared_ptr<::grpc::Channel>& channel); grpc::experimental::ClientRpcInfo* set_client_rpc_info( - const char* method, grpc::internal::RpcMethod::RpcType type, - grpc::ChannelInterface* channel, + const char* method, const char* suffix_for_stats, + grpc::internal::RpcMethod::RpcType type, grpc::ChannelInterface* channel, const std::vector>& creators, size_t interceptor_pos) { - rpc_info_ = grpc::experimental::ClientRpcInfo(this, type, method, channel); + rpc_info_ = grpc::experimental::ClientRpcInfo(this, type, method, + suffix_for_stats, channel); rpc_info_.RegisterInterceptors(creators, interceptor_pos); return &rpc_info_; } diff --git a/include/grpcpp/impl/codegen/client_interceptor.h b/include/grpcpp/impl/codegen/client_interceptor.h index 78be1f7597e..ec78074ab2a 100644 --- a/include/grpcpp/impl/codegen/client_interceptor.h +++ b/include/grpcpp/impl/codegen/client_interceptor.h @@ -87,6 +87,10 @@ class ClientRpcInfo { /// Return the fully-specified method name const char* method() const { return method_; } + /// Return an identifying suffix for the client stub, or nullptr if one wasn't + /// specified. + const char* suffix_for_stats() const { return suffix_for_stats_; } + /// Return a pointer to the channel on which the RPC is being sent ChannelInterface* channel() { return channel_; } @@ -116,10 +120,12 @@ class ClientRpcInfo { // Constructor will only be called from ClientContext ClientRpcInfo(grpc::ClientContext* ctx, internal::RpcMethod::RpcType type, - const char* method, grpc::ChannelInterface* channel) + const char* method, const char* suffix_for_stats, + grpc::ChannelInterface* channel) : ctx_(ctx), type_(static_cast(type)), method_(method), + suffix_for_stats_(suffix_for_stats), channel_(channel) {} // Move assignment should only be used by ClientContext @@ -162,6 +168,7 @@ class ClientRpcInfo { // TODO(yashykt): make type_ const once move-assignment is deleted Type type_{Type::UNKNOWN}; const char* method_ = nullptr; + const char* suffix_for_stats_ = nullptr; grpc::ChannelInterface* channel_ = nullptr; std::vector> interceptors_; bool hijacked_ = false; diff --git a/include/grpcpp/impl/codegen/interceptor_common.h b/include/grpcpp/impl/codegen/interceptor_common.h index 520d981459f..b9a6eded093 100644 --- a/include/grpcpp/impl/codegen/interceptor_common.h +++ b/include/grpcpp/impl/codegen/interceptor_common.h @@ -223,18 +223,11 @@ class InterceptorBatchMethodsImpl bool InterceptorsListEmpty() { auto* client_rpc_info = call_->client_rpc_info(); if (client_rpc_info != nullptr) { - if (client_rpc_info->interceptors_.empty()) { - return true; - } else { - return false; - } + return client_rpc_info->interceptors_.empty(); } auto* server_rpc_info = call_->server_rpc_info(); - if (server_rpc_info == nullptr || server_rpc_info->interceptors_.empty()) { - return true; - } - return false; + return server_rpc_info == nullptr || server_rpc_info->interceptors_.empty(); } // This should be used only by subclasses of CallOpSetInterface. SetCall and @@ -419,11 +412,7 @@ class CancelInterceptorBatchMethods public: bool QueryInterceptionHookPoint( experimental::InterceptionHookPoints type) override { - if (type == experimental::InterceptionHookPoints::PRE_SEND_CANCEL) { - return true; - } else { - return false; - } + return type == experimental::InterceptionHookPoints::PRE_SEND_CANCEL; } void Proceed() override { diff --git a/include/grpcpp/impl/codegen/method_handler.h b/include/grpcpp/impl/codegen/method_handler.h index 756f4aae751..fb093f54b82 100644 --- a/include/grpcpp/impl/codegen/method_handler.h +++ b/include/grpcpp/impl/codegen/method_handler.h @@ -357,9 +357,12 @@ class SplitServerStreamingHandler template <::grpc::StatusCode code> class ErrorMethodHandler : public ::grpc::internal::MethodHandler { public: + explicit ErrorMethodHandler(const std::string& message) : message_(message) {} + template - static void FillOps(::grpc::ServerContextBase* context, T* ops) { - ::grpc::Status status(code, ""); + static void FillOps(::grpc::ServerContextBase* context, + const std::string& message, T* ops) { + ::grpc::Status status(code, message); if (!context->sent_initial_metadata_) { ops->SendInitialMetadata(&context->initial_metadata_, context->initial_metadata_flags()); @@ -375,7 +378,7 @@ class ErrorMethodHandler : public ::grpc::internal::MethodHandler { ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata, ::grpc::internal::CallOpServerSendStatus> ops; - FillOps(param.server_context, &ops); + FillOps(param.server_context, message_, &ops); param.call->PerformOps(&ops); param.call->cq()->Pluck(&ops); } @@ -388,6 +391,9 @@ class ErrorMethodHandler : public ::grpc::internal::MethodHandler { } return nullptr; } + + private: + const std::string message_; }; typedef ErrorMethodHandler<::grpc::StatusCode::UNIMPLEMENTED> diff --git a/include/grpcpp/impl/codegen/rpc_method.h b/include/grpcpp/impl/codegen/rpc_method.h index 394a29b8374..388784e6ff1 100644 --- a/include/grpcpp/impl/codegen/rpc_method.h +++ b/include/grpcpp/impl/codegen/rpc_method.h @@ -36,21 +36,40 @@ class RpcMethod { }; RpcMethod(const char* name, RpcType type) - : name_(name), method_type_(type), channel_tag_(nullptr) {} + : name_(name), + suffix_for_stats_(nullptr), + method_type_(type), + channel_tag_(nullptr) {} + + RpcMethod(const char* name, const char* suffix_for_stats, RpcType type) + : name_(name), + suffix_for_stats_(suffix_for_stats), + method_type_(type), + channel_tag_(nullptr) {} RpcMethod(const char* name, RpcType type, const std::shared_ptr& channel) : name_(name), + suffix_for_stats_(nullptr), + method_type_(type), + channel_tag_(channel->RegisterMethod(name)) {} + + RpcMethod(const char* name, const char* suffix_for_stats, RpcType type, + const std::shared_ptr& channel) + : name_(name), + suffix_for_stats_(suffix_for_stats), method_type_(type), channel_tag_(channel->RegisterMethod(name)) {} const char* name() const { return name_; } + const char* suffix_for_stats() const { return suffix_for_stats_; } RpcType method_type() const { return method_type_; } void SetMethodType(RpcType type) { method_type_ = type; } void* channel_tag() const { return channel_tag_; } private: const char* const name_; + const char* const suffix_for_stats_; RpcType method_type_; void* const channel_tag_; }; diff --git a/include/grpcpp/impl/codegen/security/auth_context.h b/include/grpcpp/impl/codegen/security/auth_context.h index 4e261cad3fc..cea6dbea36f 100644 --- a/include/grpcpp/impl/codegen/security/auth_context.h +++ b/include/grpcpp/impl/codegen/security/auth_context.h @@ -42,7 +42,7 @@ class AuthPropertyIterator AuthPropertyIterator operator++(int); bool operator==(const AuthPropertyIterator& rhs) const; bool operator!=(const AuthPropertyIterator& rhs) const; - const AuthProperty operator*(); + AuthProperty operator*(); protected: AuthPropertyIterator(); diff --git a/include/grpcpp/impl/codegen/server_callback.h b/include/grpcpp/impl/codegen/server_callback.h index 532dfdd06d0..3ccabdbbfec 100644 --- a/include/grpcpp/impl/codegen/server_callback.h +++ b/include/grpcpp/impl/codegen/server_callback.h @@ -29,6 +29,7 @@ #include #include #include +#include namespace grpc { @@ -278,7 +279,7 @@ class ServerBidiReactor : public internal::ServerReactor { /// Send any initial metadata stored in the RPC context. If not invoked, /// any initial metadata will be passed along with the first Write or the /// Finish (if there are no writes). - void StartSendInitialMetadata() { + void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(stream_mu_) { ServerCallbackReaderWriter* stream = stream_.load(std::memory_order_acquire); if (stream == nullptr) { @@ -296,7 +297,7 @@ class ServerBidiReactor : public internal::ServerReactor { /// /// \param[out] req Where to eventually store the read message. Valid when /// the library calls OnReadDone - void StartRead(Request* req) { + void StartRead(Request* req) ABSL_LOCKS_EXCLUDED(stream_mu_) { ServerCallbackReaderWriter* stream = stream_.load(std::memory_order_acquire); if (stream == nullptr) { @@ -325,7 +326,8 @@ class ServerBidiReactor : public internal::ServerReactor { /// ownership but the caller must ensure that the message is /// not deleted or modified until OnWriteDone is called. /// \param[in] options The WriteOptions to use for writing this message - void StartWrite(const Response* resp, ::grpc::WriteOptions options) { + void StartWrite(const Response* resp, ::grpc::WriteOptions options) + ABSL_LOCKS_EXCLUDED(stream_mu_) { ServerCallbackReaderWriter* stream = stream_.load(std::memory_order_acquire); if (stream == nullptr) { @@ -354,7 +356,7 @@ class ServerBidiReactor : public internal::ServerReactor { /// \param[in] options The WriteOptions to use for writing this message /// \param[in] s The status outcome of this RPC void StartWriteAndFinish(const Response* resp, ::grpc::WriteOptions options, - ::grpc::Status s) { + ::grpc::Status s) ABSL_LOCKS_EXCLUDED(stream_mu_) { ServerCallbackReaderWriter* stream = stream_.load(std::memory_order_acquire); if (stream == nullptr) { @@ -389,7 +391,7 @@ class ServerBidiReactor : public internal::ServerReactor { /// cancelled. /// /// \param[in] s The status outcome of this RPC - void Finish(::grpc::Status s) { + void Finish(::grpc::Status s) ABSL_LOCKS_EXCLUDED(stream_mu_) { ServerCallbackReaderWriter* stream = stream_.load(std::memory_order_acquire); if (stream == nullptr) { @@ -481,7 +483,7 @@ class ServerBidiReactor : public internal::ServerReactor { ::grpc::WriteOptions write_options_wanted; ::grpc::Status status_wanted; }; - PreBindBacklog backlog_ /* GUARDED_BY(stream_mu_) */; + PreBindBacklog backlog_ ABSL_GUARDED_BY(stream_mu_); }; /// \a ServerReadReactor is the interface for a client-streaming RPC. @@ -492,7 +494,7 @@ class ServerReadReactor : public internal::ServerReactor { ~ServerReadReactor() override = default; /// The following operation initiations are exactly like ServerBidiReactor. - void StartSendInitialMetadata() { + void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(reader_mu_) { ServerCallbackReader* reader = reader_.load(std::memory_order_acquire); if (reader == nullptr) { @@ -505,7 +507,7 @@ class ServerReadReactor : public internal::ServerReactor { } reader->SendInitialMetadata(); } - void StartRead(Request* req) { + void StartRead(Request* req) ABSL_LOCKS_EXCLUDED(reader_mu_) { ServerCallbackReader* reader = reader_.load(std::memory_order_acquire); if (reader == nullptr) { @@ -518,7 +520,7 @@ class ServerReadReactor : public internal::ServerReactor { } reader->Read(req); } - void Finish(::grpc::Status s) { + void Finish(::grpc::Status s) ABSL_LOCKS_EXCLUDED(reader_mu_) { ServerCallbackReader* reader = reader_.load(std::memory_order_acquire); if (reader == nullptr) { @@ -544,7 +546,8 @@ class ServerReadReactor : public internal::ServerReactor { // May be overridden by internal implementation details. This is not a public // customization point. - virtual void InternalBindReader(ServerCallbackReader* reader) { + virtual void InternalBindReader(ServerCallbackReader* reader) + ABSL_LOCKS_EXCLUDED(reader_mu_) { grpc::internal::MutexLock l(&reader_mu_); if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) { @@ -568,7 +571,7 @@ class ServerReadReactor : public internal::ServerReactor { Request* read_wanted = nullptr; ::grpc::Status status_wanted; }; - PreBindBacklog backlog_ /* GUARDED_BY(reader_mu_) */; + PreBindBacklog backlog_ ABSL_GUARDED_BY(reader_mu_); }; /// \a ServerWriteReactor is the interface for a server-streaming RPC. @@ -579,7 +582,7 @@ class ServerWriteReactor : public internal::ServerReactor { ~ServerWriteReactor() override = default; /// The following operation initiations are exactly like ServerBidiReactor. - void StartSendInitialMetadata() { + void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(writer_mu_) { ServerCallbackWriter* writer = writer_.load(std::memory_order_acquire); if (writer == nullptr) { @@ -595,7 +598,8 @@ class ServerWriteReactor : public internal::ServerReactor { void StartWrite(const Response* resp) { StartWrite(resp, ::grpc::WriteOptions()); } - void StartWrite(const Response* resp, ::grpc::WriteOptions options) { + void StartWrite(const Response* resp, ::grpc::WriteOptions options) + ABSL_LOCKS_EXCLUDED(writer_mu_) { ServerCallbackWriter* writer = writer_.load(std::memory_order_acquire); if (writer == nullptr) { @@ -610,7 +614,7 @@ class ServerWriteReactor : public internal::ServerReactor { writer->Write(resp, options); } void StartWriteAndFinish(const Response* resp, ::grpc::WriteOptions options, - ::grpc::Status s) { + ::grpc::Status s) ABSL_LOCKS_EXCLUDED(writer_mu_) { ServerCallbackWriter* writer = writer_.load(std::memory_order_acquire); if (writer == nullptr) { @@ -629,7 +633,7 @@ class ServerWriteReactor : public internal::ServerReactor { void StartWriteLast(const Response* resp, ::grpc::WriteOptions options) { StartWrite(resp, options.set_last_message()); } - void Finish(::grpc::Status s) { + void Finish(::grpc::Status s) ABSL_LOCKS_EXCLUDED(writer_mu_) { ServerCallbackWriter* writer = writer_.load(std::memory_order_acquire); if (writer == nullptr) { @@ -654,7 +658,8 @@ class ServerWriteReactor : public internal::ServerReactor { friend class ServerCallbackWriter; // May be overridden by internal implementation details. This is not a public // customization point. - virtual void InternalBindWriter(ServerCallbackWriter* writer) { + virtual void InternalBindWriter(ServerCallbackWriter* writer) + ABSL_LOCKS_EXCLUDED(writer_mu_) { grpc::internal::MutexLock l(&writer_mu_); if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) { @@ -687,7 +692,7 @@ class ServerWriteReactor : public internal::ServerReactor { ::grpc::WriteOptions write_options_wanted; ::grpc::Status status_wanted; }; - PreBindBacklog backlog_ /* GUARDED_BY(writer_mu_) */; + PreBindBacklog backlog_ ABSL_GUARDED_BY(writer_mu_); }; class ServerUnaryReactor : public internal::ServerReactor { @@ -696,7 +701,7 @@ class ServerUnaryReactor : public internal::ServerReactor { ~ServerUnaryReactor() override = default; /// StartSendInitialMetadata is exactly like ServerBidiReactor. - void StartSendInitialMetadata() { + void StartSendInitialMetadata() ABSL_LOCKS_EXCLUDED(call_mu_) { ServerCallbackUnary* call = call_.load(std::memory_order_acquire); if (call == nullptr) { grpc::internal::MutexLock l(&call_mu_); @@ -711,7 +716,7 @@ class ServerUnaryReactor : public internal::ServerReactor { /// Finish is similar to ServerBidiReactor except for one detail. /// If the status is non-OK, any message will not be sent. Instead, /// the client will only receive the status and any trailing metadata. - void Finish(::grpc::Status s) { + void Finish(::grpc::Status s) ABSL_LOCKS_EXCLUDED(call_mu_) { ServerCallbackUnary* call = call_.load(std::memory_order_acquire); if (call == nullptr) { grpc::internal::MutexLock l(&call_mu_); @@ -734,7 +739,8 @@ class ServerUnaryReactor : public internal::ServerReactor { friend class ServerCallbackUnary; // May be overridden by internal implementation details. This is not a public // customization point. - virtual void InternalBindCall(ServerCallbackUnary* call) { + virtual void InternalBindCall(ServerCallbackUnary* call) + ABSL_LOCKS_EXCLUDED(call_mu_) { grpc::internal::MutexLock l(&call_mu_); if (GPR_UNLIKELY(backlog_.send_initial_metadata_wanted)) { @@ -754,7 +760,7 @@ class ServerUnaryReactor : public internal::ServerReactor { bool finish_wanted = false; ::grpc::Status status_wanted; }; - PreBindBacklog backlog_ /* GUARDED_BY(call_mu_) */; + PreBindBacklog backlog_ ABSL_GUARDED_BY(call_mu_); }; namespace internal { diff --git a/include/grpcpp/impl/codegen/string_ref.h b/include/grpcpp/impl/codegen/string_ref.h index 153f37102d8..4543e426042 100644 --- a/include/grpcpp/impl/codegen/string_ref.h +++ b/include/grpcpp/impl/codegen/string_ref.h @@ -51,6 +51,7 @@ class string_ref { string_ref() : data_(nullptr), length_(0) {} string_ref(const string_ref& other) : data_(other.data_), length_(other.length_) {} + // NOLINTNEXTLINE(bugprone-unhandled-self-assignment) string_ref& operator=(const string_ref& rhs) { data_ = rhs.data_; length_ = rhs.length_; diff --git a/include/grpcpp/impl/codegen/stub_options.h b/include/grpcpp/impl/codegen/stub_options.h index a56695a8f82..30509c250a7 100644 --- a/include/grpcpp/impl/codegen/stub_options.h +++ b/include/grpcpp/impl/codegen/stub_options.h @@ -22,7 +22,20 @@ namespace grpc { /// Useful interface for generated stubs -class StubOptions {}; +class StubOptions { + public: + StubOptions() = default; + explicit StubOptions(const char* suffix_for_stats) + : suffix_for_stats_(suffix_for_stats) {} + + void set_suffix_for_stats(const char* suffix_for_stats) { + suffix_for_stats_ = suffix_for_stats; + } + const char* suffix_for_stats() const { return suffix_for_stats_; } + + private: + const char* suffix_for_stats_ = nullptr; +}; } // namespace grpc diff --git a/include/grpcpp/server.h b/include/grpcpp/server.h index d90f28dc1ce..a69e64b462f 100644 --- a/include/grpcpp/server.h +++ b/include/grpcpp/server.h @@ -58,13 +58,13 @@ class ExternalConnectionAcceptorImpl; /// \a Server instances. class Server : public ServerInterface, private GrpcLibraryCodegen { public: - ~Server() override; + ~Server() ABSL_LOCKS_EXCLUDED(mu_) override; /// Block until the server shuts down. /// /// \warning The server must be either shutting down or some other thread must /// call \a Shutdown for this function to ever return. - void Wait() override; + void Wait() ABSL_LOCKS_EXCLUDED(mu_) override; /// Global callbacks are a set of hooks that are called when server /// events occur. \a SetGlobalCallbacks method is used to register @@ -286,13 +286,14 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { void PerformOpsOnCall(internal::CallOpSetInterface* ops, internal::Call* call) override; - void ShutdownInternal(gpr_timespec deadline) override; + void ShutdownInternal(gpr_timespec deadline) + ABSL_LOCKS_EXCLUDED(mu_) override; int max_receive_message_size() const override { return max_receive_message_size_; } - CompletionQueue* CallbackCQ() override; + CompletionQueue* CallbackCQ() ABSL_LOCKS_EXCLUDED(mu_) override; ServerInitializer* initializer(); @@ -300,8 +301,8 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // the ref count are the running state of the server (take a ref at start and // drop it at shutdown) and each running callback RPC. void Ref(); - void UnrefWithPossibleNotify() /* LOCKS_EXCLUDED(mu_) */; - void UnrefAndWaitLocked() /* EXCLUSIVE_LOCKS_REQUIRED(mu_) */; + void UnrefWithPossibleNotify() ABSL_LOCKS_EXCLUDED(mu_); + void UnrefAndWaitLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); std::vector> acceptors_; @@ -335,10 +336,11 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // Server status internal::Mutex mu_; bool started_; - bool shutdown_; - bool shutdown_notified_; // Was notify called on the shutdown_cv_ + bool shutdown_ ABSL_GUARDED_BY(mu_); + bool shutdown_notified_ + ABSL_GUARDED_BY(mu_); // Was notify called on the shutdown_cv_ internal::CondVar shutdown_done_cv_; - bool shutdown_done_ = false; + bool shutdown_done_ ABSL_GUARDED_BY(mu_) = false; std::atomic_int shutdown_refs_outstanding_{1}; internal::CondVar shutdown_cv_; @@ -378,7 +380,7 @@ class Server : public ServerInterface, private GrpcLibraryCodegen { // with this server (if any). It is set on the first call to CallbackCQ(). // It is _not owned_ by the server; ownership belongs with its internal // shutdown callback tag (invoked when the CQ is fully shutdown). - CompletionQueue* callback_cq_ /* GUARDED_BY(mu_) */ = nullptr; + std::atomic callback_cq_{nullptr}; // List of CQs passed in by user that must be Shutdown only after Server is // Shutdown. Even though this is only used with NDEBUG, instantiate it in all diff --git a/include/grpcpp/server_builder.h b/include/grpcpp/server_builder.h index 28e8cfde789..00e82a10f87 100644 --- a/include/grpcpp/server_builder.h +++ b/include/grpcpp/server_builder.h @@ -357,6 +357,9 @@ class ServerBuilder { server_config_fetcher_ = server_config_fetcher; } + /// Experimental API, subject to change. + virtual ChannelArguments BuildChannelArgs(); + private: friend class ::grpc::testing::ServerBuilderPluginTest; diff --git a/include/grpcpp/test/mock_stream.h b/include/grpcpp/test/mock_stream.h index e33595d7096..deffad3d909 100644 --- a/include/grpcpp/test/mock_stream.h +++ b/include/grpcpp/test/mock_stream.h @@ -90,6 +90,8 @@ class MockClientAsyncResponseReader public: MockClientAsyncResponseReader() = default; + /// ClientAsyncResponseReaderInterface + MOCK_METHOD0_T(StartCall, void()); MOCK_METHOD1_T(ReadInitialMetadata, void(void*)); MOCK_METHOD3_T(Finish, void(R*, Status*, void*)); }; @@ -100,6 +102,7 @@ class MockClientAsyncReader : public ClientAsyncReaderInterface { MockClientAsyncReader() = default; /// ClientAsyncStreamingInterface + MOCK_METHOD1_T(StartCall, void(void*)); MOCK_METHOD1_T(ReadInitialMetadata, void(void*)); MOCK_METHOD2_T(Finish, void(Status*, void*)); @@ -113,11 +116,13 @@ class MockClientAsyncWriter : public ::grpc::ClientAsyncWriterInterface { MockClientAsyncWriter() = default; /// ClientAsyncStreamingInterface + MOCK_METHOD1_T(StartCall, void(void*)); MOCK_METHOD1_T(ReadInitialMetadata, void(void*)); MOCK_METHOD2_T(Finish, void(Status*, void*)); /// AsyncWriterInterface MOCK_METHOD2_T(Write, void(const W&, void*)); + MOCK_METHOD3_T(Write, void(const W&, ::grpc::WriteOptions, void*)); /// ClientAsyncWriterInterface MOCK_METHOD1_T(WritesDone, void(void*)); @@ -130,11 +135,13 @@ class MockClientAsyncReaderWriter MockClientAsyncReaderWriter() = default; /// ClientAsyncStreamingInterface + MOCK_METHOD1_T(StartCall, void(void*)); MOCK_METHOD1_T(ReadInitialMetadata, void(void*)); MOCK_METHOD2_T(Finish, void(Status*, void*)); /// AsyncWriterInterface MOCK_METHOD2_T(Write, void(const W&, void*)); + MOCK_METHOD3_T(Write, void(const W&, ::grpc::WriteOptions, void*)); /// AsyncReaderInterface MOCK_METHOD2_T(Read, void(R*, void*)); diff --git a/include/grpcpp/xds_server_builder.h b/include/grpcpp/xds_server_builder.h index 1ed9e83ac3f..076c377f781 100644 --- a/include/grpcpp/xds_server_builder.h +++ b/include/grpcpp/xds_server_builder.h @@ -26,15 +26,52 @@ namespace grpc { namespace experimental { +class XdsServerServingStatusNotifierInterface { + public: + virtual ~XdsServerServingStatusNotifierInterface() = default; + + // \a uri contains the listening target associated with the notification. Note + // that a single target provided to XdsServerBuilder can get resolved to + // multiple listening addresses. + // The callback is invoked each time there is an update to the serving status. + // The API does not provide any guarantees around duplicate updates. + // Status::OK signifies that the server is serving, while a non-OK status + // signifies that the server is not serving. + virtual void OnServingStatusUpdate(std::string uri, grpc::Status status) = 0; +}; + class XdsServerBuilder : public ::grpc::ServerBuilder { public: - std::unique_ptr BuildAndStart() override { - grpc_server_config_fetcher* fetcher = - grpc_server_config_fetcher_xds_create(); - if (fetcher == nullptr) return nullptr; - set_fetcher(fetcher); - return ServerBuilder::BuildAndStart(); + // It is the responsibility of the application to make sure that \a notifier + // outlasts the life of the server. Notifications will start being made + // asynchronously once `BuildAndStart()` has been called. Note that it is + // possible for notifications to be made before `BuildAndStart()` returns. + void set_status_notifier(XdsServerServingStatusNotifierInterface* notifier) { + notifier_ = notifier; } + + private: + // Called at the beginning of BuildAndStart(). + ChannelArguments BuildChannelArgs() override { + ChannelArguments args = ServerBuilder::BuildChannelArgs(); + grpc_channel_args c_channel_args = args.c_channel_args(); + grpc_server_config_fetcher* fetcher = grpc_server_config_fetcher_xds_create( + {OnServingStatusUpdate, notifier_}, &c_channel_args); + if (fetcher != nullptr) set_fetcher(fetcher); + return args; + } + + static void OnServingStatusUpdate(void* user_data, const char* uri, + grpc_status_code code, + const char* error_message) { + if (user_data == nullptr) return; + XdsServerServingStatusNotifierInterface* notifier = + static_cast(user_data); + notifier->OnServingStatusUpdate( + uri, grpc::Status(static_cast(code), error_message)); + } + + XdsServerServingStatusNotifierInterface* notifier_ = nullptr; }; } // namespace experimental diff --git a/package.xml b/package.xml index 56873582e2f..c8c6f911a79 100644 --- a/package.xml +++ b/package.xml @@ -13,8 +13,8 @@ 2019-09-24 - 1.37.0dev - 1.37.0dev + 1.38.0dev + 1.38.0dev beta @@ -22,7 +22,7 @@ Apache 2.0 -- gRPC Core 1.37.0 update +- gRPC Core 1.38.0 update @@ -33,6 +33,10 @@ + + + + @@ -130,6 +134,8 @@ + + @@ -173,6 +179,10 @@ + + + + @@ -191,6 +201,10 @@ + + + + @@ -271,12 +285,16 @@ + + + + @@ -325,6 +343,10 @@ + + + + @@ -337,6 +359,10 @@ + + + + @@ -365,8 +391,12 @@ + + + + @@ -375,6 +405,8 @@ + + @@ -451,12 +483,16 @@ + + + + @@ -505,6 +541,10 @@ + + + + @@ -515,6 +555,10 @@ + + + + @@ -543,8 +587,12 @@ + + + + @@ -553,6 +601,8 @@ + + @@ -631,9 +681,15 @@ + + + + + + @@ -680,6 +736,8 @@ + + @@ -753,6 +811,8 @@ + + @@ -840,10 +900,6 @@ - - - - @@ -873,8 +929,6 @@ - - @@ -944,21 +998,11 @@ + + - - - - - - - - - - - - @@ -1215,7 +1259,6 @@ - @@ -1264,7 +1307,6 @@ - @@ -1315,12 +1357,17 @@ + + + + + @@ -1342,7 +1389,12 @@ + + + + + @@ -1366,6 +1418,7 @@ + @@ -1391,10 +1444,10 @@ + - @@ -1631,9 +1684,9 @@ + - @@ -1657,6 +1710,7 @@ + @@ -1743,7 +1797,6 @@ - @@ -1840,6 +1893,7 @@ + @@ -1888,6 +1942,7 @@ + @@ -1982,10 +2037,6 @@ - - - - @@ -2000,6 +2051,7 @@ + diff --git a/setup.py b/setup.py index dfdfedacdab..c93d419f320 100644 --- a/setup.py +++ b/setup.py @@ -73,6 +73,7 @@ UPB_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext', 'upb-generated'),) UPBDEFS_GRPC_GENERATED_INCLUDE = (os.path.join('src', 'core', 'ext', 'upbdefs-generated'),) +XXHASH_INCLUDE = (os.path.join('third_party', 'xxhash'),) ZLIB_INCLUDE = (os.path.join('third_party', 'zlib'),) README = os.path.join(PYTHON_STEM, 'README.rst') @@ -106,37 +107,52 @@ CLASSIFIERS = [ 'License :: OSI Approved :: Apache Software License', ] -BUILD_WITH_BORING_SSL_ASM = os.environ.get('GRPC_BUILD_WITH_BORING_SSL_ASM', - True) + +def _env_bool_value(env_name, default): + """Parses a bool option from an environment variable""" + return os.environ.get(env_name, default).upper() not in ['FALSE', '0', ''] + + +BUILD_WITH_BORING_SSL_ASM = _env_bool_value('GRPC_BUILD_WITH_BORING_SSL_ASM', + 'True') + +# Export this environment variable to override the platform variant that will +# be chosen for boringssl assembly optimizations. This option is useful when +# crosscompiling and the host platform as obtained by distutils.utils.get_platform() +# doesn't match the platform we are targetting. +# Example value: "linux-aarch64" +BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM = os.environ.get( + 'GRPC_BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM', '') # Environment variable to determine whether or not the Cython extension should # *use* Cython or use the generated C files. Note that this requires the C files # to have been generated by building first *with* Cython support. Even if this # is set to false, if the script detects that the generated `.c` file isn't # present, then it will still attempt to use Cython. -BUILD_WITH_CYTHON = os.environ.get('GRPC_PYTHON_BUILD_WITH_CYTHON', False) +BUILD_WITH_CYTHON = _env_bool_value('GRPC_PYTHON_BUILD_WITH_CYTHON', 'False') # Export this variable to use the system installation of openssl. You need to # have the header files installed (in /usr/include/openssl) and during # runtime, the shared library must be installed -BUILD_WITH_SYSTEM_OPENSSL = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_OPENSSL', - False) +BUILD_WITH_SYSTEM_OPENSSL = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_OPENSSL', + 'False') # Export this variable to use the system installation of zlib. You need to # have the header files installed (in /usr/include/) and during # runtime, the shared library must be installed -BUILD_WITH_SYSTEM_ZLIB = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_ZLIB', False) +BUILD_WITH_SYSTEM_ZLIB = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_ZLIB', + 'False') # Export this variable to use the system installation of cares. You need to # have the header files installed (in /usr/include/) and during # runtime, the shared library must be installed -BUILD_WITH_SYSTEM_CARES = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_CARES', - False) +BUILD_WITH_SYSTEM_CARES = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_CARES', + 'False') # Export this variable to use the system installation of re2. You need to # have the header files installed (in /usr/include/re2) and during # runtime, the shared library must be installed -BUILD_WITH_SYSTEM_RE2 = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_RE2', False) +BUILD_WITH_SYSTEM_RE2 = _env_bool_value('GRPC_PYTHON_BUILD_SYSTEM_RE2', 'False') # Export this variable to force building the python extension with a statically linked libstdc++. # At least on linux, this is normally not needed as we can build manylinux-compatible wheels on linux just fine @@ -145,8 +161,8 @@ BUILD_WITH_SYSTEM_RE2 = os.environ.get('GRPC_PYTHON_BUILD_SYSTEM_RE2', False) # it's difficult to ensure that the crosscompilation toolchain has a high-enough version # of GCC (we require >4.9) but still uses old-enough libstdc++ symbols. # TODO(jtattermusch): remove this workaround once issues with crosscompiler version are resolved. -BUILD_WITH_STATIC_LIBSTDCXX = os.environ.get( - 'GRPC_PYTHON_BUILD_WITH_STATIC_LIBSTDCXX', False) +BUILD_WITH_STATIC_LIBSTDCXX = _env_bool_value( + 'GRPC_PYTHON_BUILD_WITH_STATIC_LIBSTDCXX', 'False') # For local development use only: This skips building gRPC Core and its # dependencies, including protobuf and boringssl. This allows "incremental" @@ -159,23 +175,23 @@ BUILD_WITH_STATIC_LIBSTDCXX = os.environ.get( # make HAS_SYSTEM_OPENSSL_ALPN=0 # # TODO(ericgribkoff) Respect the BUILD_WITH_SYSTEM_* flags alongside this option -USE_PREBUILT_GRPC_CORE = os.environ.get('GRPC_PYTHON_USE_PREBUILT_GRPC_CORE', - False) +USE_PREBUILT_GRPC_CORE = _env_bool_value('GRPC_PYTHON_USE_PREBUILT_GRPC_CORE', + 'False') # If this environmental variable is set, GRPC will not try to be compatible with # libc versions old than the one it was compiled against. -DISABLE_LIBC_COMPATIBILITY = os.environ.get( - 'GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', False) +DISABLE_LIBC_COMPATIBILITY = _env_bool_value( + 'GRPC_PYTHON_DISABLE_LIBC_COMPATIBILITY', 'False') # Environment variable to determine whether or not to enable coverage analysis # in Cython modules. -ENABLE_CYTHON_TRACING = os.environ.get('GRPC_PYTHON_ENABLE_CYTHON_TRACING', - False) +ENABLE_CYTHON_TRACING = _env_bool_value('GRPC_PYTHON_ENABLE_CYTHON_TRACING', + 'False') # Environment variable specifying whether or not there's interest in setting up # documentation building. -ENABLE_DOCUMENTATION_BUILD = os.environ.get( - 'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD', False) +ENABLE_DOCUMENTATION_BUILD = _env_bool_value( + 'GRPC_PYTHON_ENABLE_DOCUMENTATION_BUILD', 'False') def check_linker_need_libatomic(): @@ -284,7 +300,8 @@ EXTENSION_INCLUDE_DIRECTORIES = ((PYTHON_STEM,) + CORE_INCLUDE + ABSL_INCLUDE + ADDRESS_SORTING_INCLUDE + CARES_INCLUDE + RE2_INCLUDE + SSL_INCLUDE + UPB_INCLUDE + UPB_GRPC_GENERATED_INCLUDE + - UPBDEFS_GRPC_GENERATED_INCLUDE + ZLIB_INCLUDE) + UPBDEFS_GRPC_GENERATED_INCLUDE + + XXHASH_INCLUDE + ZLIB_INCLUDE) EXTENSION_LIBRARIES = () if "linux" in sys.platform: @@ -314,20 +331,22 @@ asm_files = [] asm_key = '' if BUILD_WITH_BORING_SSL_ASM and not BUILD_WITH_SYSTEM_OPENSSL: + boringssl_asm_platform = BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM if BUILD_OVERRIDE_BORING_SSL_ASM_PLATFORM else util.get_platform( + ) LINUX_X86_64 = 'linux-x86_64' LINUX_ARM = 'linux-arm' LINUX_AARCH64 = 'linux-aarch64' - if LINUX_X86_64 == util.get_platform(): + if LINUX_X86_64 == boringssl_asm_platform: asm_key = 'crypto_linux_x86_64' - elif LINUX_ARM == util.get_platform(): + elif LINUX_ARM == boringssl_asm_platform: asm_key = 'crypto_linux_arm' - elif LINUX_AARCH64 == util.get_platform(): + elif LINUX_AARCH64 == boringssl_asm_platform: asm_key = 'crypto_linux_aarch64' - elif "mac" in util.get_platform() and "x86_64" in util.get_platform(): + elif "mac" in boringssl_asm_platform and "x86_64" in boringssl_asm_platform: asm_key = 'crypto_mac_x86_64' else: print("ASM Builds for BoringSSL currently not supported on:", - util.get_platform()) + boringssl_asm_platform) if asm_key: asm_files = grpc_core_dependencies.ASM_SOURCE_FILES[asm_key] else: diff --git a/src/abseil-cpp/preprocessed_builds.yaml b/src/abseil-cpp/preprocessed_builds.yaml index 257efad9b27..6c73dd3d5ad 100644 --- a/src/abseil-cpp/preprocessed_builds.yaml +++ b/src/abseil-cpp/preprocessed_builds.yaml @@ -63,14 +63,6 @@ - third_party/abseil-cpp/absl/base/internal/scheduling_mode.h name: absl/base:base_internal src: [] -- cmake_target: absl::bits - deps: - - absl/base:config - - absl/base:core_headers - headers: - - third_party/abseil-cpp/absl/base/internal/bits.h - name: absl/base:bits - src: [] - cmake_target: absl::config deps: [] headers: @@ -103,6 +95,7 @@ src: [] - cmake_target: absl::endian deps: + - absl/base:base - absl/base:config - absl/base:core_headers headers: @@ -215,6 +208,24 @@ name: absl/base:throw_delegate src: - third_party/abseil-cpp/absl/base/internal/throw_delegate.cc +- cmake_target: absl::cleanup + deps: + - absl/base:config + - absl/base:core_headers + - absl/cleanup:cleanup_internal + headers: + - third_party/abseil-cpp/absl/cleanup/cleanup.h + name: absl/cleanup:cleanup + src: [] +- cmake_target: absl::cleanup_internal + deps: + - absl/base:base_internal + - absl/base:core_headers + - absl/utility:utility + headers: + - third_party/abseil-cpp/absl/cleanup/internal/cleanup.h + name: absl/cleanup:cleanup_internal + src: [] - cmake_target: absl::btree deps: - absl/base:core_headers @@ -425,7 +436,6 @@ src: [] - cmake_target: absl::raw_hash_set deps: - - absl/base:bits - absl/base:config - absl/base:core_headers - absl/base:endian @@ -439,6 +449,7 @@ - absl/container:layout - absl/memory:memory - absl/meta:type_traits + - absl/numeric:bits - absl/utility:utility headers: - third_party/abseil-cpp/absl/container/internal/raw_hash_set.h @@ -619,6 +630,7 @@ - absl/utility:utility headers: - third_party/abseil-cpp/absl/flags/internal/flag.h + - third_party/abseil-cpp/absl/flags/internal/sequence_lock.h name: absl/flags:flag_internal src: - third_party/abseil-cpp/absl/flags/internal/flag.cc @@ -766,10 +778,12 @@ - third_party/abseil-cpp/absl/hash/internal/city.cc - cmake_target: absl::hash deps: + - absl/base:config - absl/base:core_headers - absl/base:endian - absl/container:fixed_array - absl/hash:city + - absl/hash:wyhash - absl/meta:type_traits - absl/numeric:int128 - absl/strings:strings @@ -782,6 +796,16 @@ name: absl/hash:hash src: - third_party/abseil-cpp/absl/hash/internal/hash.cc +- cmake_target: absl::wyhash + deps: + - absl/base:config + - absl/base:endian + - absl/numeric:int128 + headers: + - third_party/abseil-cpp/absl/hash/internal/wyhash.h + name: absl/hash:wyhash + src: + - third_party/abseil-cpp/absl/hash/internal/wyhash.cc - cmake_target: absl::memory deps: - absl/base:core_headers @@ -797,11 +821,20 @@ - third_party/abseil-cpp/absl/meta/type_traits.h name: absl/meta:type_traits src: [] +- cmake_target: absl::bits + deps: + - absl/base:config + - absl/base:core_headers + headers: + - third_party/abseil-cpp/absl/numeric/bits.h + - third_party/abseil-cpp/absl/numeric/internal/bits.h + name: absl/numeric:bits + src: [] - cmake_target: absl::int128 deps: - - absl/base:bits - absl/base:config - absl/base:core_headers + - absl/numeric:bits headers: - third_party/abseil-cpp/absl/numeric/int128.h - third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc @@ -809,6 +842,13 @@ name: absl/numeric:int128 src: - third_party/abseil-cpp/absl/numeric/int128.cc +- cmake_target: absl::numeric_representation + deps: + - absl/base:config + headers: + - third_party/abseil-cpp/absl/numeric/internal/representation.h + name: absl/numeric:representation + src: [] - cmake_target: absl::random_internal_distribution_caller deps: - absl/base:config @@ -828,15 +868,15 @@ src: [] - cmake_target: absl::random_internal_fastmath deps: - - absl/base:bits + - absl/numeric:bits headers: - third_party/abseil-cpp/absl/random/internal/fastmath.h name: absl/random/internal:fastmath src: [] - cmake_target: absl::random_internal_generate_real deps: - - absl/base:bits - absl/meta:type_traits + - absl/numeric:bits - absl/random/internal:fastmath - absl/random/internal:traits headers: @@ -888,6 +928,7 @@ deps: - absl/base:config - absl/meta:type_traits + - absl/numeric:bits - absl/numeric:int128 - absl/random/internal:fastmath - absl/random/internal:iostream_state_saver @@ -934,6 +975,7 @@ - third_party/abseil-cpp/absl/random/internal/randen.cc - cmake_target: absl::random_internal_randen_engine deps: + - absl/base:endian - absl/meta:type_traits - absl/random/internal:iostream_state_saver - absl/random/internal:randen @@ -1014,8 +1056,8 @@ src: [] - cmake_target: absl::random_internal_wide_multiply deps: - - absl/base:bits - absl/base:config + - absl/numeric:bits - absl/numeric:int128 - absl/random/internal:traits headers: @@ -1040,6 +1082,7 @@ - absl/base:config - absl/base:core_headers - absl/meta:type_traits + - absl/numeric:bits - absl/random/internal:distribution_caller - absl/random/internal:fast_uniform_bits - absl/random/internal:fastmath @@ -1158,13 +1201,25 @@ - cmake_target: absl::cord deps: - absl/base:base_internal + - absl/base:config + - absl/base:core_headers + - absl/base:endian + - absl/base:raw_logging_internal + - absl/base:throw_delegate - absl/container:compressed_tuple + - absl/container:inlined_vector + - absl/container:layout - absl/meta:type_traits - absl/strings:strings headers: - third_party/abseil-cpp/absl/strings/internal/cord_internal.h + - third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h + - third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.h + - third_party/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h name: absl/strings:cord_internal - src: [] + src: + - third_party/abseil-cpp/absl/strings/internal/cord_internal.cc + - third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc - cmake_target: absl::strings_internal deps: - absl/base:config @@ -1192,12 +1247,13 @@ src: [] - cmake_target: absl::str_format_internal deps: - - absl/base:bits - absl/base:config - absl/base:core_headers - absl/functional:function_ref - absl/meta:type_traits + - absl/numeric:bits - absl/numeric:int128 + - absl/numeric:representation - absl/strings:strings - absl/types:optional - absl/types:span @@ -1220,7 +1276,6 @@ - cmake_target: absl::strings deps: - absl/base:base - - absl/base:bits - absl/base:config - absl/base:core_headers - absl/base:endian @@ -1228,6 +1283,7 @@ - absl/base:throw_delegate - absl/memory:memory - absl/meta:type_traits + - absl/numeric:bits - absl/numeric:int128 - absl/strings:internal headers: @@ -1240,6 +1296,7 @@ - third_party/abseil-cpp/absl/strings/internal/stl_type_traits.h - third_party/abseil-cpp/absl/strings/internal/str_join_internal.h - third_party/abseil-cpp/absl/strings/internal/str_split_internal.h + - third_party/abseil-cpp/absl/strings/internal/string_constant.h - third_party/abseil-cpp/absl/strings/match.h - third_party/abseil-cpp/absl/strings/numbers.h - third_party/abseil-cpp/absl/strings/str_cat.h @@ -1305,7 +1362,7 @@ - third_party/abseil-cpp/absl/synchronization/barrier.h - third_party/abseil-cpp/absl/synchronization/blocking_counter.h - third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.h - - third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc + - third_party/abseil-cpp/absl/synchronization/internal/futex.h - third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h - third_party/abseil-cpp/absl/synchronization/internal/waiter.h - third_party/abseil-cpp/absl/synchronization/mutex.h diff --git a/src/boringssl/boringssl_prefix_symbols.h b/src/boringssl/boringssl_prefix_symbols.h index 40d458c470e..1991903fc4c 100644 --- a/src/boringssl/boringssl_prefix_symbols.h +++ b/src/boringssl/boringssl_prefix_symbols.h @@ -1,4 +1,4 @@ -// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: 1a7359455220f7010def8c63f7c7e041ce6707c6 +// generated by generate_boringssl_prefix_header.sh on BoringSSL commit: 688fc5cf5428868679d2ae1072cad81055752068 // Copyright (c) 2018, Google Inc. // @@ -142,6 +142,7 @@ #define SSL_CTX_set1_chain BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_chain) #define SSL_CTX_set1_curves BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_curves) #define SSL_CTX_set1_curves_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_curves_list) +#define SSL_CTX_set1_ech_server_config_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_ech_server_config_list) #define SSL_CTX_set1_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_param) #define SSL_CTX_set1_sigalgs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_sigalgs) #define SSL_CTX_set1_sigalgs_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set1_sigalgs_list) @@ -168,7 +169,6 @@ #define SSL_CTX_set_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_ex_data) #define SSL_CTX_set_false_start_allowed_without_alpn BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_false_start_allowed_without_alpn) #define SSL_CTX_set_grease_enabled BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_grease_enabled) -#define SSL_CTX_set_ignore_tls13_downgrade BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_ignore_tls13_downgrade) #define SSL_CTX_set_info_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_info_callback) #define SSL_CTX_set_keylog_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_keylog_callback) #define SSL_CTX_set_max_cert_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_set_max_cert_list) @@ -230,6 +230,10 @@ #define SSL_CTX_use_certificate_chain_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_certificate_chain_file) #define SSL_CTX_use_certificate_file BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_certificate_file) #define SSL_CTX_use_psk_identity_hint BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_CTX_use_psk_identity_hint) +#define SSL_ECH_SERVER_CONFIG_LIST_add BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_add) +#define SSL_ECH_SERVER_CONFIG_LIST_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_free) +#define SSL_ECH_SERVER_CONFIG_LIST_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_new) +#define SSL_ECH_SERVER_CONFIG_LIST_up_ref BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_ECH_SERVER_CONFIG_LIST_up_ref) #define SSL_SESSION_copy_without_early_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_copy_without_early_data) #define SSL_SESSION_early_data_capable BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_early_data_capable) #define SSL_SESSION_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_SESSION_free) @@ -393,7 +397,6 @@ #define SSL_is_init_finished BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_init_finished) #define SSL_is_server BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_server) #define SSL_is_signature_algorithm_rsa_pss BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_signature_algorithm_rsa_pss) -#define SSL_is_tls13_downgrade BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_tls13_downgrade) #define SSL_is_token_binding_negotiated BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_is_token_binding_negotiated) #define SSL_key_update BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_key_update) #define SSL_library_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_library_init) @@ -415,9 +418,12 @@ #define SSL_read BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_read) #define SSL_renegotiate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_renegotiate) #define SSL_renegotiate_pending BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_renegotiate_pending) +#define SSL_request_handshake_hints BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_request_handshake_hints) #define SSL_reset_early_data_reject BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_reset_early_data_reject) #define SSL_select_next_proto BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_select_next_proto) #define SSL_send_fatal_alert BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_send_fatal_alert) +#define SSL_serialize_capabilities BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_serialize_capabilities) +#define SSL_serialize_handshake_hints BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_serialize_handshake_hints) #define SSL_session_reused BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_session_reused) #define SSL_set0_chain BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set0_chain) #define SSL_set0_client_CAs BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set0_client_CAs) @@ -448,7 +454,7 @@ #define SSL_set_enforce_rsa_key_usage BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_enforce_rsa_key_usage) #define SSL_set_ex_data BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_ex_data) #define SSL_set_fd BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_fd) -#define SSL_set_ignore_tls13_downgrade BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_ignore_tls13_downgrade) +#define SSL_set_handshake_hints BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_handshake_hints) #define SSL_set_info_callback BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_info_callback) #define SSL_set_jdk11_workaround BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_jdk11_workaround) #define SSL_set_max_cert_list BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, SSL_set_max_cert_list) @@ -1289,6 +1295,7 @@ #define ECDSA_do_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_do_sign) #define ECDSA_do_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_do_verify) #define ECDSA_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_sign) +#define ECDSA_sign_with_nonce_and_leak_private_key_for_testing BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_sign_with_nonce_and_leak_private_key_for_testing) #define ECDSA_size BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_size) #define ECDSA_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ECDSA_verify) #define EC_GFp_mont_method BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GFp_mont_method) @@ -1300,6 +1307,7 @@ #define EC_GROUP_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GROUP_free) #define EC_GROUP_get0_generator BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GROUP_get0_generator) #define EC_GROUP_get0_order BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GROUP_get0_order) +#define EC_GROUP_get_asn1_flag BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GROUP_get_asn1_flag) #define EC_GROUP_get_cofactor BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GROUP_get_cofactor) #define EC_GROUP_get_curve_GFp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GROUP_get_curve_GFp) #define EC_GROUP_get_curve_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EC_GROUP_get_curve_name) @@ -1505,6 +1513,8 @@ #define EVP_EncryptUpdate BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_EncryptUpdate) #define EVP_HPKE_CTX_cleanup BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_cleanup) #define EVP_HPKE_CTX_export BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_export) +#define EVP_HPKE_CTX_get_aead_id BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_get_aead_id) +#define EVP_HPKE_CTX_get_kdf_id BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_get_kdf_id) #define EVP_HPKE_CTX_init BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_init) #define EVP_HPKE_CTX_max_overhead BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_max_overhead) #define EVP_HPKE_CTX_open BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_HPKE_CTX_open) @@ -1631,7 +1641,6 @@ #define EVP_add_digest BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_add_digest) #define EVP_aead_aes_128_cbc_sha1_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha1_tls) #define EVP_aead_aes_128_cbc_sha1_tls_implicit_iv BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha1_tls_implicit_iv) -#define EVP_aead_aes_128_cbc_sha256_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_cbc_sha256_tls) #define EVP_aead_aes_128_ccm_bluetooth BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_ccm_bluetooth) #define EVP_aead_aes_128_ccm_bluetooth_8 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_ccm_bluetooth_8) #define EVP_aead_aes_128_ctr_hmac_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_128_ctr_hmac_sha256) @@ -1643,8 +1652,6 @@ #define EVP_aead_aes_192_gcm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_192_gcm) #define EVP_aead_aes_256_cbc_sha1_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha1_tls) #define EVP_aead_aes_256_cbc_sha1_tls_implicit_iv BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha1_tls_implicit_iv) -#define EVP_aead_aes_256_cbc_sha256_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha256_tls) -#define EVP_aead_aes_256_cbc_sha384_tls BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_cbc_sha384_tls) #define EVP_aead_aes_256_ctr_hmac_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_ctr_hmac_sha256) #define EVP_aead_aes_256_gcm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_gcm) #define EVP_aead_aes_256_gcm_randnonce BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_aead_aes_256_gcm_randnonce) @@ -1700,6 +1707,7 @@ #define EVP_rc2_cbc BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_rc2_cbc) #define EVP_rc4 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_rc4) #define EVP_sha1 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha1) +#define EVP_sha1_final_with_secret_suffix BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha1_final_with_secret_suffix) #define EVP_sha224 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha224) #define EVP_sha256 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha256) #define EVP_sha384 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EVP_sha384) @@ -1714,6 +1722,7 @@ #define EXTENDED_KEY_USAGE_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, EXTENDED_KEY_USAGE_new) #define FIPS_mode BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_mode) #define FIPS_mode_set BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_mode_set) +#define FIPS_read_counter BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, FIPS_read_counter) #define GENERAL_NAMES_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, GENERAL_NAMES_free) #define GENERAL_NAMES_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, GENERAL_NAMES_it) #define GENERAL_NAMES_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, GENERAL_NAMES_new) @@ -2198,7 +2207,6 @@ #define X509_ALGOR_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_new) #define X509_ALGOR_set0 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_set0) #define X509_ALGOR_set_md BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ALGOR_set_md) -#define X509_ATTRIBUTE_SET_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_SET_it) #define X509_ATTRIBUTE_count BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_count) #define X509_ATTRIBUTE_create BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_create) #define X509_ATTRIBUTE_create_by_NID BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_ATTRIBUTE_create_by_NID) @@ -2218,10 +2226,8 @@ #define X509_CERT_AUX_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CERT_AUX_new) #define X509_CERT_AUX_print BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CERT_AUX_print) #define X509_CINF_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_free) -#define X509_CINF_get_signature BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_get_signature) #define X509_CINF_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_it) #define X509_CINF_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_new) -#define X509_CINF_set_modified BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CINF_set_modified) #define X509_CRL_INFO_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CRL_INFO_free) #define X509_CRL_INFO_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CRL_INFO_it) #define X509_CRL_INFO_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_CRL_INFO_new) @@ -2350,6 +2356,7 @@ #define X509_PUBKEY_free BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_free) #define X509_PUBKEY_get BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get) #define X509_PUBKEY_get0_param BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get0_param) +#define X509_PUBKEY_get0_public_key BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_get0_public_key) #define X509_PUBKEY_it BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_it) #define X509_PUBKEY_new BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_new) #define X509_PUBKEY_set BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_PUBKEY_set) @@ -2386,7 +2393,6 @@ #define X509_REQ_get_attr_by_NID BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_attr_by_NID) #define X509_REQ_get_attr_by_OBJ BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_attr_by_OBJ) #define X509_REQ_get_attr_count BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_attr_count) -#define X509_REQ_get_extension_nids BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_extension_nids) #define X509_REQ_get_extensions BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_extensions) #define X509_REQ_get_pubkey BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_pubkey) #define X509_REQ_get_signature_nid BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_get_signature_nid) @@ -2397,13 +2403,11 @@ #define X509_REQ_print BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_print) #define X509_REQ_print_ex BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_print_ex) #define X509_REQ_print_fp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_print_fp) -#define X509_REQ_set_extension_nids BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_extension_nids) #define X509_REQ_set_pubkey BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_pubkey) #define X509_REQ_set_subject_name BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_subject_name) #define X509_REQ_set_version BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_set_version) #define X509_REQ_sign BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_sign) #define X509_REQ_sign_ctx BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_sign_ctx) -#define X509_REQ_to_X509 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_to_X509) #define X509_REQ_verify BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REQ_verify) #define X509_REVOKED_add1_ext_i2d BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REVOKED_add1_ext_i2d) #define X509_REVOKED_add_ext BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_REVOKED_add_ext) @@ -2591,7 +2595,6 @@ #define X509_get1_email BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get1_email) #define X509_get1_ocsp BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get1_ocsp) #define X509_get_X509_PUBKEY BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_X509_PUBKEY) -#define X509_get_cert_info BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_cert_info) #define X509_get_default_cert_area BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_default_cert_area) #define X509_get_default_cert_dir BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_default_cert_dir) #define X509_get_default_cert_dir_env BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, X509_get_default_cert_dir_env) @@ -2785,6 +2788,7 @@ #define asn1_refcount_dec_and_test_zero BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_refcount_dec_and_test_zero) #define asn1_refcount_set_one BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_refcount_set_one) #define asn1_set_choice_selector BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_set_choice_selector) +#define asn1_type_value_as_pointer BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_type_value_as_pointer) #define asn1_utctime_to_tm BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, asn1_utctime_to_tm) #define beeu_mod_inverse_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, beeu_mod_inverse_vartime) #define bio_clear_socket_error BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, bio_clear_socket_error) @@ -3085,6 +3089,7 @@ #define ec_set_to_safe_point BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_set_to_safe_point) #define ec_simple_scalar_inv0_montgomery BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_simple_scalar_inv0_montgomery) #define ec_simple_scalar_to_montgomery_inv_vartime BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ec_simple_scalar_to_montgomery_inv_vartime) +#define ecdsa_sign_with_nonce_for_known_answer_test BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ecdsa_sign_with_nonce_for_known_answer_test) #define ecp_nistz256_avx2_select_w7 BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ecp_nistz256_avx2_select_w7) #define ecp_nistz256_mul_mont BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ecp_nistz256_mul_mont) #define ecp_nistz256_neg BORINGSSL_ADD_PREFIX(BORINGSSL_PREFIX, ecp_nistz256_neg) diff --git a/src/compiler/cpp_generator.cc b/src/compiler/cpp_generator.cc index c78a3e08e22..c8dff735fc2 100644 --- a/src/compiler/cpp_generator.cc +++ b/src/compiler/cpp_generator.cc @@ -633,12 +633,12 @@ void PrintHeaderClientMethodCallbackInterfaces( printer->Print(*vars, "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n" "virtual void $Method$(::grpc::ClientContext* context, " - "$Request$* request, " + "const $Request$* request, " "::grpc::ClientReadReactor< $Response$>* " "reactor) = 0;\n" "#else\n" "virtual void $Method$(::grpc::ClientContext* context, " - "$Request$* request, " + "const $Request$* request, " "::grpc::experimental::ClientReadReactor< $Response$>* " "reactor) = 0;\n" "#endif\n"); @@ -730,12 +730,12 @@ void PrintHeaderClientMethodCallback(grpc_generator::Printer* printer, printer->Print(*vars, "#ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL\n" "void $Method$(::grpc::ClientContext* context, " - "$Request$* request, " + "const $Request$* request, " "::grpc::ClientReadReactor< $Response$>* " "reactor) override;\n" "#else\n" "void $Method$(::grpc::ClientContext* context, " - "$Request$* request, " + "const $Request$* request, " "::grpc::experimental::ClientReadReactor< $Response$>* " "reactor) override;\n" "#endif\n"); @@ -1557,7 +1557,8 @@ void PrintHeaderService(grpc_generator::Printer* printer, printer->Indent(); printer->Print( "Stub(const std::shared_ptr< ::grpc::ChannelInterface>& " - "channel);\n"); + "channel, const ::grpc::StubOptions& options = " + "::grpc::StubOptions());\n"); for (int i = 0; i < service->method_count(); ++i) { PrintHeaderClientMethod(printer, service->method(i).get(), vars, true); } @@ -2005,7 +2006,7 @@ void PrintSourceClientMethod(grpc_generator::Printer* printer, *vars, "void $ns$$Service$::Stub::experimental_async::$Method$(::grpc::" "ClientContext* context, " - "$Request$* request, " + "const $Request$* request, " "::grpc::experimental::ClientReadReactor< $Response$>* reactor) {\n"); printer->Print(*vars, " ::grpc::internal::ClientCallbackReaderFactory< " @@ -2163,12 +2164,13 @@ void PrintSourceService(grpc_generator::Printer* printer, "const ::grpc::StubOptions& options) {\n" " (void)options;\n" " std::unique_ptr< $ns$$Service$::Stub> stub(new " - "$ns$$Service$::Stub(channel));\n" + "$ns$$Service$::Stub(channel, options));\n" " return stub;\n" "}\n\n"); printer->Print(*vars, "$ns$$Service$::Stub::Stub(const std::shared_ptr< " - "::grpc::ChannelInterface>& channel)\n"); + "::grpc::ChannelInterface>& channel, const " + "::grpc::StubOptions& options)\n"); printer->Indent(); printer->Print(": channel_(channel)"); for (int i = 0; i < service->method_count(); ++i) { @@ -2187,12 +2189,13 @@ void PrintSourceService(grpc_generator::Printer* printer, } else { (*vars)["StreamingType"] = "BIDI_STREAMING"; } - printer->Print(*vars, - ", rpcmethod_$Method$_(" - "$prefix$$Service$_method_names[$Idx$], " - "::grpc::internal::RpcMethod::$StreamingType$, " - "channel" - ")\n"); + printer->Print( + *vars, + ", rpcmethod_$Method$_(" + "$prefix$$Service$_method_names[$Idx$], options.suffix_for_stats()," + "::grpc::internal::RpcMethod::$StreamingType$, " + "channel" + ")\n"); } printer->Print("{}\n\n"); printer->Outdent(); diff --git a/src/compiler/php_generator.cc b/src/compiler/php_generator.cc index b2a26e5c0fa..28bbebd1041 100644 --- a/src/compiler/php_generator.cc +++ b/src/compiler/php_generator.cc @@ -131,34 +131,177 @@ void PrintMethod(const MethodDescriptor* method, Printer* out) { out->Print("}\n\n"); } -// Prints out the service descriptor object -void PrintService(const ServiceDescriptor* service, - const std::string& class_suffix, Printer* out) { +void PrintServerMethod(const MethodDescriptor* method, Printer* out) { map vars; + const Descriptor* input_type = method->input_type(); + const Descriptor* output_type = method->output_type(); + vars["service_name"] = method->service()->full_name(); + vars["method_name"] = method->name(); + vars["input_type_id"] = + MessageIdentifierName(GeneratedClassName(input_type), input_type->file()); + vars["output_type_id"] = MessageIdentifierName( + GeneratedClassName(output_type), output_type->file()); + out->Print("/**\n"); - out->Print(GetPHPComments(service, " *").c_str()); - out->Print(" */\n"); - vars["name"] = GetPHPServiceClassname(service, class_suffix); - out->Print(vars, "class $name$ extends \\Grpc\\BaseStub {\n\n"); + out->Print(GetPHPComments(method, " *").c_str()); + + const char* method_template; + if (method->client_streaming() && method->server_streaming()) { + method_template = + " * @param \\Grpc\\ServerCallReader $$reader read client request data " + "of \\$input_type_id$\n" + " * @param \\Grpc\\ServerCallWriter $$writer write response data of " + "\\$output_type_id$\n" + " * @param \\Grpc\\ServerContext $$context server request context\n" + " * @return void\n" + " */\n" + "public function $method_name$(\n" + " \\Grpc\\ServerCallReader $$reader,\n" + " \\Grpc\\ServerCallWriter $$writer,\n" + " \\Grpc\\ServerContext $$context\n" + "): void {\n" + " $$context->setStatus(\\Grpc\\Status::unimplemented());\n" + " $$writer->finish();\n" + "}\n\n"; + } else if (method->client_streaming()) { + method_template = + " * @param \\Grpc\\ServerCallReader $$reader read client request data " + "of \\$input_type_id$\n" + " * @param \\Grpc\\ServerContext $$context server request context\n" + " * @return \\$output_type_id$ for response data, null if if error " + "occured\n" + " * initial metadata (if any) and status (if not ok) should be set " + "to $$context\n" + " */\n" + "public function $method_name$(\n" + " \\Grpc\\ServerCallReader $$reader,\n" + " \\Grpc\\ServerContext $$context\n" + "): ?\\$output_type_id$ {\n" + " $$context->setStatus(\\Grpc\\Status::unimplemented());\n" + " return null;\n" + "}\n\n"; + } else if (method->server_streaming()) { + method_template = + " * @param \\$input_type_id$ $$request client request\n" + " * @param \\Grpc\\ServerCallWriter $$writer write response data of " + "\\$output_type_id$\n" + " * @param \\Grpc\\ServerContext $$context server request context\n" + " * @return void\n" + " */\n" + "public function $method_name$(\n" + " \\$input_type_id$ $$request,\n" + " \\Grpc\\ServerCallWriter $$writer,\n" + " \\Grpc\\ServerContext $$context\n" + "): void {\n" + " $$context->setStatus(\\Grpc\\Status::unimplemented());\n" + " $$writer->finish();\n" + "}\n\n"; + } else { + method_template = + " * @param \\$input_type_id$ $$request client request\n" + " * @param \\Grpc\\ServerContext $$context server request context\n" + " * @return \\$output_type_id$ for response data, null if if error " + "occured\n" + " * initial metadata (if any) and status (if not ok) should be set " + "to $$context\n" + " */\n" + "public function $method_name$(\n" + " \\$input_type_id$ $$request,\n" + " \\Grpc\\ServerContext $$context\n" + "): ?\\$output_type_id$ {\n" + " $$context->setStatus(\\Grpc\\Status::unimplemented());\n" + " return null;\n" + "}\n\n"; + } + out->Print(vars, method_template); +} + +void PrintServerMethodDescriptors(const ServiceDescriptor* service, + Printer* out) { + map vars; + vars["service_name"] = service->full_name(); + + out->Print( + "/**\n" + " * Get the method descriptors of the service for server registration\n" + " *\n" + " * @return array of \\Grpc\\MethodDescriptor for the service methods\n" + " */\n" + "public final function getMethodDescriptors(): array\n{\n"); out->Indent(); out->Indent(); - out->Print( - "/**\n * @param string $$hostname hostname\n" - " * @param array $$opts channel options\n" - " * @param \\Grpc\\Channel $$channel (optional) re-use channel " - "object\n */\n" - "public function __construct($$hostname, $$opts, " - "$$channel = null) {\n"); + out->Print("return [\n"); out->Indent(); out->Indent(); - out->Print("parent::__construct($$hostname, $$opts, $$channel);\n"); + for (int i = 0; i < service->method_count(); i++) { + auto method = service->method(i); + auto input_type = method->input_type(); + vars["method_name"] = method->name(); + vars["input_type_id"] = MessageIdentifierName( + GeneratedClassName(input_type), input_type->file()); + if (method->client_streaming() && method->server_streaming()) { + vars["call_type"] = "BIDI_STREAMING_CALL"; + } else if (method->client_streaming()) { + vars["call_type"] = "CLIENT_STREAMING_CALL"; + } else if (method->server_streaming()) { + vars["call_type"] = "SERVER_STREAMING_CALL"; + } else { + vars["call_type"] = "UNARY_CALL"; + } + out->Print( + vars, + "'/$service_name$/$method_name$' => new \\Grpc\\MethodDescriptor(\n" + " $$this,\n" + " '$method_name$',\n" + " '\\$input_type_id$',\n" + " \\Grpc\\MethodDescriptor::$call_type$\n" + "),\n"); + } + out->Outdent(); + out->Outdent(); + out->Print("];\n"); out->Outdent(); out->Outdent(); out->Print("}\n\n"); +} + +// Prints out the service descriptor object +void PrintService(const ServiceDescriptor* service, + const std::string& class_suffix, bool is_server, + Printer* out) { + map vars; + out->Print("/**\n"); + out->Print(GetPHPComments(service, " *").c_str()); + out->Print(" */\n"); + vars["name"] = GetPHPServiceClassname(service, class_suffix, is_server); + vars["extends"] = is_server ? "" : "extends \\Grpc\\BaseStub "; + out->Print(vars, "class $name$ $extends${\n\n"); + out->Indent(); + out->Indent(); + if (!is_server) { + out->Print( + "/**\n * @param string $$hostname hostname\n" + " * @param array $$opts channel options\n" + " * @param \\Grpc\\Channel $$channel (optional) re-use channel object\n" + " */\n" + "public function __construct($$hostname, $$opts, " + "$$channel = null) {\n"); + out->Indent(); + out->Indent(); + out->Print("parent::__construct($$hostname, $$opts, $$channel);\n"); + out->Outdent(); + out->Outdent(); + out->Print("}\n\n"); + } for (int i = 0; i < service->method_count(); i++) { - std::string method_name = - grpc_generator::LowercaseFirstLetter(service->method(i)->name()); - PrintMethod(service->method(i), out); + if (is_server) { + PrintServerMethod(service->method(i), out); + } else { + PrintMethod(service->method(i), out); + } + } + if (is_server) { + PrintServerMethodDescriptors(service, out); } out->Outdent(); out->Outdent(); @@ -168,7 +311,7 @@ void PrintService(const ServiceDescriptor* service, std::string GenerateFile(const FileDescriptor* file, const ServiceDescriptor* service, - const std::string& class_suffix) { + const std::string& class_suffix, bool is_server) { std::string output; { StringOutputStream output_stream(&output); @@ -188,7 +331,7 @@ std::string GenerateFile(const FileDescriptor* file, vars["package"] = php_namespace; out.Print(vars, "namespace $package$;\n\n"); - PrintService(service, class_suffix, &out); + PrintService(service, class_suffix, is_server, &out); } return output; } diff --git a/src/compiler/php_generator.h b/src/compiler/php_generator.h index aa6d20c7fd7..f775c8f2ca6 100644 --- a/src/compiler/php_generator.h +++ b/src/compiler/php_generator.h @@ -25,7 +25,8 @@ namespace grpc_php_generator { std::string GenerateFile(const grpc::protobuf::FileDescriptor* file, const grpc::protobuf::ServiceDescriptor* service, - const std::string& class_suffix); + const std::string& class_suffix, + bool is_server = false); } // namespace grpc_php_generator diff --git a/src/compiler/php_generator_helpers.h b/src/compiler/php_generator_helpers.h index 24560e4d984..a4617df1bc9 100644 --- a/src/compiler/php_generator_helpers.h +++ b/src/compiler/php_generator_helpers.h @@ -28,8 +28,10 @@ namespace grpc_php_generator { inline std::string GetPHPServiceClassname( const grpc::protobuf::ServiceDescriptor* service, - const std::string& class_suffix) { - return service->name() + (class_suffix == "" ? "Client" : class_suffix); + const std::string& class_suffix, bool is_server) { + return service->name() + + (class_suffix == "" ? (is_server ? "" : "Client") : class_suffix) + + (is_server ? "Stub" : ""); } // ReplaceAll replaces all instances of search with replace in s. @@ -46,7 +48,7 @@ inline std::string ReplaceAll(std::string s, const std::string& search, inline std::string GetPHPServiceFilename( const grpc::protobuf::FileDescriptor* file, const grpc::protobuf::ServiceDescriptor* service, - const std::string& class_suffix) { + const std::string& class_suffix, bool is_server) { std::ostringstream oss; if (file->options().has_php_namespace()) { oss << ReplaceAll(file->options().php_namespace(), "\\", "/"); @@ -58,8 +60,8 @@ inline std::string GetPHPServiceFilename( << grpc_generator::CapitalizeFirstLetter(tokens[i]); } } - return oss.str() + "/" + GetPHPServiceClassname(service, class_suffix) + - ".php"; + return oss.str() + "/" + + GetPHPServiceClassname(service, class_suffix, is_server) + ".php"; } // Get leading or trailing comments in a string. Comment lines start with "// ". diff --git a/src/compiler/php_plugin.cc b/src/compiler/php_plugin.cc index c1be38765f5..7d4e4ce32c5 100644 --- a/src/compiler/php_plugin.cc +++ b/src/compiler/php_plugin.cc @@ -48,10 +48,13 @@ class PHPGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { std::vector > options; ParseGeneratorParameter(parameter, &options); + bool generate_server = false; std::string class_suffix; for (size_t i = 0; i < options.size(); ++i) { if (options[i].first == "class_suffix") { class_suffix = options[i].second; + } else if (options[i].first == "generate_server") { + generate_server = true; } else { *error = "unsupported options: " + options[i].first; return false; @@ -59,20 +62,32 @@ class PHPGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator { } for (int i = 0; i < file->service_count(); i++) { - std::string code = GenerateFile(file, file->service(i), class_suffix); - - // Get output file name - std::string file_name = - GetPHPServiceFilename(file, file->service(i), class_suffix); - - std::unique_ptr output( - context->Open(file_name)); - grpc::protobuf::io::CodedOutputStream coded_out(output.get()); - coded_out.WriteRaw(code.data(), code.size()); + GenerateService(file, file->service(i), class_suffix, false, context); + if (generate_server) { + GenerateService(file, file->service(i), class_suffix, true, context); + } } return true; } + + private: + void GenerateService( + const grpc::protobuf::FileDescriptor* file, + const grpc::protobuf::ServiceDescriptor* service, + const std::string& class_suffix, bool is_server, + grpc::protobuf::compiler::GeneratorContext* context) const { + std::string code = GenerateFile(file, service, class_suffix, is_server); + + // Get output file name + std::string file_name = + GetPHPServiceFilename(file, service, class_suffix, is_server); + + std::unique_ptr output( + context->Open(file_name)); + grpc::protobuf::io::CodedOutputStream coded_out(output.get()); + coded_out.WriteRaw(code.data(), code.size()); + } }; int main(int argc, char* argv[]) { diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc index 2b86b7029fc..2fae61082f0 100644 --- a/src/compiler/ruby_generator.cc +++ b/src/compiler/ruby_generator.cc @@ -80,7 +80,7 @@ void PrintService(const ServiceDescriptor* service, Printer* out) { // Write the indented class body. out->Indent(); out->Print("\n"); - out->Print("include GRPC::GenericService\n"); + out->Print("include ::GRPC::GenericService\n"); out->Print("\n"); out->Print("self.marshal_class_method = :encode\n"); out->Print("self.unmarshal_class_method = :decode\n"); diff --git a/src/core/ext/filters/client_channel/backup_poller.cc b/src/core/ext/filters/client_channel/backup_poller.cc index 1b7708953ab..ad7f89210d8 100644 --- a/src/core/ext/filters/client_channel/backup_poller.cc +++ b/src/core/ext/filters/client_channel/backup_poller.cc @@ -89,7 +89,7 @@ static void backup_poller_shutdown_unref(backup_poller* p) { } } -static void done_poller(void* arg, grpc_error* /*error*/) { +static void done_poller(void* arg, grpc_error_handle /*error*/) { backup_poller_shutdown_unref(static_cast(arg)); } @@ -112,7 +112,7 @@ static void g_poller_unref() { } } -static void run_poller(void* arg, grpc_error* error) { +static void run_poller(void* arg, grpc_error_handle error) { backup_poller* p = static_cast(arg); if (error != GRPC_ERROR_NONE) { if (error != GRPC_ERROR_CANCELLED) { @@ -127,7 +127,7 @@ static void run_poller(void* arg, grpc_error* error) { backup_poller_shutdown_unref(p); return; } - grpc_error* err = + grpc_error_handle err = grpc_pollset_work(p->pollset, nullptr, grpc_core::ExecCtx::Get()->Now()); gpr_mu_unlock(p->pollset_mu); GRPC_LOG_IF_ERROR("Run client channel backup poller", err); diff --git a/src/core/ext/filters/client_channel/channel_connectivity.cc b/src/core/ext/filters/client_channel/channel_connectivity.cc index 4ebb976efe5..e5ec5c5fe09 100644 --- a/src/core/ext/filters/client_channel/channel_connectivity.cc +++ b/src/core/ext/filters/client_channel/channel_connectivity.cc @@ -1,28 +1,23 @@ -/* - * - * 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. - * - */ +// +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// #include #include "src/core/lib/surface/channel.h" -#include - -#include #include #include "src/core/ext/filters/client_channel/client_channel.h" @@ -32,195 +27,205 @@ grpc_connectivity_state grpc_channel_check_connectivity_state( grpc_channel* channel, int try_to_connect) { - /* forward through to the underlying client channel */ - grpc_channel_element* client_channel_elem = - grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; - grpc_connectivity_state state; GRPC_API_TRACE( "grpc_channel_check_connectivity_state(channel=%p, try_to_connect=%d)", 2, (channel, try_to_connect)); - if (GPR_LIKELY(client_channel_elem->filter == &grpc_client_channel_filter)) { - state = grpc_client_channel_check_connectivity_state(client_channel_elem, - try_to_connect); - - return state; + // Forward through to the underlying client channel. + grpc_core::ClientChannel* client_channel = + grpc_core::ClientChannel::GetFromChannel(channel); + if (GPR_UNLIKELY(client_channel == nullptr)) { + gpr_log(GPR_ERROR, + "grpc_channel_check_connectivity_state called on something that is " + "not a client channel"); + return GRPC_CHANNEL_SHUTDOWN; } - gpr_log(GPR_ERROR, - "grpc_channel_check_connectivity_state called on something that is " - "not a client channel, but '%s'", - client_channel_elem->filter->name); + return client_channel->CheckConnectivityState(try_to_connect); +} - return GRPC_CHANNEL_SHUTDOWN; +int grpc_channel_num_external_connectivity_watchers(grpc_channel* channel) { + grpc_core::ClientChannel* client_channel = + grpc_core::ClientChannel::GetFromChannel(channel); + if (client_channel == nullptr) { + gpr_log(GPR_ERROR, + "grpc_channel_num_external_connectivity_watchers called on " + "something that is not a client channel"); + return 0; + } + return client_channel->NumExternalConnectivityWatchers(); } -typedef enum { - WAITING, - READY_TO_CALL_BACK, - CALLING_BACK_AND_FINISHED, -} callback_phase; +int grpc_channel_support_connectivity_watcher(grpc_channel* channel) { + return grpc_core::ClientChannel::GetFromChannel(channel) != nullptr; +} +namespace grpc_core { namespace { -struct state_watcher { - gpr_mu mu; - callback_phase phase; - grpc_closure on_complete; - grpc_closure on_timeout; - grpc_closure watcher_timer_init; - grpc_timer alarm; - grpc_connectivity_state state; - grpc_completion_queue* cq; - grpc_cq_completion completion_storage; - grpc_channel* channel; - grpc_error* error; - void* tag; -}; -} // namespace - -static void delete_state_watcher(state_watcher* w) { - grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element( - grpc_channel_get_channel_stack(w->channel)); - if (client_channel_elem->filter == &grpc_client_channel_filter) { - GRPC_CHANNEL_INTERNAL_UNREF(w->channel, "watch_channel_connectivity"); - } else { - abort(); - } - gpr_mu_destroy(&w->mu); - gpr_free(w); -} -static void finished_completion(void* pw, grpc_cq_completion* /*ignored*/) { - bool should_delete = false; - state_watcher* w = static_cast(pw); - gpr_mu_lock(&w->mu); - switch (w->phase) { - case WAITING: - case READY_TO_CALL_BACK: - GPR_UNREACHABLE_CODE(return ); - case CALLING_BACK_AND_FINISHED: - should_delete = true; - break; +class StateWatcher { + public: + StateWatcher(grpc_channel* channel, grpc_completion_queue* cq, void* tag, + grpc_connectivity_state last_observed_state, + gpr_timespec deadline) + : channel_(channel), cq_(cq), tag_(tag), state_(last_observed_state) { + GPR_ASSERT(grpc_cq_begin_op(cq, tag)); + GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity"); + GRPC_CLOSURE_INIT(&on_complete_, WatchComplete, this, nullptr); + GRPC_CLOSURE_INIT(&on_timeout_, TimeoutComplete, this, nullptr); + auto* watcher_timer_init_state = new WatcherTimerInitState( + this, grpc_timespec_to_millis_round_up(deadline)); + ClientChannel* client_channel = ClientChannel::GetFromChannel(channel); + GPR_ASSERT(client_channel != nullptr); + client_channel->AddExternalConnectivityWatcher( + grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)), &state_, + &on_complete_, watcher_timer_init_state->closure()); } - gpr_mu_unlock(&w->mu); - if (should_delete) { - delete_state_watcher(w); + ~StateWatcher() { + GRPC_CHANNEL_INTERNAL_UNREF(channel_, "watch_channel_connectivity"); } -} - -static void partly_done(state_watcher* w, bool due_to_completion, - grpc_error* error) { - bool end_op = false; - void* end_op_tag = nullptr; - grpc_error* end_op_error = nullptr; - grpc_completion_queue* end_op_cq = nullptr; - grpc_cq_completion* end_op_completion_storage = nullptr; - if (due_to_completion) { - grpc_timer_cancel(&w->alarm); - } else { - grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element( - grpc_channel_get_channel_stack(w->channel)); - grpc_client_channel_watch_connectivity_state( - client_channel_elem, - grpc_polling_entity_create_from_pollset(grpc_cq_pollset(w->cq)), - nullptr, &w->on_complete, nullptr); - } + private: + // A fire-and-forget object used to delay starting the timer until the + // ClientChannel actually starts the watch. + class WatcherTimerInitState { + public: + WatcherTimerInitState(StateWatcher* state_watcher, grpc_millis deadline) + : state_watcher_(state_watcher), deadline_(deadline) { + GRPC_CLOSURE_INIT(&closure_, WatcherTimerInit, this, nullptr); + } - gpr_mu_lock(&w->mu); + grpc_closure* closure() { return &closure_; } - if (due_to_completion) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures)) { - GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error)); + private: + static void WatcherTimerInit(void* arg, grpc_error_handle /*error*/) { + auto* self = static_cast(arg); + grpc_timer_init(&self->state_watcher_->timer_, self->deadline_, + &self->state_watcher_->on_timeout_); + delete self; } - GRPC_ERROR_UNREF(error); - error = GRPC_ERROR_NONE; - } else { - if (error == GRPC_ERROR_NONE) { - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Timed out waiting for connection state change"); - } else if (error == GRPC_ERROR_CANCELLED) { - error = GRPC_ERROR_NONE; + + StateWatcher* state_watcher_; + grpc_millis deadline_; + grpc_closure closure_; + }; + + enum CallbackPhase { kWaiting, kReadyToCallBack, kCallingBackAndFinished }; + + // Called when the completion is returned to the CQ. + static void FinishedCompletion(void* arg, grpc_cq_completion* /*ignored*/) { + auto* self = static_cast(arg); + bool should_delete = false; + { + MutexLock lock(&self->mu_); + switch (self->phase_) { + case kWaiting: + case kReadyToCallBack: + GPR_UNREACHABLE_CODE(return ); + case kCallingBackAndFinished: + should_delete = true; + } } + if (should_delete) delete self; } - switch (w->phase) { - case WAITING: - GRPC_ERROR_REF(error); - w->error = error; - w->phase = READY_TO_CALL_BACK; - break; - case READY_TO_CALL_BACK: - if (error != GRPC_ERROR_NONE) { - GPR_ASSERT(!due_to_completion); - GRPC_ERROR_UNREF(w->error); - GRPC_ERROR_REF(error); - w->error = error; + + void PartlyDone(bool due_to_completion, grpc_error_handle error) { + bool end_op = false; + void* end_op_tag = nullptr; + grpc_error_handle end_op_error = GRPC_ERROR_NONE; + grpc_completion_queue* end_op_cq = nullptr; + grpc_cq_completion* end_op_completion_storage = nullptr; + if (due_to_completion) { + grpc_timer_cancel(&timer_); + } else { + grpc_core::ClientChannel* client_channel = + grpc_core::ClientChannel::GetFromChannel(channel_); + GPR_ASSERT(client_channel != nullptr); + client_channel->CancelExternalConnectivityWatcher(&on_complete_); + } + { + MutexLock lock(&mu_); + if (due_to_completion) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures)) { + GRPC_LOG_IF_ERROR("watch_completion_error", GRPC_ERROR_REF(error)); + } + GRPC_ERROR_UNREF(error); + error = GRPC_ERROR_NONE; + } else { + if (error == GRPC_ERROR_NONE) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Timed out waiting for connection state change"); + } else if (error == GRPC_ERROR_CANCELLED) { + error = GRPC_ERROR_NONE; + } + } + switch (phase_) { + case kWaiting: + GRPC_ERROR_REF(error); + error_ = error; + phase_ = kReadyToCallBack; + break; + case kReadyToCallBack: + if (error != GRPC_ERROR_NONE) { + GPR_ASSERT(!due_to_completion); + GRPC_ERROR_UNREF(error_); + GRPC_ERROR_REF(error); + error_ = error; + } + phase_ = kCallingBackAndFinished; + end_op = true; + end_op_cq = cq_; + end_op_tag = tag_; + end_op_error = error_; + end_op_completion_storage = &completion_storage_; + break; + case kCallingBackAndFinished: + GPR_UNREACHABLE_CODE(return ); } - w->phase = CALLING_BACK_AND_FINISHED; - end_op = true; - end_op_cq = w->cq; - end_op_tag = w->tag; - end_op_error = w->error; - end_op_completion_storage = &w->completion_storage; - break; - case CALLING_BACK_AND_FINISHED: - GPR_UNREACHABLE_CODE(return ); - break; + } + if (end_op) { + grpc_cq_end_op(end_op_cq, end_op_tag, end_op_error, FinishedCompletion, + this, end_op_completion_storage); + } + GRPC_ERROR_UNREF(error); } - gpr_mu_unlock(&w->mu); - if (end_op) { - grpc_cq_end_op(end_op_cq, end_op_tag, end_op_error, finished_completion, w, - end_op_completion_storage); + static void WatchComplete(void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + self->PartlyDone(/*due_to_completion=*/true, GRPC_ERROR_REF(error)); } - GRPC_ERROR_UNREF(error); -} - -static void watch_complete(void* pw, grpc_error* error) { - partly_done(static_cast(pw), true, GRPC_ERROR_REF(error)); -} + static void TimeoutComplete(void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + self->PartlyDone(/*due_to_completion=*/false, GRPC_ERROR_REF(error)); + } -static void timeout_complete(void* pw, grpc_error* error) { - partly_done(static_cast(pw), false, GRPC_ERROR_REF(error)); -} + grpc_channel* channel_; + grpc_completion_queue* cq_; + void* tag_; -int grpc_channel_num_external_connectivity_watchers(grpc_channel* channel) { - grpc_channel_element* client_channel_elem = - grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); - return grpc_client_channel_num_external_connectivity_watchers( - client_channel_elem); -} + grpc_connectivity_state state_; -typedef struct watcher_timer_init_arg { - state_watcher* w; - gpr_timespec deadline; -} watcher_timer_init_arg; + grpc_cq_completion completion_storage_; -static void watcher_timer_init(void* arg, grpc_error* /*error_ignored*/) { - watcher_timer_init_arg* wa = static_cast(arg); + grpc_closure on_complete_; + grpc_timer timer_; + grpc_closure on_timeout_; - grpc_timer_init(&wa->w->alarm, grpc_timespec_to_millis_round_up(wa->deadline), - &wa->w->on_timeout); - gpr_free(wa); -} + Mutex mu_; + CallbackPhase phase_ ABSL_GUARDED_BY(mu_) = kWaiting; + grpc_error_handle error_ ABSL_GUARDED_BY(mu_) = GRPC_ERROR_NONE; +}; -int grpc_channel_support_connectivity_watcher(grpc_channel* channel) { - grpc_channel_element* client_channel_elem = - grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); - return client_channel_elem->filter != &grpc_client_channel_filter ? 0 : 1; -} +} // namespace +} // namespace grpc_core void grpc_channel_watch_connectivity_state( grpc_channel* channel, grpc_connectivity_state last_observed_state, gpr_timespec deadline, grpc_completion_queue* cq, void* tag) { - grpc_channel_element* client_channel_elem = - grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; - state_watcher* w = static_cast(gpr_malloc(sizeof(*w))); - GRPC_API_TRACE( "grpc_channel_watch_connectivity_state(" "channel=%p, last_observed_state=%d, " @@ -230,35 +235,5 @@ void grpc_channel_watch_connectivity_state( 7, (channel, (int)last_observed_state, deadline.tv_sec, deadline.tv_nsec, (int)deadline.clock_type, cq, tag)); - - GPR_ASSERT(grpc_cq_begin_op(cq, tag)); - - gpr_mu_init(&w->mu); - GRPC_CLOSURE_INIT(&w->on_complete, watch_complete, w, - grpc_schedule_on_exec_ctx); - GRPC_CLOSURE_INIT(&w->on_timeout, timeout_complete, w, - grpc_schedule_on_exec_ctx); - w->phase = WAITING; - w->state = last_observed_state; - w->cq = cq; - w->tag = tag; - w->channel = channel; - w->error = nullptr; - - watcher_timer_init_arg* wa = static_cast( - gpr_malloc(sizeof(watcher_timer_init_arg))); - wa->w = w; - wa->deadline = deadline; - GRPC_CLOSURE_INIT(&w->watcher_timer_init, watcher_timer_init, wa, - grpc_schedule_on_exec_ctx); - - if (client_channel_elem->filter == &grpc_client_channel_filter) { - GRPC_CHANNEL_INTERNAL_REF(channel, "watch_channel_connectivity"); - grpc_client_channel_watch_connectivity_state( - client_channel_elem, - grpc_polling_entity_create_from_pollset(grpc_cq_pollset(cq)), &w->state, - &w->on_complete, &w->watcher_timer_init); - } else { - abort(); - } + new grpc_core::StateWatcher(channel, cq, tag, last_observed_state, deadline); } diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc index 455e1460c4f..3bbec5eaadc 100644 --- a/src/core/ext/filters/client_channel/client_channel.cc +++ b/src/core/ext/filters/client_channel/client_channel.cc @@ -51,7 +51,7 @@ #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/resolver_result_parsing.h" -#include "src/core/ext/filters/client_channel/retry_throttle.h" +#include "src/core/ext/filters/client_channel/retry_filter.h" #include "src/core/ext/filters/client_channel/service_config.h" #include "src/core/ext/filters/client_channel/service_config_call_data.h" #include "src/core/ext/filters/client_channel/subchannel.h" @@ -61,7 +61,6 @@ #include "src/core/lib/channel/connected_channel.h" #include "src/core/lib/channel/status_util.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" @@ -81,335 +80,23 @@ // Client channel filter // -// By default, we buffer 256 KiB per RPC for retries. -// TODO(roth): Do we have any data to suggest a better value? -#define DEFAULT_PER_RPC_RETRY_BUFFER_SIZE (256 << 10) - -// This value was picked arbitrarily. It can be changed if there is -// any even moderately compelling reason to do so. -#define RETRY_BACKOFF_JITTER 0.2 - -// Max number of batches that can be pending on a call at any given -// time. This includes one batch for each of the following ops: -// recv_initial_metadata -// send_initial_metadata -// recv_message -// send_message -// recv_trailing_metadata -// send_trailing_metadata -#define MAX_PENDING_BATCHES 6 - -// Channel arg containing a pointer to the ChannelData object. -#define GRPC_ARG_CLIENT_CHANNEL_DATA "grpc.internal.client_channel_data" - -// Channel arg containing a pointer to the RetryThrottleData object. -#define GRPC_ARG_RETRY_THROTTLE_DATA "grpc.internal.retry_throttle_data" - namespace grpc_core { using internal::ClientChannelGlobalParsedConfig; using internal::ClientChannelMethodParsedConfig; using internal::ClientChannelServiceConfigParser; -using internal::ServerRetryThrottleData; TraceFlag grpc_client_channel_call_trace(false, "client_channel_call"); TraceFlag grpc_client_channel_routing_trace(false, "client_channel_routing"); -namespace { - -// -// ChannelData definition -// - -class LoadBalancedCall; - -class ChannelData { - public: - struct ResolverQueuedCall { - grpc_call_element* elem; - ResolverQueuedCall* next = nullptr; - }; - struct LbQueuedCall { - LoadBalancedCall* lb_call; - LbQueuedCall* next = nullptr; - }; - - static grpc_error* Init(grpc_channel_element* elem, - grpc_channel_element_args* args); - static void Destroy(grpc_channel_element* elem); - static void StartTransportOp(grpc_channel_element* elem, - grpc_transport_op* op); - static void GetChannelInfo(grpc_channel_element* elem, - const grpc_channel_info* info); - - bool deadline_checking_enabled() const { return deadline_checking_enabled_; } - bool enable_retries() const { return enable_retries_; } - size_t per_rpc_retry_buffer_size() const { - return per_rpc_retry_buffer_size_; - } - grpc_channel_stack* owning_stack() const { return owning_stack_; } - - // Note: Does NOT return a new ref. - grpc_error* disconnect_error() const { - return disconnect_error_.Load(MemoryOrder::ACQUIRE); - } - - Mutex* resolution_mu() const { return &resolution_mu_; } - // These methods all require holding resolution_mu_. - void AddResolverQueuedCall(ResolverQueuedCall* call, - grpc_polling_entity* pollent); - void RemoveResolverQueuedCall(ResolverQueuedCall* to_remove, - grpc_polling_entity* pollent); - bool received_service_config_data() const { - return received_service_config_data_; - } - grpc_error* resolver_transient_failure_error() const { - return resolver_transient_failure_error_; - } - RefCountedPtr service_config() const { - return service_config_; - } - ConfigSelector* config_selector() const { return config_selector_.get(); } - RefCountedPtr dynamic_filters() const { - return dynamic_filters_; - } - - Mutex* data_plane_mu() const { return &data_plane_mu_; } - // These methods all require holding data_plane_mu_. - LoadBalancingPolicy::SubchannelPicker* picker() const { - return picker_.get(); - } - void AddLbQueuedCall(LbQueuedCall* call, grpc_polling_entity* pollent); - void RemoveLbQueuedCall(LbQueuedCall* to_remove, - grpc_polling_entity* pollent); - RefCountedPtr GetConnectedSubchannelInDataPlane( - SubchannelInterface* subchannel) const; - - WorkSerializer* work_serializer() const { return work_serializer_.get(); } - - grpc_connectivity_state CheckConnectivityState(bool try_to_connect); - - void AddExternalConnectivityWatcher(grpc_polling_entity pollent, - grpc_connectivity_state* state, - grpc_closure* on_complete, - grpc_closure* watcher_timer_init) { - new ExternalConnectivityWatcher(this, pollent, state, on_complete, - watcher_timer_init); - } - - void RemoveExternalConnectivityWatcher(grpc_closure* on_complete, - bool cancel) { - ExternalConnectivityWatcher::RemoveWatcherFromExternalWatchersMap( - this, on_complete, cancel); - } - - int NumExternalConnectivityWatchers() const { - MutexLock lock(&external_watchers_mu_); - return static_cast(external_watchers_.size()); - } - - void AddConnectivityWatcher( - grpc_connectivity_state initial_state, - OrphanablePtr watcher); - void RemoveConnectivityWatcher( - AsyncConnectivityStateWatcherInterface* watcher); - - private: - class SubchannelWrapper; - class ClientChannelControlHelper; - class ConnectivityWatcherAdder; - class ConnectivityWatcherRemover; - - // Represents a pending connectivity callback from an external caller - // via grpc_client_channel_watch_connectivity_state(). - class ExternalConnectivityWatcher : public ConnectivityStateWatcherInterface { - public: - ExternalConnectivityWatcher(ChannelData* chand, grpc_polling_entity pollent, - grpc_connectivity_state* state, - grpc_closure* on_complete, - grpc_closure* watcher_timer_init); - - ~ExternalConnectivityWatcher() override; - - // Removes the watcher from the external_watchers_ map. - static void RemoveWatcherFromExternalWatchersMap(ChannelData* chand, - grpc_closure* on_complete, - bool cancel); - - void Notify(grpc_connectivity_state state, - const absl::Status& /* status */) override; - - void Cancel(); - - private: - // Adds the watcher to state_tracker_. Consumes the ref that is passed to it - // from Start(). - void AddWatcherLocked(); - void RemoveWatcherLocked(); - - ChannelData* chand_; - grpc_polling_entity pollent_; - grpc_connectivity_state initial_state_; - grpc_connectivity_state* state_; - grpc_closure* on_complete_; - grpc_closure* watcher_timer_init_; - Atomic done_{false}; - }; - - class ResolverResultHandler : public Resolver::ResultHandler { - public: - explicit ResolverResultHandler(ChannelData* chand) : chand_(chand) { - GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ResolverResultHandler"); - } - - ~ResolverResultHandler() override { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log(GPR_INFO, "chand=%p: resolver shutdown complete", chand_); - } - GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ResolverResultHandler"); - } - - void ReturnResult(Resolver::Result result) override { - chand_->OnResolverResultChangedLocked(std::move(result)); - } - - void ReturnError(grpc_error* error) override { - chand_->OnResolverErrorLocked(error); - } - - private: - ChannelData* chand_; - }; - - ChannelData(grpc_channel_element_args* args, grpc_error** error); - ~ChannelData(); - - // Note: All methods with "Locked" suffix must be invoked from within - // work_serializer_. - - void OnResolverResultChangedLocked(Resolver::Result result); - void OnResolverErrorLocked(grpc_error* error); - - void CreateOrUpdateLbPolicyLocked( - RefCountedPtr lb_policy_config, - Resolver::Result result); - OrphanablePtr CreateLbPolicyLocked( - const grpc_channel_args& args); - - void UpdateStateAndPickerLocked( - grpc_connectivity_state state, const absl::Status& status, - const char* reason, - std::unique_ptr picker); - - void UpdateServiceConfigInControlPlaneLocked( - RefCountedPtr service_config, - RefCountedPtr config_selector, - const internal::ClientChannelGlobalParsedConfig* parsed_service_config, - const char* lb_policy_name); - - void UpdateServiceConfigInDataPlaneLocked(); - - void CreateResolverLocked(); - void DestroyResolverAndLbPolicyLocked(); - - grpc_error* DoPingLocked(grpc_transport_op* op); - - void StartTransportOpLocked(grpc_transport_op* op); - - void TryToConnectLocked(); - - // - // Fields set at construction and never modified. - // - const bool deadline_checking_enabled_; - const bool enable_retries_; - const size_t per_rpc_retry_buffer_size_; - grpc_channel_stack* owning_stack_; - ClientChannelFactory* client_channel_factory_; - const grpc_channel_args* channel_args_; - RefCountedPtr default_service_config_; - std::string server_name_; - UniquePtr target_uri_; - channelz::ChannelNode* channelz_node_; - - // - // Fields related to name resolution. Guarded by resolution_mu_. - // - mutable Mutex resolution_mu_; - // Linked list of calls queued waiting for resolver result. - ResolverQueuedCall* resolver_queued_calls_ = nullptr; - // Data from service config. - grpc_error* resolver_transient_failure_error_ = GRPC_ERROR_NONE; - bool received_service_config_data_ = false; - RefCountedPtr service_config_; - RefCountedPtr config_selector_; - RefCountedPtr dynamic_filters_; - - // - // Fields used in the data plane. Guarded by data_plane_mu_. - // - mutable Mutex data_plane_mu_; - std::unique_ptr picker_; - // Linked list of calls queued waiting for LB pick. - LbQueuedCall* lb_queued_calls_ = nullptr; - - // - // Fields used in the control plane. Guarded by work_serializer. - // - std::shared_ptr work_serializer_; - grpc_pollset_set* interested_parties_; - ConnectivityStateTracker state_tracker_; - OrphanablePtr resolver_; - bool previous_resolution_contained_addresses_ = false; - RefCountedPtr saved_service_config_; - RefCountedPtr saved_config_selector_; - absl::optional health_check_service_name_; - OrphanablePtr lb_policy_; - RefCountedPtr subchannel_pool_; - // The number of SubchannelWrapper instances referencing a given Subchannel. - std::map subchannel_refcount_map_; - // The set of SubchannelWrappers that currently exist. - // No need to hold a ref, since the map is updated in the control-plane - // work_serializer when the SubchannelWrappers are created and destroyed. - std::set subchannel_wrappers_; - // Pending ConnectedSubchannel updates for each SubchannelWrapper. - // Updates are queued here in the control plane work_serializer and then - // applied in the data plane mutex when the picker is updated. - std::map, RefCountedPtr> - pending_subchannel_updates_; - int keepalive_time_ = -1; - - // - // Fields accessed from both data plane mutex and control plane - // work_serializer. - // - Atomic disconnect_error_; - - // - // Fields guarded by a mutex, since they need to be accessed - // synchronously via get_channel_info(). - // - Mutex info_mu_; - UniquePtr info_lb_policy_name_; - UniquePtr info_service_config_json_; - - // - // Fields guarded by a mutex, since they need to be accessed - // synchronously via grpc_channel_num_external_connectivity_watchers(). - // - mutable Mutex external_watchers_mu_; - std::map> - external_watchers_; -}; - // -// CallData definition +// ClientChannel::CallData definition // -class CallData { +class ClientChannel::CallData { public: - static grpc_error* Init(grpc_call_element* elem, - const grpc_call_element_args* args); + static grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args); static void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* then_schedule_closure); @@ -418,22 +105,23 @@ class CallData { static void SetPollent(grpc_call_element* elem, grpc_polling_entity* pollent); // Invoked by channel for queued calls when name resolution is completed. - static void CheckResolution(void* arg, grpc_error* error); + static void CheckResolution(void* arg, grpc_error_handle error); // Helper function for applying the service config to a call while - // holding ChannelData::resolution_mu_. + // holding ClientChannel::resolution_mu_. // Returns true if the service config has been applied to the call, in which // case the caller must invoke ResolutionDone() or AsyncResolutionDone() // with the returned error. - bool CheckResolutionLocked(grpc_call_element* elem, grpc_error** error); + bool CheckResolutionLocked(grpc_call_element* elem, grpc_error_handle* error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_); // Schedules a callback to continue processing the call once // resolution is complete. The callback will not run until after this // method returns. - void AsyncResolutionDone(grpc_call_element* elem, grpc_error* error); + void AsyncResolutionDone(grpc_call_element* elem, grpc_error_handle error); private: class ResolverQueuedCallCanceller; - CallData(grpc_call_element* elem, const ChannelData& chand, + CallData(grpc_call_element* elem, const ClientChannel& chand, const grpc_call_element_args& args); ~CallData(); @@ -441,7 +129,8 @@ class CallData { static size_t GetBatchIndex(grpc_transport_stream_op_batch* batch); void PendingBatchesAdd(grpc_call_element* elem, grpc_transport_stream_op_batch* batch); - static void FailPendingBatchInCallCombiner(void* arg, grpc_error* error); + static void FailPendingBatchInCallCombiner(void* arg, + grpc_error_handle error); // A predicate type and some useful implementations for PendingBatchesFail(). typedef bool (*YieldCallCombinerPredicate)( const CallCombinerClosureList& closures); @@ -459,9 +148,10 @@ class CallData { // If yield_call_combiner_predicate returns true, assumes responsibility for // yielding the call combiner. void PendingBatchesFail( - grpc_call_element* elem, grpc_error* error, + grpc_call_element* elem, grpc_error_handle error, YieldCallCombinerPredicate yield_call_combiner_predicate); - static void ResumePendingBatchInCallCombiner(void* arg, grpc_error* ignored); + static void ResumePendingBatchInCallCombiner(void* arg, + grpc_error_handle ignored); // Resumes all pending batches on lb_call_. void PendingBatchesResume(grpc_call_element* elem); @@ -469,20 +159,23 @@ class CallData { // that the resolver has returned results to the channel. // If an error is returned, the error indicates the status with which // the call should be failed. - grpc_error* ApplyServiceConfigToCallLocked( - grpc_call_element* elem, grpc_metadata_batch* initial_metadata); + grpc_error_handle ApplyServiceConfigToCallLocked( + grpc_call_element* elem, grpc_metadata_batch* initial_metadata) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_); // Invoked when the resolver result is applied to the caller, on both // success or failure. - static void ResolutionDone(void* arg, grpc_error* error); + static void ResolutionDone(void* arg, grpc_error_handle error); // Removes the call (if present) from the channel's list of calls queued // for name resolution. - void MaybeRemoveCallFromResolverQueuedCallsLocked(grpc_call_element* elem); + void MaybeRemoveCallFromResolverQueuedCallsLocked(grpc_call_element* elem) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_); // Adds the call (if not already present) to the channel's list of // calls queued for name resolution. - void MaybeAddCallToResolverQueuedCallsLocked(grpc_call_element* elem); + void MaybeAddCallToResolverQueuedCallsLocked(grpc_call_element* elem) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::resolution_mu_); static void RecvInitialMetadataReadyForConfigSelectorCommitCallback( - void* arg, grpc_error* error); + void* arg, grpc_error_handle error); void InjectRecvInitialMetadataReadyForConfigSelectorCommitCallback( grpc_transport_stream_op_batch* batch); @@ -508,11 +201,15 @@ class CallData { grpc_closure pick_closure_; - // Accessed while holding ChannelData::resolution_mu_. - bool service_config_applied_ = false; - bool queued_pending_resolver_result_ = false; - ChannelData::ResolverQueuedCall resolver_queued_call_; - ResolverQueuedCallCanceller* resolver_call_canceller_ = nullptr; + // Accessed while holding ClientChannel::resolution_mu_. + bool service_config_applied_ ABSL_GUARDED_BY(&ClientChannel::resolution_mu_) = + false; + bool queued_pending_resolver_result_ + ABSL_GUARDED_BY(&ClientChannel::resolution_mu_) = false; + ClientChannel::ResolverQueuedCall resolver_queued_call_ + ABSL_GUARDED_BY(&ClientChannel::resolution_mu_); + ResolverQueuedCallCanceller* resolver_call_canceller_ + ABSL_GUARDED_BY(&ClientChannel::resolution_mu_) = nullptr; std::function on_call_committed_; @@ -530,552 +227,72 @@ class CallData { grpc_transport_stream_op_batch* pending_batches_[MAX_PENDING_BATCHES] = {}; // Set when we get a cancel_stream op. - grpc_error* cancel_error_ = GRPC_ERROR_NONE; -}; - -// -// RetryingCall definition -// - -class RetryingCall { - public: - RetryingCall( - ChannelData* chand, const grpc_call_element_args& args, - grpc_polling_entity* pollent, - RefCountedPtr retry_throttle_data, - const ClientChannelMethodParsedConfig::RetryPolicy* retry_policy); - ~RetryingCall(); - - void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); - - RefCountedPtr subchannel_call() const; - - private: - // State used for starting a retryable batch on a subchannel call. - // This provides its own grpc_transport_stream_op_batch and other data - // structures needed to populate the ops in the batch. - // We allocate one struct on the arena for each attempt at starting a - // batch on a given subchannel call. - struct SubchannelCallBatchData { - // Creates a SubchannelCallBatchData object on the call's arena with the - // specified refcount. If set_on_complete is true, the batch's - // on_complete callback will be set to point to on_complete(); - // otherwise, the batch's on_complete callback will be null. - static SubchannelCallBatchData* Create(RetryingCall* call, int refcount, - bool set_on_complete); - - void Unref() { - if (gpr_unref(&refs)) Destroy(); - } - - SubchannelCallBatchData(RetryingCall* call, int refcount, - bool set_on_complete); - // All dtor code must be added in `Destroy()`. This is because we may - // call closures in `SubchannelCallBatchData` after they are unrefed by - // `Unref()`, and msan would complain about accessing this class - // after calling dtor. As a result we cannot call the `dtor` in `Unref()`. - // TODO(soheil): We should try to call the dtor in `Unref()`. - ~SubchannelCallBatchData() { Destroy(); } - void Destroy(); - - gpr_refcount refs; - grpc_call_element* elem; - RetryingCall* call; - RefCountedPtr lb_call; - // The batch to use in the subchannel call. - // Its payload field points to SubchannelCallRetryState::batch_payload. - grpc_transport_stream_op_batch batch; - // For intercepting on_complete. - grpc_closure on_complete; - }; - - // Retry state associated with a subchannel call. - // Stored in the parent_data of the subchannel call object. - struct SubchannelCallRetryState { - explicit SubchannelCallRetryState(grpc_call_context_element* context) - : batch_payload(context), - started_send_initial_metadata(false), - completed_send_initial_metadata(false), - started_send_trailing_metadata(false), - completed_send_trailing_metadata(false), - started_recv_initial_metadata(false), - completed_recv_initial_metadata(false), - started_recv_trailing_metadata(false), - completed_recv_trailing_metadata(false), - retry_dispatched(false) {} - - // SubchannelCallBatchData.batch.payload points to this. - grpc_transport_stream_op_batch_payload batch_payload; - // For send_initial_metadata. - // Note that we need to make a copy of the initial metadata for each - // subchannel call instead of just referring to the copy in call_data, - // because filters in the subchannel stack will probably add entries, - // so we need to start in a pristine state for each attempt of the call. - grpc_linked_mdelem* send_initial_metadata_storage; - grpc_metadata_batch send_initial_metadata; - // For send_message. - // TODO(roth): Restructure this to eliminate use of ManualConstructor. - ManualConstructor send_message; - // For send_trailing_metadata. - grpc_linked_mdelem* send_trailing_metadata_storage; - grpc_metadata_batch send_trailing_metadata; - // For intercepting recv_initial_metadata. - grpc_metadata_batch recv_initial_metadata; - grpc_closure recv_initial_metadata_ready; - bool trailing_metadata_available = false; - // For intercepting recv_message. - grpc_closure recv_message_ready; - OrphanablePtr recv_message; - // For intercepting recv_trailing_metadata. - grpc_metadata_batch recv_trailing_metadata; - grpc_transport_stream_stats collect_stats; - grpc_closure recv_trailing_metadata_ready; - // These fields indicate which ops have been started and completed on - // this subchannel call. - size_t started_send_message_count = 0; - size_t completed_send_message_count = 0; - size_t started_recv_message_count = 0; - size_t completed_recv_message_count = 0; - bool started_send_initial_metadata : 1; - bool completed_send_initial_metadata : 1; - bool started_send_trailing_metadata : 1; - bool completed_send_trailing_metadata : 1; - bool started_recv_initial_metadata : 1; - bool completed_recv_initial_metadata : 1; - bool started_recv_trailing_metadata : 1; - bool completed_recv_trailing_metadata : 1; - // State for callback processing. - SubchannelCallBatchData* recv_initial_metadata_ready_deferred_batch = - nullptr; - grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE; - SubchannelCallBatchData* recv_message_ready_deferred_batch = nullptr; - grpc_error* recv_message_error = GRPC_ERROR_NONE; - SubchannelCallBatchData* recv_trailing_metadata_internal_batch = nullptr; - // NOTE: Do not move this next to the metadata bitfields above. That would - // save space but will also result in a data race because compiler - // will generate a 2 byte store which overwrites the meta-data - // fields upon setting this field. - bool retry_dispatched : 1; - }; - - // Pending batches stored in call data. - struct PendingBatch { - // The pending batch. If nullptr, this slot is empty. - grpc_transport_stream_op_batch* batch = nullptr; - // Indicates whether payload for send ops has been cached in CallData. - bool send_ops_cached = false; - }; - - // Caches data for send ops so that it can be retried later, if not - // already cached. - void MaybeCacheSendOpsForBatch(PendingBatch* pending); - void FreeCachedSendInitialMetadata(); - // Frees cached send_message at index idx. - void FreeCachedSendMessage(size_t idx); - void FreeCachedSendTrailingMetadata(); - // Frees cached send ops that have already been completed after - // committing the call. - void FreeCachedSendOpDataAfterCommit(SubchannelCallRetryState* retry_state); - // Frees cached send ops that were completed by the completed batch in - // batch_data. Used when batches are completed after the call is committed. - void FreeCachedSendOpDataForCompletedBatch( - SubchannelCallBatchData* batch_data, - SubchannelCallRetryState* retry_state); - - // Returns the index into pending_batches_ to be used for batch. - static size_t GetBatchIndex(grpc_transport_stream_op_batch* batch); - void PendingBatchesAdd(grpc_transport_stream_op_batch* batch); - void PendingBatchClear(PendingBatch* pending); - void MaybeClearPendingBatch(PendingBatch* pending); - static void FailPendingBatchInCallCombiner(void* arg, grpc_error* error); - // A predicate type and some useful implementations for PendingBatchesFail(). - typedef bool (*YieldCallCombinerPredicate)( - const CallCombinerClosureList& closures); - static bool YieldCallCombiner(const CallCombinerClosureList& /*closures*/) { - return true; - } - static bool NoYieldCallCombiner(const CallCombinerClosureList& /*closures*/) { - return false; - } - static bool YieldCallCombinerIfPendingBatchesFound( - const CallCombinerClosureList& closures) { - return closures.size() > 0; - } - // Fails all pending batches. - // If yield_call_combiner_predicate returns true, assumes responsibility for - // yielding the call combiner. - void PendingBatchesFail( - grpc_error* error, - YieldCallCombinerPredicate yield_call_combiner_predicate); - static void ResumePendingBatchInCallCombiner(void* arg, grpc_error* ignored); - // Resumes all pending batches on lb_call_. - void PendingBatchesResume(); - // Returns a pointer to the first pending batch for which predicate(batch) - // returns true, or null if not found. - template - PendingBatch* PendingBatchFind(const char* log_message, Predicate predicate); - - // Commits the call so that no further retry attempts will be performed. - void RetryCommit(SubchannelCallRetryState* retry_state); - // Starts a retry after appropriate back-off. - void DoRetry(SubchannelCallRetryState* retry_state, - grpc_millis server_pushback_ms); - // Returns true if the call is being retried. - bool MaybeRetry(SubchannelCallBatchData* batch_data, grpc_status_code status, - grpc_mdelem* server_pushback_md); - - // Invokes recv_initial_metadata_ready for a subchannel batch. - static void InvokeRecvInitialMetadataCallback(void* arg, grpc_error* error); - // Intercepts recv_initial_metadata_ready callback for retries. - // Commits the call and returns the initial metadata up the stack. - static void RecvInitialMetadataReady(void* arg, grpc_error* error); - - // Invokes recv_message_ready for a subchannel batch. - static void InvokeRecvMessageCallback(void* arg, grpc_error* error); - // Intercepts recv_message_ready callback for retries. - // Commits the call and returns the message up the stack. - static void RecvMessageReady(void* arg, grpc_error* error); - - // Sets *status and *server_pushback_md based on md_batch and error. - // Only sets *server_pushback_md if server_pushback_md != nullptr. - void GetCallStatus(grpc_metadata_batch* md_batch, grpc_error* error, - grpc_status_code* status, - grpc_mdelem** server_pushback_md); - // Adds recv_trailing_metadata_ready closure to closures. - void AddClosureForRecvTrailingMetadataReady( - SubchannelCallBatchData* batch_data, grpc_error* error, - CallCombinerClosureList* closures); - // Adds any necessary closures for deferred recv_initial_metadata and - // recv_message callbacks to closures. - static void AddClosuresForDeferredRecvCallbacks( - SubchannelCallBatchData* batch_data, - SubchannelCallRetryState* retry_state, CallCombinerClosureList* closures); - // Returns true if any op in the batch was not yet started. - // Only looks at send ops, since recv ops are always started immediately. - bool PendingBatchIsUnstarted(PendingBatch* pending, - SubchannelCallRetryState* retry_state); - // For any pending batch containing an op that has not yet been started, - // adds the pending batch's completion closures to closures. - void AddClosuresToFailUnstartedPendingBatches( - SubchannelCallRetryState* retry_state, grpc_error* error, - CallCombinerClosureList* closures); - // Runs necessary closures upon completion of a call attempt. - void RunClosuresForCompletedCall(SubchannelCallBatchData* batch_data, - grpc_error* error); - // Intercepts recv_trailing_metadata_ready callback for retries. - // Commits the call and returns the trailing metadata up the stack. - static void RecvTrailingMetadataReady(void* arg, grpc_error* error); - - // Adds the on_complete closure for the pending batch completed in - // batch_data to closures. - void AddClosuresForCompletedPendingBatch(SubchannelCallBatchData* batch_data, - grpc_error* error, - CallCombinerClosureList* closures); - - // If there are any cached ops to replay or pending ops to start on the - // subchannel call, adds a closure to closures to invoke - // StartRetriableSubchannelBatches(). - void AddClosuresForReplayOrPendingSendOps( - SubchannelCallBatchData* batch_data, - SubchannelCallRetryState* retry_state, CallCombinerClosureList* closures); - - // Callback used to intercept on_complete from subchannel calls. - // Called only when retries are enabled. - static void OnComplete(void* arg, grpc_error* error); - - static void StartBatchInCallCombiner(void* arg, grpc_error* ignored); - // Adds a closure to closures that will execute batch in the call combiner. - void AddClosureForSubchannelBatch(grpc_transport_stream_op_batch* batch, - CallCombinerClosureList* closures); - // Adds retriable send_initial_metadata op to batch_data. - void AddRetriableSendInitialMetadataOp(SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data); - // Adds retriable send_message op to batch_data. - void AddRetriableSendMessageOp(SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data); - // Adds retriable send_trailing_metadata op to batch_data. - void AddRetriableSendTrailingMetadataOp(SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data); - // Adds retriable recv_initial_metadata op to batch_data. - void AddRetriableRecvInitialMetadataOp(SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data); - // Adds retriable recv_message op to batch_data. - void AddRetriableRecvMessageOp(SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data); - // Adds retriable recv_trailing_metadata op to batch_data. - void AddRetriableRecvTrailingMetadataOp(SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data); - // Helper function used to start a recv_trailing_metadata batch. This - // is used in the case where a recv_initial_metadata or recv_message - // op fails in a way that we know the call is over but when the application - // has not yet started its own recv_trailing_metadata op. - void StartInternalRecvTrailingMetadata(); - // If there are any cached send ops that need to be replayed on the - // current subchannel call, creates and returns a new subchannel batch - // to replay those ops. Otherwise, returns nullptr. - SubchannelCallBatchData* MaybeCreateSubchannelBatchForReplay( - SubchannelCallRetryState* retry_state); - // Adds subchannel batches for pending batches to closures. - void AddSubchannelBatchesForPendingBatches( - SubchannelCallRetryState* retry_state, CallCombinerClosureList* closures); - // Constructs and starts whatever subchannel batches are needed on the - // subchannel call. - static void StartRetriableSubchannelBatches(void* arg, grpc_error* ignored); - - static void CreateLbCall(void* arg, grpc_error* error); - - ChannelData* chand_; - grpc_polling_entity* pollent_; - RefCountedPtr retry_throttle_data_; - const ClientChannelMethodParsedConfig::RetryPolicy* retry_policy_ = nullptr; - BackOff retry_backoff_; - - grpc_slice path_; // Request path. - gpr_cycle_counter call_start_time_; - grpc_millis deadline_; - Arena* arena_; - grpc_call_stack* owning_call_; - CallCombiner* call_combiner_; - grpc_call_context_element* call_context_; - - grpc_closure retry_closure_; - - RefCountedPtr lb_call_; - - // Batches are added to this list when received from above. - // They are removed when we are done handling the batch (i.e., when - // either we have invoked all of the batch's callbacks or we have - // passed the batch down to the LB call and are not intercepting any of - // its callbacks). - // TODO(roth): Now that the retry code is split out into its own call - // object, revamp this to work in a cleaner way, since we no longer need - // for batches to ever wait for name resolution or LB picks. - PendingBatch pending_batches_[MAX_PENDING_BATCHES]; - bool pending_send_initial_metadata_ : 1; - bool pending_send_message_ : 1; - bool pending_send_trailing_metadata_ : 1; - - // Set when we get a cancel_stream op. - grpc_error* cancel_error_ = GRPC_ERROR_NONE; - - // Retry state. - bool enable_retries_ : 1; - bool retry_committed_ : 1; - bool last_attempt_got_server_pushback_ : 1; - int num_attempts_completed_ = 0; - size_t bytes_buffered_for_retry_ = 0; - grpc_timer retry_timer_; - - // The number of pending retriable subchannel batches containing send ops. - // We hold a ref to the call stack while this is non-zero, since replay - // batches may not complete until after all callbacks have been returned - // to the surface, and we need to make sure that the call is not destroyed - // until all of these batches have completed. - // Note that we actually only need to track replay batches, but it's - // easier to track all batches with send ops. - int num_pending_retriable_subchannel_send_batches_ = 0; - - // Cached data for retrying send ops. - // send_initial_metadata - bool seen_send_initial_metadata_ = false; - grpc_linked_mdelem* send_initial_metadata_storage_ = nullptr; - grpc_metadata_batch send_initial_metadata_; - uint32_t send_initial_metadata_flags_; - gpr_atm* peer_string_; - // send_message - // When we get a send_message op, we replace the original byte stream - // with a CachingByteStream that caches the slices to a local buffer for - // use in retries. - // Note: We inline the cache for the first 3 send_message ops and use - // dynamic allocation after that. This number was essentially picked - // at random; it could be changed in the future to tune performance. - absl::InlinedVector send_messages_; - // send_trailing_metadata - bool seen_send_trailing_metadata_ = false; - grpc_linked_mdelem* send_trailing_metadata_storage_ = nullptr; - grpc_metadata_batch send_trailing_metadata_; + grpc_error_handle cancel_error_ = GRPC_ERROR_NONE; }; // -// LoadBalancedCall definition +// Filter vtable // -// This object is ref-counted, but it cannot inherit from RefCounted<>, -// because it is allocated on the arena and can't free its memory when -// its refcount goes to zero. So instead, it manually implements the -// same API as RefCounted<>, so that it can be used with RefCountedPtr<>. -class LoadBalancedCall { - public: - static RefCountedPtr Create( - ChannelData* chand, const grpc_call_element_args& args, - grpc_polling_entity* pollent, size_t parent_data_size); - - LoadBalancedCall(ChannelData* chand, const grpc_call_element_args& args, - grpc_polling_entity* pollent); - ~LoadBalancedCall(); - - // Interface of RefCounted<>. - RefCountedPtr Ref() GRPC_MUST_USE_RESULT; - RefCountedPtr Ref(const DebugLocation& location, - const char* reason) GRPC_MUST_USE_RESULT; - // When refcount drops to 0, destroys itself and the associated call stack, - // but does NOT free the memory because it's in the call arena. - void Unref(); - void Unref(const DebugLocation& location, const char* reason); - - void* GetParentData(); - - void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); - - // Invoked by channel for queued LB picks when the picker is updated. - static void PickSubchannel(void* arg, grpc_error* error); - // Helper function for performing an LB pick while holding the data plane - // mutex. Returns true if the pick is complete, in which case the caller - // must invoke PickDone() or AsyncPickDone() with the returned error. - bool PickSubchannelLocked(grpc_error** error); - // Schedules a callback to process the completed pick. The callback - // will not run until after this method returns. - void AsyncPickDone(grpc_error* error); - - RefCountedPtr subchannel_call() const { - return subchannel_call_; - } - - private: - // Allow RefCountedPtr<> to access IncrementRefCount(). - template - friend class ::grpc_core::RefCountedPtr; - - class LbQueuedCallCanceller; - class Metadata; - class LbCallState; - - // Interface of RefCounted<>. - void IncrementRefCount(); - void IncrementRefCount(const DebugLocation& location, const char* reason); - - // Returns the index into pending_batches_ to be used for batch. - static size_t GetBatchIndex(grpc_transport_stream_op_batch* batch); - void PendingBatchesAdd(grpc_transport_stream_op_batch* batch); - static void FailPendingBatchInCallCombiner(void* arg, grpc_error* error); - // A predicate type and some useful implementations for PendingBatchesFail(). - typedef bool (*YieldCallCombinerPredicate)( - const CallCombinerClosureList& closures); - static bool YieldCallCombiner(const CallCombinerClosureList& /*closures*/) { - return true; - } - static bool NoYieldCallCombiner(const CallCombinerClosureList& /*closures*/) { - return false; - } - static bool YieldCallCombinerIfPendingBatchesFound( - const CallCombinerClosureList& closures) { - return closures.size() > 0; - } - // Fails all pending batches. - // If yield_call_combiner_predicate returns true, assumes responsibility for - // yielding the call combiner. - void PendingBatchesFail( - grpc_error* error, - YieldCallCombinerPredicate yield_call_combiner_predicate); - static void ResumePendingBatchInCallCombiner(void* arg, grpc_error* ignored); - // Resumes all pending batches on subchannel_call_. - void PendingBatchesResume(); - - static void RecvTrailingMetadataReadyForLoadBalancingPolicy( - void* arg, grpc_error* error); - void InjectRecvTrailingMetadataReadyForLoadBalancingPolicy( - grpc_transport_stream_op_batch* batch); - - void CreateSubchannelCall(); - // Invoked when a pick is completed, on both success or failure. - static void PickDone(void* arg, grpc_error* error); - // Removes the call from the channel's list of queued picks if present. - void MaybeRemoveCallFromLbQueuedCallsLocked(); - // Adds the call to the channel's list of queued picks if not already present. - void MaybeAddCallToLbQueuedCallsLocked(); - - RefCount refs_; - - ChannelData* chand_; - - // TODO(roth): Instead of duplicating these fields in every filter - // that uses any one of them, we should store them in the call - // context. This will save per-call memory overhead. - grpc_slice path_; // Request path. - gpr_cycle_counter call_start_time_; - grpc_millis deadline_; - Arena* arena_; - grpc_call_stack* owning_call_; - CallCombiner* call_combiner_; - grpc_call_context_element* call_context_; - - // Set when we get a cancel_stream op. - grpc_error* cancel_error_ = GRPC_ERROR_NONE; - - grpc_polling_entity* pollent_ = nullptr; - - grpc_closure pick_closure_; - - // Accessed while holding ChannelData::data_plane_mu_. - ChannelData::LbQueuedCall queued_call_; - bool queued_pending_lb_pick_ = false; - const LoadBalancingPolicy::BackendMetricData* backend_metric_data_ = nullptr; - RefCountedPtr connected_subchannel_; - std::function - lb_recv_trailing_metadata_ready_; - LbQueuedCallCanceller* lb_call_canceller_ = nullptr; - - RefCountedPtr subchannel_call_; - - // For intercepting recv_trailing_metadata_ready for the LB policy. - grpc_metadata_batch* recv_trailing_metadata_ = nullptr; - grpc_closure recv_trailing_metadata_ready_; - grpc_closure* original_recv_trailing_metadata_ready_ = nullptr; - - // Batches are added to this list when received from above. - // They are removed when we are done handling the batch (i.e., when - // either we have invoked all of the batch's callbacks or we have - // passed the batch down to the subchannel call and are not - // intercepting any of its callbacks). - grpc_transport_stream_op_batch* pending_batches_[MAX_PENDING_BATCHES] = {}; +const grpc_channel_filter ClientChannel::kFilterVtable = { + ClientChannel::CallData::StartTransportStreamOpBatch, + ClientChannel::StartTransportOp, + sizeof(ClientChannel::CallData), + ClientChannel::CallData::Init, + ClientChannel::CallData::SetPollent, + ClientChannel::CallData::Destroy, + sizeof(ClientChannel), + ClientChannel::Init, + ClientChannel::Destroy, + ClientChannel::GetChannelInfo, + "client-channel", }; // // dynamic termination filter // -// Channel arg pointer vtable for GRPC_ARG_CLIENT_CHANNEL_DATA. -void* ChannelDataArgCopy(void* p) { return p; } -void ChannelDataArgDestroy(void* /*p*/) {} -int ChannelDataArgCmp(void* p, void* q) { return GPR_ICMP(p, q); } -const grpc_arg_pointer_vtable kChannelDataArgPointerVtable = { - ChannelDataArgCopy, ChannelDataArgDestroy, ChannelDataArgCmp}; - -// Channel arg pointer vtable for GRPC_ARG_RETRY_THROTTLE_DATA. -void* RetryThrottleDataArgCopy(void* p) { - auto* retry_throttle_data = static_cast(p); - retry_throttle_data->Ref().release(); +namespace { + +// Channel arg pointer vtable for GRPC_ARG_CLIENT_CHANNEL. +void* ClientChannelArgCopy(void* p) { return p; } +void ClientChannelArgDestroy(void* /*p*/) {} +int ClientChannelArgCmp(void* p, void* q) { return GPR_ICMP(p, q); } +const grpc_arg_pointer_vtable kClientChannelArgPointerVtable = { + ClientChannelArgCopy, ClientChannelArgDestroy, ClientChannelArgCmp}; + +// Channel arg pointer vtable for GRPC_ARG_SERVICE_CONFIG_OBJ. +void* ServiceConfigObjArgCopy(void* p) { + auto* service_config = static_cast(p); + service_config->Ref().release(); return p; } -void RetryThrottleDataArgDestroy(void* p) { - auto* retry_throttle_data = static_cast(p); - retry_throttle_data->Unref(); +void ServiceConfigObjArgDestroy(void* p) { + auto* service_config = static_cast(p); + service_config->Unref(); } -int RetryThrottleDataArgCmp(void* p, void* q) { return GPR_ICMP(p, q); } -const grpc_arg_pointer_vtable kRetryThrottleDataArgPointerVtable = { - RetryThrottleDataArgCopy, RetryThrottleDataArgDestroy, - RetryThrottleDataArgCmp}; +int ServiceConfigObjArgCmp(void* p, void* q) { return GPR_ICMP(p, q); } +const grpc_arg_pointer_vtable kServiceConfigObjArgPointerVtable = { + ServiceConfigObjArgCopy, ServiceConfigObjArgDestroy, + ServiceConfigObjArgCmp}; -class DynamicTerminationFilterChannelData { +class DynamicTerminationFilter { public: - static grpc_error* Init(grpc_channel_element* elem, - grpc_channel_element_args* args); + class CallData; + + static const grpc_channel_filter kFilterVtable; + + static grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args) { + GPR_ASSERT(args->is_last); + GPR_ASSERT(elem->filter == &kFilterVtable); + new (elem->channel_data) DynamicTerminationFilter(args->channel_args); + return GRPC_ERROR_NONE; + } static void Destroy(grpc_channel_element* elem) { - auto* chand = - static_cast(elem->channel_data); - chand->~DynamicTerminationFilterChannelData(); + auto* chand = static_cast(elem->channel_data); + chand->~DynamicTerminationFilter(); } // Will never be called. @@ -1084,57 +301,31 @@ class DynamicTerminationFilterChannelData { static void GetChannelInfo(grpc_channel_element* /*elem*/, const grpc_channel_info* /*info*/) {} - ChannelData* chand() const { return chand_; } - RefCountedPtr retry_throttle_data() const { - return retry_throttle_data_; - } - private: - static RefCountedPtr GetRetryThrottleDataFromArgs( - const grpc_channel_args* args) { - auto* retry_throttle_data = - grpc_channel_args_find_pointer( - args, GRPC_ARG_RETRY_THROTTLE_DATA); - if (retry_throttle_data == nullptr) return nullptr; - return retry_throttle_data->Ref(); - } - - explicit DynamicTerminationFilterChannelData(const grpc_channel_args* args) - : chand_(grpc_channel_args_find_pointer( - args, GRPC_ARG_CLIENT_CHANNEL_DATA)), - retry_throttle_data_(GetRetryThrottleDataFromArgs(args)) {} - - ChannelData* chand_; - RefCountedPtr retry_throttle_data_; + explicit DynamicTerminationFilter(const grpc_channel_args* args) + : chand_(grpc_channel_args_find_pointer( + args, GRPC_ARG_CLIENT_CHANNEL)) {} + + ClientChannel* chand_; }; -class DynamicTerminationFilterCallData { +class DynamicTerminationFilter::CallData { public: - static grpc_error* Init(grpc_call_element* elem, - const grpc_call_element_args* args) { - new (elem->call_data) DynamicTerminationFilterCallData(*args); + static grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args) { + new (elem->call_data) CallData(*args); return GRPC_ERROR_NONE; } static void Destroy(grpc_call_element* elem, const grpc_call_final_info* /*final_info*/, grpc_closure* then_schedule_closure) { - auto* calld = - static_cast(elem->call_data); - auto* chand = - static_cast(elem->channel_data); + auto* calld = static_cast(elem->call_data); RefCountedPtr subchannel_call; - if (chand->chand()->enable_retries()) { - if (GPR_LIKELY(calld->retrying_call_ != nullptr)) { - subchannel_call = calld->retrying_call_->subchannel_call(); - calld->retrying_call_->~RetryingCall(); - } - } else { - if (GPR_LIKELY(calld->lb_call_ != nullptr)) { - subchannel_call = calld->lb_call_->subchannel_call(); - } + if (GPR_LIKELY(calld->lb_call_ != nullptr)) { + subchannel_call = calld->lb_call_->subchannel_call(); } - calld->~DynamicTerminationFilterCallData(); + calld->~CallData(); if (GPR_LIKELY(subchannel_call != nullptr)) { subchannel_call->SetAfterCallStackDestroy(then_schedule_closure); } else { @@ -1145,60 +336,31 @@ class DynamicTerminationFilterCallData { static void StartTransportStreamOpBatch( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { - auto* calld = - static_cast(elem->call_data); - auto* chand = - static_cast(elem->channel_data); - if (chand->chand()->enable_retries()) { - calld->retrying_call_->StartTransportStreamOpBatch(batch); - } else { - calld->lb_call_->StartTransportStreamOpBatch(batch); - } + auto* calld = static_cast(elem->call_data); + calld->lb_call_->StartTransportStreamOpBatch(batch); } static void SetPollent(grpc_call_element* elem, grpc_polling_entity* pollent) { - auto* calld = - static_cast(elem->call_data); - auto* chand = - static_cast(elem->channel_data); - ChannelData* client_channel = chand->chand(); + auto* calld = static_cast(elem->call_data); + auto* chand = static_cast(elem->channel_data); + ClientChannel* client_channel = chand->chand_; grpc_call_element_args args = { calld->owning_call_, nullptr, calld->call_context_, calld->path_, calld->call_start_time_, calld->deadline_, calld->arena_, calld->call_combiner_}; - if (client_channel->enable_retries()) { - // Get retry settings from service config. - auto* svc_cfg_call_data = static_cast( - calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value); - GPR_ASSERT(svc_cfg_call_data != nullptr); - auto* method_config = static_cast( - svc_cfg_call_data->GetMethodParsedConfig( - ClientChannelServiceConfigParser::ParserIndex())); - // Create retrying call. - calld->retrying_call_ = calld->arena_->New( - client_channel, args, pollent, chand->retry_throttle_data(), - method_config == nullptr ? nullptr : method_config->retry_policy()); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log( - GPR_INFO, - "chand=%p dymamic_termination_calld=%p: create retrying_call=%p", - client_channel, calld, calld->retrying_call_); - } - } else { - calld->lb_call_ = - LoadBalancedCall::Create(client_channel, args, pollent, 0); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log(GPR_INFO, - "chand=%p dynamic_termination_calld=%p: create lb_call=%p", - chand, client_channel, calld->lb_call_.get()); - } + calld->lb_call_ = + client_channel->CreateLoadBalancedCall(args, pollent, nullptr); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, + "chand=%p dynamic_termination_calld=%p: create lb_call=%p", chand, + client_channel, calld->lb_call_.get()); } } private: - explicit DynamicTerminationFilterCallData(const grpc_call_element_args& args) + explicit CallData(const grpc_call_element_args& args) : path_(grpc_slice_ref_internal(args.path)), call_start_time_(args.start_time), deadline_(args.deadline), @@ -1207,7 +369,7 @@ class DynamicTerminationFilterCallData { call_combiner_(args.call_combiner), call_context_(args.context) {} - ~DynamicTerminationFilterCallData() { grpc_slice_unref_internal(path_); } + ~CallData() { grpc_slice_unref_internal(path_); } grpc_slice path_; // Request path. gpr_cycle_counter call_start_time_; @@ -1217,68 +379,92 @@ class DynamicTerminationFilterCallData { CallCombiner* call_combiner_; grpc_call_context_element* call_context_; - RetryingCall* retrying_call_ = nullptr; - RefCountedPtr lb_call_; + RefCountedPtr lb_call_; }; -const grpc_channel_filter kDynamicTerminationFilterVtable = { - DynamicTerminationFilterCallData::StartTransportStreamOpBatch, - DynamicTerminationFilterChannelData::StartTransportOp, - sizeof(DynamicTerminationFilterCallData), - DynamicTerminationFilterCallData::Init, - DynamicTerminationFilterCallData::SetPollent, - DynamicTerminationFilterCallData::Destroy, - sizeof(DynamicTerminationFilterChannelData), - DynamicTerminationFilterChannelData::Init, - DynamicTerminationFilterChannelData::Destroy, - DynamicTerminationFilterChannelData::GetChannelInfo, +const grpc_channel_filter DynamicTerminationFilter::kFilterVtable = { + DynamicTerminationFilter::CallData::StartTransportStreamOpBatch, + DynamicTerminationFilter::StartTransportOp, + sizeof(DynamicTerminationFilter::CallData), + DynamicTerminationFilter::CallData::Init, + DynamicTerminationFilter::CallData::SetPollent, + DynamicTerminationFilter::CallData::Destroy, + sizeof(DynamicTerminationFilter), + DynamicTerminationFilter::Init, + DynamicTerminationFilter::Destroy, + DynamicTerminationFilter::GetChannelInfo, "dynamic_filter_termination", }; -grpc_error* DynamicTerminationFilterChannelData::Init( - grpc_channel_element* elem, grpc_channel_element_args* args) { - GPR_ASSERT(args->is_last); - GPR_ASSERT(elem->filter == &kDynamicTerminationFilterVtable); - new (elem->channel_data) - DynamicTerminationFilterChannelData(args->channel_args); - return GRPC_ERROR_NONE; -} +} // namespace // -// ChannelData::SubchannelWrapper +// ClientChannel::ResolverResultHandler // -// This class is a wrapper for Subchannel that hides details of the -// channel's implementation (such as the health check service name and -// connected subchannel) from the LB policy API. -// -// Note that no synchronization is needed here, because even if the -// underlying subchannel is shared between channels, this wrapper will only -// be used within one channel, so it will always be synchronized by the -// control plane work_serializer. -class ChannelData::SubchannelWrapper : public SubchannelInterface { +class ClientChannel::ResolverResultHandler : public Resolver::ResultHandler { public: - SubchannelWrapper(ChannelData* chand, Subchannel* subchannel, + explicit ResolverResultHandler(ClientChannel* chand) : chand_(chand) { + GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ResolverResultHandler"); + } + + ~ResolverResultHandler() override { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, "chand=%p: resolver shutdown complete", chand_); + } + GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ResolverResultHandler"); + } + + void ReturnResult(Resolver::Result result) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { + chand_->OnResolverResultChangedLocked(std::move(result)); + } + + void ReturnError(grpc_error_handle error) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { + chand_->OnResolverErrorLocked(error); + } + + private: + ClientChannel* chand_; +}; + +// +// ClientChannel::SubchannelWrapper +// + +// This class is a wrapper for Subchannel that hides details of the +// channel's implementation (such as the health check service name and +// connected subchannel) from the LB policy API. +// +// Note that no synchronization is needed here, because even if the +// underlying subchannel is shared between channels, this wrapper will only +// be used within one channel, so it will always be synchronized by the +// control plane work_serializer. +class ClientChannel::SubchannelWrapper : public SubchannelInterface { + public: + SubchannelWrapper(ClientChannel* chand, RefCountedPtr subchannel, absl::optional health_check_service_name) : SubchannelInterface( GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace) ? "SubchannelWrapper" : nullptr), chand_(chand), - subchannel_(subchannel), + subchannel_(std::move(subchannel)), health_check_service_name_(std::move(health_check_service_name)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: creating subchannel wrapper %p for subchannel %p", - chand, this, subchannel_); + chand, this, subchannel_.get()); } GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "SubchannelWrapper"); auto* subchannel_node = subchannel_->channelz_node(); if (subchannel_node != nullptr) { - auto it = chand_->subchannel_refcount_map_.find(subchannel_); + auto it = chand_->subchannel_refcount_map_.find(subchannel_.get()); if (it == chand_->subchannel_refcount_map_.end()) { chand_->channelz_node_->AddChildSubchannel(subchannel_node->uuid()); - it = chand_->subchannel_refcount_map_.emplace(subchannel_, 0).first; + it = chand_->subchannel_refcount_map_.emplace(subchannel_.get(), 0) + .first; } ++it->second; } @@ -1289,12 +475,12 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: destroying subchannel wrapper %p for subchannel %p", - chand_, this, subchannel_); + chand_, this, subchannel_.get()); } chand_->subchannel_wrappers_.erase(this); auto* subchannel_node = subchannel_->channelz_node(); if (subchannel_node != nullptr) { - auto it = chand_->subchannel_refcount_map_.find(subchannel_); + auto it = chand_->subchannel_refcount_map_.find(subchannel_.get()); GPR_ASSERT(it != chand_->subchannel_refcount_map_.end()); --it->second; if (it->second == 0) { @@ -1302,11 +488,11 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { chand_->subchannel_refcount_map_.erase(it); } } - GRPC_SUBCHANNEL_UNREF(subchannel_, "unref from LB"); GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "SubchannelWrapper"); } - grpc_connectivity_state CheckConnectivityState() override { + grpc_connectivity_state CheckConnectivityState() override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { RefCountedPtr connected_subchannel; grpc_connectivity_state connectivity_state = subchannel_->CheckConnectivityState(health_check_service_name_, @@ -1385,16 +571,19 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { } // Caller must be holding the control-plane work_serializer. - ConnectedSubchannel* connected_subchannel() const { + ConnectedSubchannel* connected_subchannel() const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::work_serializer_) { return connected_subchannel_.get(); } // Caller must be holding the data-plane mutex. - ConnectedSubchannel* connected_subchannel_in_data_plane() const { + ConnectedSubchannel* connected_subchannel_in_data_plane() const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) { return connected_subchannel_in_data_plane_.get(); } void set_connected_subchannel_in_data_plane( - RefCountedPtr connected_subchannel) { + RefCountedPtr connected_subchannel) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_) { connected_subchannel_in_data_plane_ = std::move(connected_subchannel); } @@ -1427,7 +616,10 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { ~WatcherWrapper() override { auto* parent = parent_.release(); // ref owned by lambda parent->chand_->work_serializer_->Run( - [parent]() { parent->Unref(DEBUG_LOCATION, "WatcherWrapper"); }, + [parent]() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->chand_->work_serializer_) { + parent->Unref(DEBUG_LOCATION, "WatcherWrapper"); + }, DEBUG_LOCATION); } @@ -1436,14 +628,15 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { gpr_log(GPR_INFO, "chand=%p: connectivity change for subchannel wrapper %p " "subchannel %p; hopping into work_serializer", - parent_->chand_, parent_.get(), parent_->subchannel_); + parent_->chand_, parent_.get(), parent_->subchannel_.get()); } Ref().release(); // ref owned by lambda parent_->chand_->work_serializer_->Run( - [this]() { - ApplyUpdateInControlPlaneWorkSerializer(); - Unref(); - }, + [this]() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->chand_->work_serializer_) { + ApplyUpdateInControlPlaneWorkSerializer(); + Unref(); + }, DEBUG_LOCATION); } @@ -1464,13 +657,14 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { grpc_connectivity_state last_seen_state() const { return last_seen_state_; } private: - void ApplyUpdateInControlPlaneWorkSerializer() { + void ApplyUpdateInControlPlaneWorkSerializer() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_->chand_->work_serializer_) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: processing connectivity change in work serializer " "for subchannel wrapper %p subchannel %p " "watcher=%p", - parent_->chand_, parent_.get(), parent_->subchannel_, + parent_->chand_, parent_.get(), parent_->subchannel_.get(), watcher_.get()); } ConnectivityStateChange state_change = PopConnectivityStateChange(); @@ -1518,7 +712,8 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { }; void MaybeUpdateConnectedSubchannel( - RefCountedPtr connected_subchannel) { + RefCountedPtr connected_subchannel) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::work_serializer_) { // Update the connected subchannel only if the channel is not shutting // down. This is because once the channel is shutting down, we // ignore picker updates from the LB policy, which means that @@ -1526,7 +721,7 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { // in chand_->pending_subchannel_updates_. So we don't want to add // entries there that will never be processed, since that would // leave dangling refs to the channel and prevent its destruction. - grpc_error* disconnect_error = chand_->disconnect_error(); + grpc_error_handle disconnect_error = chand_->disconnect_error(); if (disconnect_error != GRPC_ERROR_NONE) return; // Not shutting down, so do the update. if (connected_subchannel_ != connected_subchannel) { @@ -1538,8 +733,8 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { } } - ChannelData* chand_; - Subchannel* subchannel_; + ClientChannel* chand_; + RefCountedPtr subchannel_; absl::optional health_check_service_name_; // Maps from the address of the watcher passed to us by the LB policy // to the address of the WrapperWatcher that we passed to the underlying @@ -1548,17 +743,19 @@ class ChannelData::SubchannelWrapper : public SubchannelInterface { // corresponding WrapperWatcher to cancel on the underlying subchannel. std::map watcher_map_; // To be accessed only in the control plane work_serializer. - RefCountedPtr connected_subchannel_; + RefCountedPtr connected_subchannel_ + ABSL_GUARDED_BY(&ClientChannel::work_serializer_); // To be accessed only in the data plane mutex. - RefCountedPtr connected_subchannel_in_data_plane_; + RefCountedPtr connected_subchannel_in_data_plane_ + ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_); }; // -// ChannelData::ExternalConnectivityWatcher +// ClientChannel::ExternalConnectivityWatcher // -ChannelData::ExternalConnectivityWatcher::ExternalConnectivityWatcher( - ChannelData* chand, grpc_polling_entity pollent, +ClientChannel::ExternalConnectivityWatcher::ExternalConnectivityWatcher( + ClientChannel* chand, grpc_polling_entity pollent, grpc_connectivity_state* state, grpc_closure* on_complete, grpc_closure* watcher_timer_init) : chand_(chand), @@ -1580,22 +777,22 @@ ChannelData::ExternalConnectivityWatcher::ExternalConnectivityWatcher( } // Pass the ref from creating the object to Start(). chand_->work_serializer_->Run( - [this]() { + [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { // The ref is passed to AddWatcherLocked(). AddWatcherLocked(); }, DEBUG_LOCATION); } -ChannelData::ExternalConnectivityWatcher::~ExternalConnectivityWatcher() { +ClientChannel::ExternalConnectivityWatcher::~ExternalConnectivityWatcher() { grpc_polling_entity_del_from_pollset_set(&pollent_, chand_->interested_parties_); GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ExternalConnectivityWatcher"); } -void ChannelData::ExternalConnectivityWatcher:: - RemoveWatcherFromExternalWatchersMap(ChannelData* chand, +void ClientChannel::ExternalConnectivityWatcher:: + RemoveWatcherFromExternalWatchersMap(ClientChannel* chand, grpc_closure* on_complete, bool cancel) { RefCountedPtr watcher; @@ -1612,7 +809,7 @@ void ChannelData::ExternalConnectivityWatcher:: if (watcher != nullptr && cancel) watcher->Cancel(); } -void ChannelData::ExternalConnectivityWatcher::Notify( +void ClientChannel::ExternalConnectivityWatcher::Notify( grpc_connectivity_state state, const absl::Status& /* status */) { bool done = false; if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED, @@ -1620,7 +817,8 @@ void ChannelData::ExternalConnectivityWatcher::Notify( return; // Already done. } // Remove external watcher. - chand_->RemoveExternalConnectivityWatcher(on_complete_, /*cancel=*/false); + ExternalConnectivityWatcher::RemoveWatcherFromExternalWatchersMap( + chand_, on_complete_, /*cancel=*/false); // Report new state to the user. *state_ = state; ExecCtx::Run(DEBUG_LOCATION, on_complete_, GRPC_ERROR_NONE); @@ -1628,12 +826,15 @@ void ChannelData::ExternalConnectivityWatcher::Notify( // Not needed in state SHUTDOWN, because the tracker will // automatically remove all watchers in that case. if (state != GRPC_CHANNEL_SHUTDOWN) { - chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); }, - DEBUG_LOCATION); + chand_->work_serializer_->Run( + [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { + RemoveWatcherLocked(); + }, + DEBUG_LOCATION); } } -void ChannelData::ExternalConnectivityWatcher::Cancel() { +void ClientChannel::ExternalConnectivityWatcher::Cancel() { bool done = false; if (!done_.CompareExchangeStrong(&done, true, MemoryOrder::RELAXED, MemoryOrder::RELAXED)) { @@ -1641,84 +842,95 @@ void ChannelData::ExternalConnectivityWatcher::Cancel() { } ExecCtx::Run(DEBUG_LOCATION, on_complete_, GRPC_ERROR_CANCELLED); // Hop back into the work_serializer to clean up. - chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); }, - DEBUG_LOCATION); + chand_->work_serializer_->Run( + [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { + RemoveWatcherLocked(); + }, + DEBUG_LOCATION); } -void ChannelData::ExternalConnectivityWatcher::AddWatcherLocked() { +void ClientChannel::ExternalConnectivityWatcher::AddWatcherLocked() { Closure::Run(DEBUG_LOCATION, watcher_timer_init_, GRPC_ERROR_NONE); // Add new watcher. Pass the ref of the object from creation to OrphanablePtr. chand_->state_tracker_.AddWatcher( initial_state_, OrphanablePtr(this)); } -void ChannelData::ExternalConnectivityWatcher::RemoveWatcherLocked() { +void ClientChannel::ExternalConnectivityWatcher::RemoveWatcherLocked() { chand_->state_tracker_.RemoveWatcher(this); } // -// ChannelData::ConnectivityWatcherAdder +// ClientChannel::ConnectivityWatcherAdder // -class ChannelData::ConnectivityWatcherAdder { +class ClientChannel::ConnectivityWatcherAdder { public: ConnectivityWatcherAdder( - ChannelData* chand, grpc_connectivity_state initial_state, + ClientChannel* chand, grpc_connectivity_state initial_state, OrphanablePtr watcher) : chand_(chand), initial_state_(initial_state), watcher_(std::move(watcher)) { GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ConnectivityWatcherAdder"); - chand_->work_serializer_->Run([this]() { AddWatcherLocked(); }, - DEBUG_LOCATION); + chand_->work_serializer_->Run( + [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { + AddWatcherLocked(); + }, + DEBUG_LOCATION); } private: - void AddWatcherLocked() { + void AddWatcherLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { chand_->state_tracker_.AddWatcher(initial_state_, std::move(watcher_)); GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ConnectivityWatcherAdder"); delete this; } - ChannelData* chand_; + ClientChannel* chand_; grpc_connectivity_state initial_state_; OrphanablePtr watcher_; }; // -// ChannelData::ConnectivityWatcherRemover +// ClientChannel::ConnectivityWatcherRemover // -class ChannelData::ConnectivityWatcherRemover { +class ClientChannel::ConnectivityWatcherRemover { public: - ConnectivityWatcherRemover(ChannelData* chand, + ConnectivityWatcherRemover(ClientChannel* chand, AsyncConnectivityStateWatcherInterface* watcher) : chand_(chand), watcher_(watcher) { GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ConnectivityWatcherRemover"); - chand_->work_serializer_->Run([this]() { RemoveWatcherLocked(); }, - DEBUG_LOCATION); + chand_->work_serializer_->Run( + [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { + RemoveWatcherLocked(); + }, + DEBUG_LOCATION); } private: - void RemoveWatcherLocked() { + void RemoveWatcherLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { chand_->state_tracker_.RemoveWatcher(watcher_); GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ConnectivityWatcherRemover"); delete this; } - ChannelData* chand_; + ClientChannel* chand_; AsyncConnectivityStateWatcherInterface* watcher_; }; // -// ChannelData::ClientChannelControlHelper +// ClientChannel::ClientChannelControlHelper // -class ChannelData::ClientChannelControlHelper +class ClientChannel::ClientChannelControlHelper : public LoadBalancingPolicy::ChannelControlHelper { public: - explicit ClientChannelControlHelper(ChannelData* chand) : chand_(chand) { + explicit ClientChannelControlHelper(ClientChannel* chand) : chand_(chand) { GRPC_CHANNEL_STACK_REF(chand_->owning_stack_, "ClientChannelControlHelper"); } @@ -1728,11 +940,12 @@ class ChannelData::ClientChannelControlHelper } RefCountedPtr CreateSubchannel( - ServerAddress address, const grpc_channel_args& args) override { + ServerAddress address, const grpc_channel_args& args) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { if (chand_->resolver_ == nullptr) return nullptr; // Shutting down. // Determine health check service name. - bool inhibit_health_checking = grpc_channel_arg_get_bool( - grpc_channel_args_find(&args, GRPC_ARG_INHIBIT_HEALTH_CHECKING), false); + bool inhibit_health_checking = grpc_channel_args_find_bool( + &args, GRPC_ARG_INHIBIT_HEALTH_CHECKING, false); absl::optional health_check_service_name; if (!inhibit_health_checking) { health_check_service_name = chand_->health_check_service_name_; @@ -1758,7 +971,7 @@ class ChannelData::ClientChannelControlHelper args_to_add.data(), args_to_add.size()); gpr_free(args_to_add[0].value.string); // Create subchannel. - Subchannel* subchannel = + RefCountedPtr subchannel = chand_->client_channel_factory_->CreateSubchannel(new_args); grpc_channel_args_destroy(new_args); if (subchannel == nullptr) return nullptr; @@ -1766,14 +979,15 @@ class ChannelData::ClientChannelControlHelper subchannel->ThrottleKeepaliveTime(chand_->keepalive_time_); // Create and return wrapper for the subchannel. return MakeRefCounted( - chand_, subchannel, std::move(health_check_service_name)); + chand_, std::move(subchannel), std::move(health_check_service_name)); } void UpdateState( grpc_connectivity_state state, const absl::Status& status, - std::unique_ptr picker) override { + std::unique_ptr picker) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { if (chand_->resolver_ == nullptr) return; // Shutting down. - grpc_error* disconnect_error = chand_->disconnect_error(); + grpc_error_handle disconnect_error = chand_->disconnect_error(); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { const char* extra = disconnect_error == GRPC_ERROR_NONE ? "" @@ -1789,7 +1003,8 @@ class ChannelData::ClientChannelControlHelper } } - void RequestReresolution() override { + void RequestReresolution() override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { if (chand_->resolver_ == nullptr) return; // Shutting down. if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: started name re-resolving", chand_); @@ -1797,8 +1012,8 @@ class ChannelData::ClientChannelControlHelper chand_->resolver_->RequestReresolutionLocked(); } - void AddTraceEvent(TraceSeverity severity, - absl::string_view message) override { + void AddTraceEvent(TraceSeverity severity, absl::string_view message) override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { if (chand_->resolver_ == nullptr) return; // Shutting down. if (chand_->channelz_node_ != nullptr) { chand_->channelz_node_->AddTraceEvent( @@ -1815,42 +1030,44 @@ class ChannelData::ClientChannelControlHelper return channelz::ChannelTrace::Error; } - ChannelData* chand_; + ClientChannel* chand_; }; // -// ChannelData implementation +// ClientChannel implementation // -grpc_error* ChannelData::Init(grpc_channel_element* elem, - grpc_channel_element_args* args) { +ClientChannel* ClientChannel::GetFromChannel(grpc_channel* channel) { + grpc_channel_element* elem = + grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel)); + if (elem->filter != &kFilterVtable) return nullptr; + return static_cast(elem->channel_data); +} + +grpc_error_handle ClientChannel::Init(grpc_channel_element* elem, + grpc_channel_element_args* args) { GPR_ASSERT(args->is_last); - GPR_ASSERT(elem->filter == &grpc_client_channel_filter); - grpc_error* error = GRPC_ERROR_NONE; - new (elem->channel_data) ChannelData(args, &error); + GPR_ASSERT(elem->filter == &kFilterVtable); + grpc_error_handle error = GRPC_ERROR_NONE; + new (elem->channel_data) ClientChannel(args, &error); return error; } -void ChannelData::Destroy(grpc_channel_element* elem) { - ChannelData* chand = static_cast(elem->channel_data); - chand->~ChannelData(); +void ClientChannel::Destroy(grpc_channel_element* elem) { + ClientChannel* chand = static_cast(elem->channel_data); + chand->~ClientChannel(); } -bool GetEnableRetries(const grpc_channel_args* args) { - return grpc_channel_arg_get_bool( - grpc_channel_args_find(args, GRPC_ARG_ENABLE_RETRIES), true); -} +namespace { -size_t GetMaxPerRpcRetryBufferSize(const grpc_channel_args* args) { - return static_cast(grpc_channel_arg_get_integer( - grpc_channel_args_find(args, GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE), - {DEFAULT_PER_RPC_RETRY_BUFFER_SIZE, 0, INT_MAX})); +bool GetEnableRetries(const grpc_channel_args* args) { + return grpc_channel_args_find_bool(args, GRPC_ARG_ENABLE_RETRIES, false); } RefCountedPtr GetSubchannelPool( const grpc_channel_args* args) { - const bool use_local_subchannel_pool = grpc_channel_arg_get_bool( - grpc_channel_args_find(args, GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL), false); + const bool use_local_subchannel_pool = grpc_channel_args_find_bool( + args, GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, false); if (use_local_subchannel_pool) { return MakeRefCounted(); } @@ -1858,26 +1075,23 @@ RefCountedPtr GetSubchannelPool( } channelz::ChannelNode* GetChannelzNode(const grpc_channel_args* args) { - const grpc_arg* arg = - grpc_channel_args_find(args, GRPC_ARG_CHANNELZ_CHANNEL_NODE); - if (arg != nullptr && arg->type == GRPC_ARG_POINTER) { - return static_cast(arg->value.pointer.p); - } - return nullptr; + return grpc_channel_args_find_pointer( + args, GRPC_ARG_CHANNELZ_CHANNEL_NODE); } -ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) +} // namespace + +ClientChannel::ClientChannel(grpc_channel_element_args* args, + grpc_error_handle* error) : deadline_checking_enabled_( grpc_deadline_checking_enabled(args->channel_args)), enable_retries_(GetEnableRetries(args->channel_args)), - per_rpc_retry_buffer_size_( - GetMaxPerRpcRetryBufferSize(args->channel_args)), owning_stack_(args->channel_stack), client_channel_factory_( ClientChannelFactory::GetFromChannelArgs(args->channel_args)), channelz_node_(GetChannelzNode(args->channel_args)), - work_serializer_(std::make_shared()), interested_parties_(grpc_pollset_set_create()), + work_serializer_(std::make_shared()), state_tracker_("client_channel", GRPC_CHANNEL_IDLE), subchannel_pool_(GetSubchannelPool(args->channel_args)), disconnect_error_(GRPC_ERROR_NONE) { @@ -1894,8 +1108,8 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) return; } // Get server name to resolve, using proxy mapper if needed. - const char* server_uri = grpc_channel_arg_get_string( - grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVER_URI)); + const char* server_uri = + grpc_channel_args_find_string(args->channel_args, GRPC_ARG_SERVER_URI); if (server_uri == nullptr) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "server URI channel arg missing or wrong type in client channel " @@ -1904,8 +1118,8 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) } // Get default service config. If none is specified via the client API, // we use an empty config. - const char* service_config_json = grpc_channel_arg_get_string( - grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG)); + const char* service_config_json = grpc_channel_args_find_string( + args->channel_args, GRPC_ARG_SERVICE_CONFIG); if (service_config_json == nullptr) service_config_json = "{}"; *error = GRPC_ERROR_NONE; default_service_config_ = @@ -1942,7 +1156,7 @@ ChannelData::ChannelData(grpc_channel_element_args* args, grpc_error** error) *error = GRPC_ERROR_NONE; } -ChannelData::~ChannelData() { +ClientChannel::~ClientChannel() { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: destroying channel", this); } @@ -1955,6 +1169,16 @@ ChannelData::~ChannelData() { GRPC_ERROR_UNREF(disconnect_error_.Load(MemoryOrder::RELAXED)); } +RefCountedPtr +ClientChannel::CreateLoadBalancedCall( + const grpc_call_element_args& args, grpc_polling_entity* pollent, + grpc_closure* on_call_destruction_complete) { + return args.arena->New(this, args, pollent, + on_call_destruction_complete); +} + +namespace { + RefCountedPtr ChooseLbPolicy( const Resolver::Result& resolver_result, const internal::ClientChannelGlobalParsedConfig* parsed_service_config) { @@ -1968,9 +1192,8 @@ RefCountedPtr ChooseLbPolicy( if (!parsed_service_config->parsed_deprecated_lb_policy().empty()) { policy_name = parsed_service_config->parsed_deprecated_lb_policy().c_str(); } else { - const grpc_arg* channel_arg = - grpc_channel_args_find(resolver_result.args, GRPC_ARG_LB_POLICY_NAME); - policy_name = grpc_channel_arg_get_string(channel_arg); + policy_name = grpc_channel_args_find_string(resolver_result.args, + GRPC_ARG_LB_POLICY_NAME); } // Use pick_first if nothing was specified and we didn't select grpclb // above. @@ -1979,7 +1202,7 @@ RefCountedPtr ChooseLbPolicy( Json config_json = Json::Array{Json::Object{ {policy_name, Json::Object{}}, }}; - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; auto lb_policy_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( config_json, &parse_error); // The policy name came from one of three places: @@ -1999,7 +1222,9 @@ RefCountedPtr ChooseLbPolicy( return lb_policy_config; } -void ChannelData::OnResolverResultChangedLocked(Resolver::Result result) { +} // namespace + +void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { // Handle race conditions. if (resolver_ == nullptr) return; if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { @@ -2022,21 +1247,19 @@ void ChannelData::OnResolverResultChangedLocked(Resolver::Result result) { trace_strings.push_back("Address list became non-empty"); } previous_resolution_contained_addresses_ = !result.addresses.empty(); - // The result of grpc_error_string() is owned by the error itself. - // We're storing that string in trace_strings, so we need to make sure - // that the error lives until we're done with the string. - grpc_error* service_config_error = - GRPC_ERROR_REF(result.service_config_error); - if (service_config_error != GRPC_ERROR_NONE) { - trace_strings.push_back(grpc_error_string(service_config_error)); + std::string service_config_error_string_storage; + if (result.service_config_error != GRPC_ERROR_NONE) { + service_config_error_string_storage = + grpc_error_std_string(result.service_config_error); + trace_strings.push_back(service_config_error_string_storage.c_str()); } // Choose the service config. RefCountedPtr service_config; RefCountedPtr config_selector; - if (service_config_error != GRPC_ERROR_NONE) { + if (result.service_config_error != GRPC_ERROR_NONE) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver returned service config error: %s", - this, grpc_error_string(service_config_error)); + this, grpc_error_std_string(result.service_config_error).c_str()); } // If the service config was invalid, then fallback to the // previously returned service config. @@ -2053,7 +1276,7 @@ void ChannelData::OnResolverResultChangedLocked(Resolver::Result result) { // We received an invalid service config and we don't have a // previous service config to fall back to. Put the channel into // TRANSIENT_FAILURE. - OnResolverErrorLocked(GRPC_ERROR_REF(service_config_error)); + OnResolverErrorLocked(GRPC_ERROR_REF(result.service_config_error)); trace_strings.push_back("no valid service config"); } } else if (result.service_config == nullptr) { @@ -2118,24 +1341,24 @@ void ChannelData::OnResolverResultChangedLocked(Resolver::Result result) { grpc_slice_from_cpp_string(message)); } } - GRPC_ERROR_UNREF(service_config_error); } -void ChannelData::OnResolverErrorLocked(grpc_error* error) { +void ClientChannel::OnResolverErrorLocked(grpc_error_handle error) { if (resolver_ == nullptr) { GRPC_ERROR_UNREF(error); return; } if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver transient failure: %s", this, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } // If we already have an LB policy from a previous resolution // result, then we continue to let it set the connectivity state. // Otherwise, we go into TRANSIENT_FAILURE. if (lb_policy_ == nullptr) { - grpc_error* state_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Resolver transient failure", &error, 1); + grpc_error_handle state_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Resolver transient failure", &error, 1); { MutexLock lock(&resolution_mu_); // Update resolver transient failure. @@ -2146,7 +1369,7 @@ void ChannelData::OnResolverErrorLocked(grpc_error* error) { call = call->next) { grpc_call_element* elem = call->elem; CallData* calld = static_cast(elem->call_data); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (calld->CheckResolutionLocked(elem, &error)) { calld->AsyncResolutionDone(elem, error); } @@ -2162,7 +1385,7 @@ void ChannelData::OnResolverErrorLocked(grpc_error* error) { GRPC_ERROR_UNREF(error); } -void ChannelData::CreateOrUpdateLbPolicyLocked( +void ClientChannel::CreateOrUpdateLbPolicyLocked( RefCountedPtr lb_policy_config, Resolver::Result result) { // Construct update. @@ -2188,7 +1411,7 @@ void ChannelData::CreateOrUpdateLbPolicyLocked( } // Creates a new LB policy. -OrphanablePtr ChannelData::CreateLbPolicyLocked( +OrphanablePtr ClientChannel::CreateLbPolicyLocked( const grpc_channel_args& args) { LoadBalancingPolicy::Args lb_policy_args; lb_policy_args.work_serializer = work_serializer_; @@ -2207,8 +1430,8 @@ OrphanablePtr ChannelData::CreateLbPolicyLocked( return lb_policy; } -void ChannelData::AddResolverQueuedCall(ResolverQueuedCall* call, - grpc_polling_entity* pollent) { +void ClientChannel::AddResolverQueuedCall(ResolverQueuedCall* call, + grpc_polling_entity* pollent) { // Add call to queued calls list. call->next = resolver_queued_calls_; resolver_queued_calls_ = call; @@ -2217,8 +1440,8 @@ void ChannelData::AddResolverQueuedCall(ResolverQueuedCall* call, grpc_polling_entity_add_to_pollset_set(pollent, interested_parties_); } -void ChannelData::RemoveResolverQueuedCall(ResolverQueuedCall* to_remove, - grpc_polling_entity* pollent) { +void ClientChannel::RemoveResolverQueuedCall(ResolverQueuedCall* to_remove, + grpc_polling_entity* pollent) { // Remove call's pollent from channel's interested_parties. grpc_polling_entity_del_from_pollset_set(pollent, interested_parties_); // Remove from queued calls list. @@ -2231,7 +1454,7 @@ void ChannelData::RemoveResolverQueuedCall(ResolverQueuedCall* to_remove, } } -void ChannelData::UpdateServiceConfigInControlPlaneLocked( +void ClientChannel::UpdateServiceConfigInControlPlaneLocked( RefCountedPtr service_config, RefCountedPtr config_selector, const internal::ClientChannelGlobalParsedConfig* parsed_service_config, @@ -2271,7 +1494,7 @@ void ChannelData::UpdateServiceConfigInControlPlaneLocked( } } -void ChannelData::UpdateServiceConfigInDataPlaneLocked() { +void ClientChannel::UpdateServiceConfigInDataPlaneLocked() { // Grab ref to service config. RefCountedPtr service_config = saved_service_config_; // Grab ref to config selector. Use default if resolver didn't supply one. @@ -2284,32 +1507,22 @@ void ChannelData::UpdateServiceConfigInDataPlaneLocked() { config_selector = MakeRefCounted(saved_service_config_); } - // Get retry throttle data from service config. - const internal::ClientChannelGlobalParsedConfig* parsed_service_config = - static_cast( - saved_service_config_->GetGlobalParsedConfig( - internal::ClientChannelServiceConfigParser::ParserIndex())); - absl::optional - retry_throttle_config = parsed_service_config->retry_throttling(); - RefCountedPtr retry_throttle_data; - if (retry_throttle_config.has_value()) { - retry_throttle_data = internal::ServerRetryThrottleMap::GetDataForServer( - server_name_, retry_throttle_config.value().max_milli_tokens, - retry_throttle_config.value().milli_token_ratio); - } // Construct dynamic filter stack. std::vector filters = config_selector->GetFilters(); - filters.push_back(&kDynamicTerminationFilterVtable); - absl::InlinedVector args_to_add; - args_to_add.push_back(grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_CLIENT_CHANNEL_DATA), this, - &kChannelDataArgPointerVtable)); - if (retry_throttle_data != nullptr) { - args_to_add.push_back(grpc_channel_arg_pointer_create( - const_cast(GRPC_ARG_RETRY_THROTTLE_DATA), - retry_throttle_data.get(), &kRetryThrottleDataArgPointerVtable)); - } + if (enable_retries_) { + filters.push_back(&kRetryFilterVtable); + } else { + filters.push_back(&DynamicTerminationFilter::kFilterVtable); + } + absl::InlinedVector args_to_add = { + grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_CLIENT_CHANNEL), this, + &kClientChannelArgPointerVtable), + grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_SERVICE_CONFIG_OBJ), service_config.get(), + &kServiceConfigObjArgPointerVtable), + }; grpc_channel_args* new_args = grpc_channel_args_copy_and_add( channel_args_, args_to_add.data(), args_to_add.size()); new_args = config_selector->ModifyChannelArgs(new_args); @@ -2337,7 +1550,7 @@ void ChannelData::UpdateServiceConfigInDataPlaneLocked() { call = call->next) { grpc_call_element* elem = call->elem; CallData* calld = static_cast(elem->call_data); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (calld->CheckResolutionLocked(elem, &error)) { calld->AsyncResolutionDone(elem, error); } @@ -2347,7 +1560,7 @@ void ChannelData::UpdateServiceConfigInDataPlaneLocked() { // of scope. } -void ChannelData::CreateResolverLocked() { +void ClientChannel::CreateResolverLocked() { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: starting name resolution", this); } @@ -2366,7 +1579,7 @@ void ChannelData::CreateResolverLocked() { } } -void ChannelData::DestroyResolverAndLbPolicyLocked() { +void ClientChannel::DestroyResolverAndLbPolicyLocked() { if (resolver_ != nullptr) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: shutting down resolver=%p", this, @@ -2385,7 +1598,7 @@ void ChannelData::DestroyResolverAndLbPolicyLocked() { } } -void ChannelData::UpdateStateAndPickerLocked( +void ClientChannel::UpdateStateAndPickerLocked( grpc_connectivity_state state, const absl::Status& status, const char* reason, std::unique_ptr picker) { @@ -2447,7 +1660,7 @@ void ChannelData::UpdateStateAndPickerLocked( // Re-process queued picks. for (LbQueuedCall* call = lb_queued_calls_; call != nullptr; call = call->next) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (call->lb_call->PickSubchannelLocked(&error)) { call->lb_call->AsyncPickDone(error); } @@ -2458,12 +1671,15 @@ void ChannelData::UpdateStateAndPickerLocked( pending_subchannel_updates_.clear(); } -grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) { +grpc_error_handle ClientChannel::DoPingLocked(grpc_transport_op* op) { if (state_tracker_.state() != GRPC_CHANNEL_READY) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("channel not connected"); } - LoadBalancingPolicy::PickResult result = - picker_->Pick(LoadBalancingPolicy::PickArgs()); + LoadBalancingPolicy::PickResult result; + { + MutexLock lock(&data_plane_mu_); + result = picker_->Pick(LoadBalancingPolicy::PickArgs()); + } ConnectedSubchannel* connected_subchannel = nullptr; if (result.subchannel != nullptr) { SubchannelWrapper* subchannel = @@ -2481,7 +1697,7 @@ grpc_error* ChannelData::DoPingLocked(grpc_transport_op* op) { return result.error; } -void ChannelData::StartTransportOpLocked(grpc_transport_op* op) { +void ClientChannel::StartTransportOpLocked(grpc_transport_op* op) { // Connectivity watch. if (op->start_connectivity_watch != nullptr) { state_tracker_.AddWatcher(op->start_connectivity_watch_state, @@ -2492,7 +1708,7 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) { } // Ping. if (op->send_ping.on_initiate != nullptr || op->send_ping.on_ack != nullptr) { - grpc_error* error = DoPingLocked(op); + grpc_error_handle error = DoPingLocked(op); if (error != GRPC_ERROR_NONE) { ExecCtx::Run(DEBUG_LOCATION, op->send_ping.on_initiate, GRPC_ERROR_REF(error)); @@ -2512,7 +1728,7 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) { if (op->disconnect_with_error != GRPC_ERROR_NONE) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p: disconnect_with_error: %s", this, - grpc_error_string(op->disconnect_with_error)); + grpc_error_std_string(op->disconnect_with_error).c_str()); } DestroyResolverAndLbPolicyLocked(); intptr_t value; @@ -2540,9 +1756,9 @@ void ChannelData::StartTransportOpLocked(grpc_transport_op* op) { ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, GRPC_ERROR_NONE); } -void ChannelData::StartTransportOp(grpc_channel_element* elem, - grpc_transport_op* op) { - ChannelData* chand = static_cast(elem->channel_data); +void ClientChannel::StartTransportOp(grpc_channel_element* elem, + grpc_transport_op* op) { + ClientChannel* chand = static_cast(elem->channel_data); GPR_ASSERT(op->set_accept_stream == false); // Handle bind_pollset. if (op->bind_pollset != nullptr) { @@ -2551,12 +1767,15 @@ void ChannelData::StartTransportOp(grpc_channel_element* elem, // Pop into control plane work_serializer for remaining ops. GRPC_CHANNEL_STACK_REF(chand->owning_stack_, "start_transport_op"); chand->work_serializer_->Run( - [chand, op]() { chand->StartTransportOpLocked(op); }, DEBUG_LOCATION); + [chand, op]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand->work_serializer_) { + chand->StartTransportOpLocked(op); + }, + DEBUG_LOCATION); } -void ChannelData::GetChannelInfo(grpc_channel_element* elem, - const grpc_channel_info* info) { - ChannelData* chand = static_cast(elem->channel_data); +void ClientChannel::GetChannelInfo(grpc_channel_element* elem, + const grpc_channel_info* info) { + ClientChannel* chand = static_cast(elem->channel_data); MutexLock lock(&chand->info_mu_); if (info->lb_policy_name != nullptr) { *info->lb_policy_name = gpr_strdup(chand->info_lb_policy_name_.get()); @@ -2567,8 +1786,8 @@ void ChannelData::GetChannelInfo(grpc_channel_element* elem, } } -void ChannelData::AddLbQueuedCall(LbQueuedCall* call, - grpc_polling_entity* pollent) { +void ClientChannel::AddLbQueuedCall(LbQueuedCall* call, + grpc_polling_entity* pollent) { // Add call to queued picks list. call->next = lb_queued_calls_; lb_queued_calls_ = call; @@ -2577,8 +1796,8 @@ void ChannelData::AddLbQueuedCall(LbQueuedCall* call, grpc_polling_entity_add_to_pollset_set(pollent, interested_parties_); } -void ChannelData::RemoveLbQueuedCall(LbQueuedCall* to_remove, - grpc_polling_entity* pollent) { +void ClientChannel::RemoveLbQueuedCall(LbQueuedCall* to_remove, + grpc_polling_entity* pollent) { // Remove call's pollent from channel's interested_parties. grpc_polling_entity_del_from_pollset_set(pollent, interested_parties_); // Remove from queued picks list. @@ -2592,7 +1811,7 @@ void ChannelData::RemoveLbQueuedCall(LbQueuedCall* to_remove, } RefCountedPtr -ChannelData::GetConnectedSubchannelInDataPlane( +ClientChannel::GetConnectedSubchannelInDataPlane( SubchannelInterface* subchannel) const { SubchannelWrapper* subchannel_wrapper = static_cast(subchannel); @@ -2602,7 +1821,7 @@ ChannelData::GetConnectedSubchannelInDataPlane( return connected_subchannel->Ref(); } -void ChannelData::TryToConnectLocked() { +void ClientChannel::TryToConnectLocked() { if (lb_policy_ != nullptr) { lb_policy_->ExitIdleLocked(); } else if (resolver_ == nullptr) { @@ -2611,23 +1830,29 @@ void ChannelData::TryToConnectLocked() { GRPC_CHANNEL_STACK_UNREF(owning_stack_, "TryToConnect"); } -grpc_connectivity_state ChannelData::CheckConnectivityState( +grpc_connectivity_state ClientChannel::CheckConnectivityState( bool try_to_connect) { - grpc_connectivity_state out = state_tracker_.state(); + // state_tracker_ is guarded by work_serializer_, which we're not + // holding here. But the one method of state_tracker_ that *is* + // thread-safe to call without external synchronization is the state() + // method, so we can disable thread-safety analysis for this one read. + grpc_connectivity_state out = ABSL_TS_UNCHECKED_READ(state_tracker_).state(); if (out == GRPC_CHANNEL_IDLE && try_to_connect) { GRPC_CHANNEL_STACK_REF(owning_stack_, "TryToConnect"); - work_serializer_->Run([this]() { TryToConnectLocked(); }, DEBUG_LOCATION); + work_serializer_->Run([this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED( + work_serializer_) { TryToConnectLocked(); }, + DEBUG_LOCATION); } return out; } -void ChannelData::AddConnectivityWatcher( +void ClientChannel::AddConnectivityWatcher( grpc_connectivity_state initial_state, OrphanablePtr watcher) { new ConnectivityWatcherAdder(this, initial_state, std::move(watcher)); } -void ChannelData::RemoveConnectivityWatcher( +void ClientChannel::RemoveConnectivityWatcher( AsyncConnectivityStateWatcherInterface* watcher) { new ConnectivityWatcherRemover(this, watcher); } @@ -2636,10 +1861,11 @@ void ChannelData::RemoveConnectivityWatcher( // CallData implementation // -CallData::CallData(grpc_call_element* elem, const ChannelData& chand, - const grpc_call_element_args& args) +ClientChannel::CallData::CallData(grpc_call_element* elem, + const ClientChannel& chand, + const grpc_call_element_args& args) : deadline_state_(elem, args, - GPR_LIKELY(chand.deadline_checking_enabled()) + GPR_LIKELY(chand.deadline_checking_enabled_) ? args.deadline : GRPC_MILLIS_INF_FUTURE), path_(grpc_slice_ref_internal(args.path)), @@ -2654,7 +1880,7 @@ CallData::CallData(grpc_call_element* elem, const ChannelData& chand, } } -CallData::~CallData() { +ClientChannel::CallData::~CallData() { grpc_slice_unref_internal(path_); GRPC_ERROR_UNREF(cancel_error_); // Make sure there are no remaining pending batches. @@ -2663,16 +1889,16 @@ CallData::~CallData() { } } -grpc_error* CallData::Init(grpc_call_element* elem, - const grpc_call_element_args* args) { - ChannelData* chand = static_cast(elem->channel_data); +grpc_error_handle ClientChannel::CallData::Init( + grpc_call_element* elem, const grpc_call_element_args* args) { + ClientChannel* chand = static_cast(elem->channel_data); new (elem->call_data) CallData(elem, *chand, *args); return GRPC_ERROR_NONE; } -void CallData::Destroy(grpc_call_element* elem, - const grpc_call_final_info* /*final_info*/, - grpc_closure* then_schedule_closure) { +void ClientChannel::CallData::Destroy( + grpc_call_element* elem, const grpc_call_final_info* /*final_info*/, + grpc_closure* then_schedule_closure) { CallData* calld = static_cast(elem->call_data); RefCountedPtr dynamic_call = std::move(calld->dynamic_call_); @@ -2685,12 +1911,12 @@ void CallData::Destroy(grpc_call_element* elem, } } -void CallData::StartTransportStreamOpBatch( +void ClientChannel::CallData::StartTransportStreamOpBatch( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { GPR_TIMER_SCOPE("cc_start_transport_stream_op_batch", 0); CallData* calld = static_cast(elem->call_data); - ChannelData* chand = static_cast(elem->channel_data); - if (GPR_LIKELY(chand->deadline_checking_enabled())) { + ClientChannel* chand = static_cast(elem->channel_data); + if (GPR_LIKELY(chand->deadline_checking_enabled_)) { grpc_deadline_state_client_start_transport_stream_op_batch(elem, batch); } // Intercept recv_initial_metadata for config selector on-committed callback. @@ -2701,7 +1927,8 @@ void CallData::StartTransportStreamOpBatch( if (GPR_UNLIKELY(calld->cancel_error_ != GRPC_ERROR_NONE)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: failing batch with error: %s", - chand, calld, grpc_error_string(calld->cancel_error_)); + chand, calld, + grpc_error_std_string(calld->cancel_error_).c_str()); } // Note: This will release the call combiner. grpc_transport_stream_op_batch_finish_with_failure( @@ -2720,7 +1947,7 @@ void CallData::StartTransportStreamOpBatch( GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: recording cancel_error=%s", chand, - calld, grpc_error_string(calld->cancel_error_)); + calld, grpc_error_std_string(calld->cancel_error_).c_str()); } // If we do not have a dynamic call (i.e., name resolution has not // yet completed), fail all pending batches. Otherwise, send the @@ -2774,8 +2001,8 @@ void CallData::StartTransportStreamOpBatch( } } -void CallData::SetPollent(grpc_call_element* elem, - grpc_polling_entity* pollent) { +void ClientChannel::CallData::SetPollent(grpc_call_element* elem, + grpc_polling_entity* pollent) { CallData* calld = static_cast(elem->call_data); calld->pollent_ = pollent; } @@ -2784,9 +2011,11 @@ void CallData::SetPollent(grpc_call_element* elem, // pending_batches management // -size_t CallData::GetBatchIndex(grpc_transport_stream_op_batch* batch) { +size_t ClientChannel::CallData::GetBatchIndex( + grpc_transport_stream_op_batch* batch) { // Note: It is important the send_initial_metadata be the first entry - // here, since the code in pick_subchannel_locked() assumes it will be. + // here, since the code in ApplyServiceConfigToCallLocked() and + // CheckResolutionLocked() assumes it will be. if (batch->send_initial_metadata) return 0; if (batch->send_message) return 1; if (batch->send_trailing_metadata) return 2; @@ -2797,9 +2026,9 @@ size_t CallData::GetBatchIndex(grpc_transport_stream_op_batch* batch) { } // This is called via the call combiner, so access to calld is synchronized. -void CallData::PendingBatchesAdd(grpc_call_element* elem, - grpc_transport_stream_op_batch* batch) { - ChannelData* chand = static_cast(elem->channel_data); +void ClientChannel::CallData::PendingBatchesAdd( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + ClientChannel* chand = static_cast(elem->channel_data); const size_t idx = GetBatchIndex(batch); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, @@ -2812,7 +2041,8 @@ void CallData::PendingBatchesAdd(grpc_call_element* elem, } // This is called via the call combiner, so access to calld is synchronized. -void CallData::FailPendingBatchInCallCombiner(void* arg, grpc_error* error) { +void ClientChannel::CallData::FailPendingBatchInCallCombiner( + void* arg, grpc_error_handle error) { grpc_transport_stream_op_batch* batch = static_cast(arg); CallData* calld = static_cast(batch->handler_private.extra_arg); @@ -2822,8 +2052,8 @@ void CallData::FailPendingBatchInCallCombiner(void* arg, grpc_error* error) { } // This is called via the call combiner, so access to calld is synchronized. -void CallData::PendingBatchesFail( - grpc_call_element* elem, grpc_error* error, +void ClientChannel::CallData::PendingBatchesFail( + grpc_call_element* elem, grpc_error_handle error, YieldCallCombinerPredicate yield_call_combiner_predicate) { GPR_ASSERT(error != GRPC_ERROR_NONE); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { @@ -2833,7 +2063,8 @@ void CallData::PendingBatchesFail( } gpr_log(GPR_INFO, "chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s", - elem->channel_data, this, num_batches, grpc_error_string(error)); + elem->channel_data, this, num_batches, + grpc_error_std_string(error).c_str()); } CallCombinerClosureList closures; for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { @@ -2857,8 +2088,8 @@ void CallData::PendingBatchesFail( } // This is called via the call combiner, so access to calld is synchronized. -void CallData::ResumePendingBatchInCallCombiner(void* arg, - grpc_error* /*ignored*/) { +void ClientChannel::CallData::ResumePendingBatchInCallCombiner( + void* arg, grpc_error_handle /*ignored*/) { grpc_transport_stream_op_batch* batch = static_cast(arg); auto* elem = @@ -2869,8 +2100,8 @@ void CallData::ResumePendingBatchInCallCombiner(void* arg, } // This is called via the call combiner, so access to calld is synchronized. -void CallData::PendingBatchesResume(grpc_call_element* elem) { - ChannelData* chand = static_cast(elem->channel_data); +void ClientChannel::CallData::PendingBatchesResume(grpc_call_element* elem) { + ClientChannel* chand = static_cast(elem->channel_data); // Retries not enabled; send down batches as-is. if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { size_t num_batches = 0; @@ -2904,7 +2135,7 @@ void CallData::PendingBatchesResume(grpc_call_element* elem) { // A class to handle the call combiner cancellation callback for a // queued pick. -class CallData::ResolverQueuedCallCanceller { +class ClientChannel::CallData::ResolverQueuedCallCanceller { public: explicit ResolverQueuedCallCanceller(grpc_call_element* elem) : elem_(elem) { auto* calld = static_cast(elem->call_data); @@ -2915,17 +2146,17 @@ class CallData::ResolverQueuedCallCanceller { } private: - static void CancelLocked(void* arg, grpc_error* error) { + static void CancelLocked(void* arg, grpc_error_handle error) { auto* self = static_cast(arg); - auto* chand = static_cast(self->elem_->channel_data); + auto* chand = static_cast(self->elem_->channel_data); auto* calld = static_cast(self->elem_->call_data); { - MutexLock lock(chand->resolution_mu()); + MutexLock lock(&chand->resolution_mu_); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: cancelling resolver queued pick: " "error=%s self=%p calld->resolver_pick_canceller=%p", - chand, calld, grpc_error_string(error), self, + chand, calld, grpc_error_std_string(error).c_str(), self, calld->resolver_call_canceller_); } if (calld->resolver_call_canceller_ == self && error != GRPC_ERROR_NONE) { @@ -2944,10 +2175,10 @@ class CallData::ResolverQueuedCallCanceller { grpc_closure closure_; }; -void CallData::MaybeRemoveCallFromResolverQueuedCallsLocked( +void ClientChannel::CallData::MaybeRemoveCallFromResolverQueuedCallsLocked( grpc_call_element* elem) { if (!queued_pending_resolver_result_) return; - auto* chand = static_cast(elem->channel_data); + auto* chand = static_cast(elem->channel_data); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p: removing from resolver queued picks list", @@ -2959,1841 +2190,244 @@ void CallData::MaybeRemoveCallFromResolverQueuedCallsLocked( resolver_call_canceller_ = nullptr; } -void CallData::MaybeAddCallToResolverQueuedCallsLocked( +void ClientChannel::CallData::MaybeAddCallToResolverQueuedCallsLocked( grpc_call_element* elem) { if (queued_pending_resolver_result_) return; - auto* chand = static_cast(elem->channel_data); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log(GPR_INFO, "chand=%p calld=%p: adding to resolver queued picks list", - chand, this); - } - queued_pending_resolver_result_ = true; - resolver_queued_call_.elem = elem; - chand->AddResolverQueuedCall(&resolver_queued_call_, pollent_); - // Register call combiner cancellation callback. - resolver_call_canceller_ = new ResolverQueuedCallCanceller(elem); -} - -grpc_error* CallData::ApplyServiceConfigToCallLocked( - grpc_call_element* elem, grpc_metadata_batch* initial_metadata) { - ChannelData* chand = static_cast(elem->channel_data); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call", - chand, this); - } - ConfigSelector* config_selector = chand->config_selector(); - if (config_selector != nullptr) { - // Use the ConfigSelector to determine the config for the call. - ConfigSelector::CallConfig call_config = - config_selector->GetCallConfig({&path_, initial_metadata, arena_}); - if (call_config.error != GRPC_ERROR_NONE) return call_config.error; - on_call_committed_ = std::move(call_config.on_call_committed); - // Create a ServiceConfigCallData for the call. This stores a ref to the - // ServiceConfig and caches the right set of parsed configs to use for - // the call. The MethodConfig will store itself in the call context, - // so that it can be accessed by filters in the subchannel, and it - // will be cleaned up when the call ends. - auto* service_config_call_data = arena_->New( - std::move(call_config.service_config), call_config.method_configs, - std::move(call_config.call_attributes), call_context_); - // Apply our own method params to the call. - auto* method_params = static_cast( - service_config_call_data->GetMethodParsedConfig( - internal::ClientChannelServiceConfigParser::ParserIndex())); - if (method_params != nullptr) { - // If the deadline from the service config is shorter than the one - // from the client API, reset the deadline timer. - if (chand->deadline_checking_enabled() && method_params->timeout() != 0) { - const grpc_millis per_method_deadline = - grpc_cycle_counter_to_millis_round_up(call_start_time_) + - method_params->timeout(); - if (per_method_deadline < deadline_) { - deadline_ = per_method_deadline; - grpc_deadline_state_reset(elem, deadline_); - } - } - // If the service config set wait_for_ready and the application - // did not explicitly set it, use the value from the service config. - uint32_t* send_initial_metadata_flags = - &pending_batches_[0] - ->payload->send_initial_metadata.send_initial_metadata_flags; - if (method_params->wait_for_ready().has_value() && - !(*send_initial_metadata_flags & - GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) { - if (method_params->wait_for_ready().value()) { - *send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY; - } else { - *send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY; - } - } - } - // Set the dynamic filter stack. - dynamic_filters_ = chand->dynamic_filters(); - } - return GRPC_ERROR_NONE; -} - -void CallData::RecvInitialMetadataReadyForConfigSelectorCommitCallback( - void* arg, grpc_error* error) { - auto* self = static_cast(arg); - if (self->on_call_committed_ != nullptr) { - self->on_call_committed_(); - self->on_call_committed_ = nullptr; - } - // Chain to original callback. - Closure::Run(DEBUG_LOCATION, self->original_recv_initial_metadata_ready_, - GRPC_ERROR_REF(error)); -} - -// TODO(roth): Consider not intercepting this callback unless we -// actually need to, if this causes a performance problem. -void CallData::InjectRecvInitialMetadataReadyForConfigSelectorCommitCallback( - grpc_transport_stream_op_batch* batch) { - original_recv_initial_metadata_ready_ = - batch->payload->recv_initial_metadata.recv_initial_metadata_ready; - GRPC_CLOSURE_INIT(&recv_initial_metadata_ready_, - RecvInitialMetadataReadyForConfigSelectorCommitCallback, - this, nullptr); - batch->payload->recv_initial_metadata.recv_initial_metadata_ready = - &recv_initial_metadata_ready_; -} - -void CallData::AsyncResolutionDone(grpc_call_element* elem, grpc_error* error) { - GRPC_CLOSURE_INIT(&pick_closure_, ResolutionDone, elem, nullptr); - ExecCtx::Run(DEBUG_LOCATION, &pick_closure_, error); -} - -void CallData::ResolutionDone(void* arg, grpc_error* error) { - grpc_call_element* elem = static_cast(arg); - ChannelData* chand = static_cast(elem->channel_data); - CallData* calld = static_cast(elem->call_data); - if (error != GRPC_ERROR_NONE) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: error applying config to call: error=%s", - chand, calld, grpc_error_string(error)); - } - calld->PendingBatchesFail(elem, GRPC_ERROR_REF(error), YieldCallCombiner); - return; - } - calld->CreateDynamicCall(elem); -} - -void CallData::CheckResolution(void* arg, grpc_error* error) { - grpc_call_element* elem = static_cast(arg); - CallData* calld = static_cast(elem->call_data); - ChannelData* chand = static_cast(elem->channel_data); - bool resolution_complete; - { - MutexLock lock(chand->resolution_mu()); - resolution_complete = calld->CheckResolutionLocked(elem, &error); - } - if (resolution_complete) { - ResolutionDone(elem, error); - GRPC_ERROR_UNREF(error); - } -} - -bool CallData::CheckResolutionLocked(grpc_call_element* elem, - grpc_error** error) { - ChannelData* chand = static_cast(elem->channel_data); - // If we're still in IDLE, we need to start resolving. - if (GPR_UNLIKELY(chand->CheckConnectivityState(false) == GRPC_CHANNEL_IDLE)) { - // Bounce into the control plane work serializer to start resolving, - // in case we are still in IDLE state. Since we are holding on to the - // resolution mutex here, we offload it on the ExecCtx so that we don't - // deadlock with ourselves. - GRPC_CHANNEL_STACK_REF(chand->owning_stack(), "CheckResolutionLocked"); - ExecCtx::Run( - DEBUG_LOCATION, - GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error* /*error*/) { - auto* chand = static_cast(arg); - chand->work_serializer()->Run( - [chand]() { - chand->CheckConnectivityState(/*try_to_connect=*/true); - GRPC_CHANNEL_STACK_UNREF(chand->owning_stack(), - "CheckResolutionLocked"); - }, - DEBUG_LOCATION); - }, - chand, nullptr), - GRPC_ERROR_NONE); - } - // Get send_initial_metadata batch and flags. - auto& send_initial_metadata = - pending_batches_[0]->payload->send_initial_metadata; - grpc_metadata_batch* initial_metadata_batch = - send_initial_metadata.send_initial_metadata; - const uint32_t send_initial_metadata_flags = - send_initial_metadata.send_initial_metadata_flags; - // If we don't yet have a resolver result, we need to queue the call - // until we get one. - if (GPR_UNLIKELY(!chand->received_service_config_data())) { - // If the resolver returned transient failure before returning the - // first service config, fail any non-wait_for_ready calls. - grpc_error* resolver_error = chand->resolver_transient_failure_error(); - if (resolver_error != GRPC_ERROR_NONE && - (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) == - 0) { - MaybeRemoveCallFromResolverQueuedCallsLocked(elem); - *error = GRPC_ERROR_REF(resolver_error); - return true; - } - // Either the resolver has not yet returned a result, or it has - // returned transient failure but the call is wait_for_ready. In - // either case, queue the call. - MaybeAddCallToResolverQueuedCallsLocked(elem); - return false; - } - // Apply service config to call if not yet applied. - if (GPR_LIKELY(!service_config_applied_)) { - service_config_applied_ = true; - *error = ApplyServiceConfigToCallLocked(elem, initial_metadata_batch); - } - MaybeRemoveCallFromResolverQueuedCallsLocked(elem); - return true; -} - -void CallData::CreateDynamicCall(grpc_call_element* elem) { - auto* chand = static_cast(elem->channel_data); - DynamicFilters::Call::Args args = {std::move(dynamic_filters_), - pollent_, - path_, - call_start_time_, - deadline_, - arena_, - call_context_, - call_combiner_}; - grpc_error* error = GRPC_ERROR_NONE; - DynamicFilters* channel_stack = args.channel_stack.get(); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log( - GPR_INFO, - "chand=%p calld=%p: creating dynamic call stack on channel_stack=%p", - chand, this, channel_stack); - } - dynamic_call_ = channel_stack->CreateCall(std::move(args), &error); - if (error != GRPC_ERROR_NONE) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log(GPR_INFO, - "chand=%p calld=%p: failed to create dynamic call: error=%s", - chand, this, grpc_error_string(error)); - } - PendingBatchesFail(elem, error, YieldCallCombiner); - return; - } - PendingBatchesResume(elem); -} - -// -// RetryingCall implementation -// - -// Retry support: -// -// In order to support retries, we act as a proxy for stream op batches. -// When we get a batch from the surface, we add it to our list of pending -// batches, and we then use those batches to construct separate "child" -// batches to be started on the subchannel call. When the child batches -// return, we then decide which pending batches have been completed and -// schedule their callbacks accordingly. If a subchannel call fails and -// we want to retry it, we do a new pick and start again, constructing -// new "child" batches for the new subchannel call. -// -// Note that retries are committed when receiving data from the server -// (except for Trailers-Only responses). However, there may be many -// send ops started before receiving any data, so we may have already -// completed some number of send ops (and returned the completions up to -// the surface) by the time we realize that we need to retry. To deal -// with this, we cache data for send ops, so that we can replay them on a -// different subchannel call even after we have completed the original -// batches. -// -// There are two sets of data to maintain: -// - In call_data (in the parent channel), we maintain a list of pending -// ops and cached data for send ops. -// - In the subchannel call, we maintain state to indicate what ops have -// already been sent down to that call. -// -// When constructing the "child" batches, we compare those two sets of -// data to see which batches need to be sent to the subchannel call. - -// TODO(roth): In subsequent PRs: -// - add support for transparent retries (including initial metadata) -// - figure out how to record stats in census for retries -// (census filter is on top of this one) -// - add census stats for retries - -RetryingCall::RetryingCall( - ChannelData* chand, const grpc_call_element_args& args, - grpc_polling_entity* pollent, - RefCountedPtr retry_throttle_data, - const ClientChannelMethodParsedConfig::RetryPolicy* retry_policy) - : chand_(chand), - pollent_(pollent), - retry_throttle_data_(std::move(retry_throttle_data)), - retry_policy_(retry_policy), - retry_backoff_( - BackOff::Options() - .set_initial_backoff( - retry_policy_ == nullptr ? 0 : retry_policy_->initial_backoff) - .set_multiplier(retry_policy_ == nullptr - ? 0 - : retry_policy_->backoff_multiplier) - .set_jitter(RETRY_BACKOFF_JITTER) - .set_max_backoff( - retry_policy_ == nullptr ? 0 : retry_policy_->max_backoff)), - path_(grpc_slice_ref_internal(args.path)), - call_start_time_(args.start_time), - deadline_(args.deadline), - arena_(args.arena), - owning_call_(args.call_stack), - call_combiner_(args.call_combiner), - call_context_(args.context), - pending_send_initial_metadata_(false), - pending_send_message_(false), - pending_send_trailing_metadata_(false), - enable_retries_(true), - retry_committed_(false), - last_attempt_got_server_pushback_(false) {} - -RetryingCall::~RetryingCall() { - grpc_slice_unref_internal(path_); - GRPC_ERROR_UNREF(cancel_error_); - // Make sure there are no remaining pending batches. - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - GPR_ASSERT(pending_batches_[i].batch == nullptr); - } -} - -void RetryingCall::StartTransportStreamOpBatch( - grpc_transport_stream_op_batch* batch) { - // If we've previously been cancelled, immediately fail any new batches. - if (GPR_UNLIKELY(cancel_error_ != GRPC_ERROR_NONE)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: failing batch with error: %s", chand_, - this, grpc_error_string(cancel_error_)); - } - // Note: This will release the call combiner. - grpc_transport_stream_op_batch_finish_with_failure( - batch, GRPC_ERROR_REF(cancel_error_), call_combiner_); - return; - } - // Handle cancellation. - if (GPR_UNLIKELY(batch->cancel_stream)) { - // Stash a copy of cancel_error in our call data, so that we can use - // it for subsequent operations. This ensures that if the call is - // cancelled before any batches are passed down (e.g., if the deadline - // is in the past when the call starts), we can return the right - // error to the caller when the first batch does get passed down. - GRPC_ERROR_UNREF(cancel_error_); - cancel_error_ = GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: recording cancel_error=%s", - chand_, this, grpc_error_string(cancel_error_)); - } - // If we do not have an LB call (i.e., a pick has not yet been started), - // fail all pending batches. Otherwise, send the cancellation down to the - // LB call. - if (lb_call_ == nullptr) { - // TODO(roth): If there is a pending retry callback, do we need to - // cancel it here? - PendingBatchesFail(GRPC_ERROR_REF(cancel_error_), NoYieldCallCombiner); - // Note: This will release the call combiner. - grpc_transport_stream_op_batch_finish_with_failure( - batch, GRPC_ERROR_REF(cancel_error_), call_combiner_); - } else { - // Note: This will release the call combiner. - lb_call_->StartTransportStreamOpBatch(batch); - } - return; - } - // Add the batch to the pending list. - PendingBatchesAdd(batch); - // Create LB call if needed. - // TODO(roth): If we get a new batch from the surface after the - // initial retry attempt has failed, while the retry timer is pending, - // we should queue the batch and not try to send it immediately. - if (lb_call_ == nullptr) { - // We do not yet have an LB call, so create one. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: creating LB call", chand_, - this); - } - CreateLbCall(this, GRPC_ERROR_NONE); - return; - } - // Send batches to LB call. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: starting batch on lb_call=%p", - chand_, this, lb_call_.get()); - } - PendingBatchesResume(); -} - -RefCountedPtr RetryingCall::subchannel_call() const { - if (lb_call_ == nullptr) return nullptr; - return lb_call_->subchannel_call(); -} - -// -// send op data caching -// - -void RetryingCall::MaybeCacheSendOpsForBatch(PendingBatch* pending) { - if (pending->send_ops_cached) return; - pending->send_ops_cached = true; - grpc_transport_stream_op_batch* batch = pending->batch; - // Save a copy of metadata for send_initial_metadata ops. - if (batch->send_initial_metadata) { - seen_send_initial_metadata_ = true; - GPR_ASSERT(send_initial_metadata_storage_ == nullptr); - grpc_metadata_batch* send_initial_metadata = - batch->payload->send_initial_metadata.send_initial_metadata; - send_initial_metadata_storage_ = - static_cast(arena_->Alloc( - sizeof(grpc_linked_mdelem) * send_initial_metadata->list.count)); - grpc_metadata_batch_copy(send_initial_metadata, &send_initial_metadata_, - send_initial_metadata_storage_); - send_initial_metadata_flags_ = - batch->payload->send_initial_metadata.send_initial_metadata_flags; - peer_string_ = batch->payload->send_initial_metadata.peer_string; - } - // Set up cache for send_message ops. - if (batch->send_message) { - ByteStreamCache* cache = arena_->New( - std::move(batch->payload->send_message.send_message)); - send_messages_.push_back(cache); - } - // Save metadata batch for send_trailing_metadata ops. - if (batch->send_trailing_metadata) { - seen_send_trailing_metadata_ = true; - GPR_ASSERT(send_trailing_metadata_storage_ == nullptr); - grpc_metadata_batch* send_trailing_metadata = - batch->payload->send_trailing_metadata.send_trailing_metadata; - send_trailing_metadata_storage_ = - static_cast(arena_->Alloc( - sizeof(grpc_linked_mdelem) * send_trailing_metadata->list.count)); - grpc_metadata_batch_copy(send_trailing_metadata, &send_trailing_metadata_, - send_trailing_metadata_storage_); - } -} - -void RetryingCall::FreeCachedSendInitialMetadata() { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: destroying send_initial_metadata", - chand_, this); - } - grpc_metadata_batch_destroy(&send_initial_metadata_); -} - -void RetryingCall::FreeCachedSendMessage(size_t idx) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: destroying send_messages[%" PRIuPTR "]", - chand_, this, idx); - } - send_messages_[idx]->Destroy(); -} - -void RetryingCall::FreeCachedSendTrailingMetadata() { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand_=%p retrying_call=%p: destroying send_trailing_metadata", - chand_, this); - } - grpc_metadata_batch_destroy(&send_trailing_metadata_); -} - -void RetryingCall::FreeCachedSendOpDataAfterCommit( - SubchannelCallRetryState* retry_state) { - if (retry_state->completed_send_initial_metadata) { - FreeCachedSendInitialMetadata(); - } - for (size_t i = 0; i < retry_state->completed_send_message_count; ++i) { - FreeCachedSendMessage(i); - } - if (retry_state->completed_send_trailing_metadata) { - FreeCachedSendTrailingMetadata(); - } -} - -void RetryingCall::FreeCachedSendOpDataForCompletedBatch( - SubchannelCallBatchData* batch_data, - SubchannelCallRetryState* retry_state) { - if (batch_data->batch.send_initial_metadata) { - FreeCachedSendInitialMetadata(); - } - if (batch_data->batch.send_message) { - FreeCachedSendMessage(retry_state->completed_send_message_count - 1); - } - if (batch_data->batch.send_trailing_metadata) { - FreeCachedSendTrailingMetadata(); - } -} - -// -// pending_batches management -// - -size_t RetryingCall::GetBatchIndex(grpc_transport_stream_op_batch* batch) { - // Note: It is important the send_initial_metadata be the first entry - // here, since the code in pick_subchannel_locked() assumes it will be. - if (batch->send_initial_metadata) return 0; - if (batch->send_message) return 1; - if (batch->send_trailing_metadata) return 2; - if (batch->recv_initial_metadata) return 3; - if (batch->recv_message) return 4; - if (batch->recv_trailing_metadata) return 5; - GPR_UNREACHABLE_CODE(return (size_t)-1); -} - -// This is called via the call combiner, so access to calld is synchronized. -void RetryingCall::PendingBatchesAdd(grpc_transport_stream_op_batch* batch) { - const size_t idx = GetBatchIndex(batch); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand_=%p retrying_call=%p: adding pending batch at index %" PRIuPTR, - chand_, this, idx); - } - PendingBatch* pending = &pending_batches_[idx]; - GPR_ASSERT(pending->batch == nullptr); - pending->batch = batch; - pending->send_ops_cached = false; - if (enable_retries_) { - // Update state in calld about pending batches. - // Also check if the batch takes us over the retry buffer limit. - // Note: We don't check the size of trailing metadata here, because - // gRPC clients do not send trailing metadata. - if (batch->send_initial_metadata) { - pending_send_initial_metadata_ = true; - bytes_buffered_for_retry_ += grpc_metadata_batch_size( - batch->payload->send_initial_metadata.send_initial_metadata); - } - if (batch->send_message) { - pending_send_message_ = true; - bytes_buffered_for_retry_ += - batch->payload->send_message.send_message->length(); - } - if (batch->send_trailing_metadata) { - pending_send_trailing_metadata_ = true; - } - if (GPR_UNLIKELY(bytes_buffered_for_retry_ > - chand_->per_rpc_retry_buffer_size())) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: exceeded retry buffer size, " - "committing", - chand_, this); - } - SubchannelCallRetryState* retry_state = - lb_call_ == nullptr ? nullptr - : static_cast( - lb_call_->GetParentData()); - RetryCommit(retry_state); - // If we are not going to retry and have not yet started, pretend - // retries are disabled so that we don't bother with retry overhead. - if (num_attempts_completed_ == 0) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: disabling retries before first " - "attempt", - chand_, this); - } - // TODO(roth): Treat this as a commit? - enable_retries_ = false; - } - } - } -} - -void RetryingCall::PendingBatchClear(PendingBatch* pending) { - if (enable_retries_) { - if (pending->batch->send_initial_metadata) { - pending_send_initial_metadata_ = false; - } - if (pending->batch->send_message) { - pending_send_message_ = false; - } - if (pending->batch->send_trailing_metadata) { - pending_send_trailing_metadata_ = false; - } - } - pending->batch = nullptr; -} - -void RetryingCall::MaybeClearPendingBatch(PendingBatch* pending) { - grpc_transport_stream_op_batch* batch = pending->batch; - // We clear the pending batch if all of its callbacks have been - // scheduled and reset to nullptr. - if (batch->on_complete == nullptr && - (!batch->recv_initial_metadata || - batch->payload->recv_initial_metadata.recv_initial_metadata_ready == - nullptr) && - (!batch->recv_message || - batch->payload->recv_message.recv_message_ready == nullptr) && - (!batch->recv_trailing_metadata || - batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready == - nullptr)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: clearing pending batch", - chand_, this); - } - PendingBatchClear(pending); - } -} - -// This is called via the call combiner, so access to calld is synchronized. -void RetryingCall::FailPendingBatchInCallCombiner(void* arg, - grpc_error* error) { - grpc_transport_stream_op_batch* batch = - static_cast(arg); - RetryingCall* call = - static_cast(batch->handler_private.extra_arg); - // Note: This will release the call combiner. - grpc_transport_stream_op_batch_finish_with_failure( - batch, GRPC_ERROR_REF(error), call->call_combiner_); -} - -// This is called via the call combiner, so access to calld is synchronized. -void RetryingCall::PendingBatchesFail( - grpc_error* error, - YieldCallCombinerPredicate yield_call_combiner_predicate) { - GPR_ASSERT(error != GRPC_ERROR_NONE); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - size_t num_batches = 0; - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - if (pending_batches_[i].batch != nullptr) ++num_batches; - } - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: failing %" PRIuPTR - " pending batches: %s", - chand_, this, num_batches, grpc_error_string(error)); - } - CallCombinerClosureList closures; - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - PendingBatch* pending = &pending_batches_[i]; - grpc_transport_stream_op_batch* batch = pending->batch; - if (batch != nullptr) { - batch->handler_private.extra_arg = this; - GRPC_CLOSURE_INIT(&batch->handler_private.closure, - FailPendingBatchInCallCombiner, batch, - grpc_schedule_on_exec_ctx); - closures.Add(&batch->handler_private.closure, GRPC_ERROR_REF(error), - "PendingBatchesFail"); - PendingBatchClear(pending); - } - } - if (yield_call_combiner_predicate(closures)) { - closures.RunClosures(call_combiner_); - } else { - closures.RunClosuresWithoutYielding(call_combiner_); - } - GRPC_ERROR_UNREF(error); -} - -// This is called via the call combiner, so access to calld is synchronized. -void RetryingCall::ResumePendingBatchInCallCombiner(void* arg, - grpc_error* /*ignored*/) { - grpc_transport_stream_op_batch* batch = - static_cast(arg); - auto* lb_call = - static_cast(batch->handler_private.extra_arg); - // Note: This will release the call combiner. - lb_call->StartTransportStreamOpBatch(batch); -} - -// This is called via the call combiner, so access to calld is synchronized. -void RetryingCall::PendingBatchesResume() { - if (enable_retries_) { - StartRetriableSubchannelBatches(this, GRPC_ERROR_NONE); - return; - } - // Retries not enabled; send down batches as-is. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - size_t num_batches = 0; - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - if (pending_batches_[i].batch != nullptr) ++num_batches; - } - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: starting %" PRIuPTR - " pending batches on lb_call=%p", - chand_, this, num_batches, lb_call_.get()); - } - CallCombinerClosureList closures; - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - PendingBatch* pending = &pending_batches_[i]; - grpc_transport_stream_op_batch* batch = pending->batch; - if (batch != nullptr) { - batch->handler_private.extra_arg = lb_call_.get(); - GRPC_CLOSURE_INIT(&batch->handler_private.closure, - ResumePendingBatchInCallCombiner, batch, nullptr); - closures.Add(&batch->handler_private.closure, GRPC_ERROR_NONE, - "PendingBatchesResume"); - PendingBatchClear(pending); - } - } - // Note: This will release the call combiner. - closures.RunClosures(call_combiner_); -} - -template -RetryingCall::PendingBatch* RetryingCall::PendingBatchFind( - const char* log_message, Predicate predicate) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - PendingBatch* pending = &pending_batches_[i]; - grpc_transport_stream_op_batch* batch = pending->batch; - if (batch != nullptr && predicate(batch)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: %s pending batch at index %" PRIuPTR, - chand_, this, log_message, i); - } - return pending; - } - } - return nullptr; -} - -// -// retry code -// - -void RetryingCall::RetryCommit(SubchannelCallRetryState* retry_state) { - if (retry_committed_) return; - retry_committed_ = true; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: committing retries", chand_, - this); - } - if (retry_state != nullptr) { - FreeCachedSendOpDataAfterCommit(retry_state); - } -} - -void RetryingCall::DoRetry(SubchannelCallRetryState* retry_state, - grpc_millis server_pushback_ms) { - GPR_ASSERT(retry_policy_ != nullptr); - // Reset LB call. - lb_call_.reset(); - // Compute backoff delay. - grpc_millis next_attempt_time; - if (server_pushback_ms >= 0) { - next_attempt_time = ExecCtx::Get()->Now() + server_pushback_ms; - last_attempt_got_server_pushback_ = true; - } else { - if (num_attempts_completed_ == 1 || last_attempt_got_server_pushback_) { - last_attempt_got_server_pushback_ = false; - } - next_attempt_time = retry_backoff_.NextAttemptTime(); - } - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: retrying failed call in %" PRId64 " ms", - chand_, this, next_attempt_time - ExecCtx::Get()->Now()); - } - // Schedule retry after computed delay. - GRPC_CLOSURE_INIT(&retry_closure_, CreateLbCall, this, nullptr); - grpc_timer_init(&retry_timer_, next_attempt_time, &retry_closure_); - // Update bookkeeping. - if (retry_state != nullptr) retry_state->retry_dispatched = true; -} - -bool RetryingCall::MaybeRetry(SubchannelCallBatchData* batch_data, - grpc_status_code status, - grpc_mdelem* server_pushback_md) { - // Get retry policy. - if (retry_policy_ == nullptr) return false; - // If we've already dispatched a retry from this call, return true. - // This catches the case where the batch has multiple callbacks - // (i.e., it includes either recv_message or recv_initial_metadata). - SubchannelCallRetryState* retry_state = nullptr; - if (batch_data != nullptr) { - retry_state = static_cast( - batch_data->lb_call->GetParentData()); - if (retry_state->retry_dispatched) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: retry already dispatched", - chand_, this); - } - return true; - } - } - // Check status. - if (GPR_LIKELY(status == GRPC_STATUS_OK)) { - if (retry_throttle_data_ != nullptr) { - retry_throttle_data_->RecordSuccess(); - } - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: call succeeded", chand_, - this); - } - return false; - } - // Status is not OK. Check whether the status is retryable. - if (!retry_policy_->retryable_status_codes.Contains(status)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: status %s not configured as retryable", - chand_, this, grpc_status_code_to_string(status)); - } - return false; - } - // Record the failure and check whether retries are throttled. - // Note that it's important for this check to come after the status - // code check above, since we should only record failures whose statuses - // match the configured retryable status codes, so that we don't count - // things like failures due to malformed requests (INVALID_ARGUMENT). - // Conversely, it's important for this to come before the remaining - // checks, so that we don't fail to record failures due to other factors. - if (retry_throttle_data_ != nullptr && - !retry_throttle_data_->RecordFailure()) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: retries throttled", chand_, - this); - } - return false; - } - // Check whether the call is committed. - if (retry_committed_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: retries already committed", - chand_, this); - } - return false; - } - // Check whether we have retries remaining. - ++num_attempts_completed_; - if (num_attempts_completed_ >= retry_policy_->max_attempts) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: exceeded %d retry attempts", - chand_, this, retry_policy_->max_attempts); - } - return false; - } - // If the call was cancelled from the surface, don't retry. - if (cancel_error_ != GRPC_ERROR_NONE) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: call cancelled from surface, not " - "retrying", - chand_, this); - } - return false; - } - // Check server push-back. - grpc_millis server_pushback_ms = -1; - if (server_pushback_md != nullptr) { - // If the value is "-1" or any other unparseable string, we do not retry. - uint32_t ms; - if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(*server_pushback_md), &ms)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: not retrying due to server push-back", - chand_, this); - } - return false; - } else { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: server push-back: retry in %u ms", - chand_, this, ms); - } - server_pushback_ms = static_cast(ms); - } - } - DoRetry(retry_state, server_pushback_ms); - return true; -} - -// -// RetryingCall::SubchannelCallBatchData -// - -RetryingCall::SubchannelCallBatchData* -RetryingCall::SubchannelCallBatchData::Create(RetryingCall* call, int refcount, - bool set_on_complete) { - return call->arena_->New(call, refcount, - set_on_complete); -} - -RetryingCall::SubchannelCallBatchData::SubchannelCallBatchData( - RetryingCall* call, int refcount, bool set_on_complete) - : call(call), lb_call(call->lb_call_) { - SubchannelCallRetryState* retry_state = - static_cast(lb_call->GetParentData()); - batch.payload = &retry_state->batch_payload; - gpr_ref_init(&refs, refcount); - if (set_on_complete) { - GRPC_CLOSURE_INIT(&on_complete, RetryingCall::OnComplete, this, - grpc_schedule_on_exec_ctx); - batch.on_complete = &on_complete; - } - GRPC_CALL_STACK_REF(call->owning_call_, "batch_data"); -} - -void RetryingCall::SubchannelCallBatchData::Destroy() { - SubchannelCallRetryState* retry_state = - static_cast(lb_call->GetParentData()); - if (batch.send_initial_metadata) { - grpc_metadata_batch_destroy(&retry_state->send_initial_metadata); - } - if (batch.send_trailing_metadata) { - grpc_metadata_batch_destroy(&retry_state->send_trailing_metadata); - } - if (batch.recv_initial_metadata) { - grpc_metadata_batch_destroy(&retry_state->recv_initial_metadata); - } - if (batch.recv_trailing_metadata) { - grpc_metadata_batch_destroy(&retry_state->recv_trailing_metadata); - } - lb_call.reset(); - GRPC_CALL_STACK_UNREF(call->owning_call_, "batch_data"); -} - -// -// recv_initial_metadata callback handling -// - -void RetryingCall::InvokeRecvInitialMetadataCallback(void* arg, - grpc_error* error) { - SubchannelCallBatchData* batch_data = - static_cast(arg); - // Find pending batch. - PendingBatch* pending = batch_data->call->PendingBatchFind( - "invoking recv_initial_metadata_ready for", - [](grpc_transport_stream_op_batch* batch) { - return batch->recv_initial_metadata && - batch->payload->recv_initial_metadata - .recv_initial_metadata_ready != nullptr; - }); - GPR_ASSERT(pending != nullptr); - // Return metadata. - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - grpc_metadata_batch_move( - &retry_state->recv_initial_metadata, - pending->batch->payload->recv_initial_metadata.recv_initial_metadata); - // Update bookkeeping. - // Note: Need to do this before invoking the callback, since invoking - // the callback will result in yielding the call combiner. - grpc_closure* recv_initial_metadata_ready = - pending->batch->payload->recv_initial_metadata - .recv_initial_metadata_ready; - pending->batch->payload->recv_initial_metadata.recv_initial_metadata_ready = - nullptr; - batch_data->call->MaybeClearPendingBatch(pending); - batch_data->Unref(); - // Invoke callback. - Closure::Run(DEBUG_LOCATION, recv_initial_metadata_ready, - GRPC_ERROR_REF(error)); -} - -void RetryingCall::RecvInitialMetadataReady(void* arg, grpc_error* error) { - SubchannelCallBatchData* batch_data = - static_cast(arg); - RetryingCall* call = batch_data->call; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: got recv_initial_metadata_ready, error=%s", - call->chand_, call, grpc_error_string(error)); - } - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - retry_state->completed_recv_initial_metadata = true; - // If a retry was already dispatched, then we're not going to use the - // result of this recv_initial_metadata op, so do nothing. - if (retry_state->retry_dispatched) { - GRPC_CALL_COMBINER_STOP( - call->call_combiner_, - "recv_initial_metadata_ready after retry dispatched"); - return; - } - // If we got an error or a Trailers-Only response and have not yet gotten - // the recv_trailing_metadata_ready callback, then defer propagating this - // callback back to the surface. We can evaluate whether to retry when - // recv_trailing_metadata comes back. - if (GPR_UNLIKELY((retry_state->trailing_metadata_available || - error != GRPC_ERROR_NONE) && - !retry_state->completed_recv_trailing_metadata)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: deferring recv_initial_metadata_ready " - "(Trailers-Only)", - call->chand_, call); - } - retry_state->recv_initial_metadata_ready_deferred_batch = batch_data; - retry_state->recv_initial_metadata_error = GRPC_ERROR_REF(error); - if (!retry_state->started_recv_trailing_metadata) { - // recv_trailing_metadata not yet started by application; start it - // ourselves to get status. - call->StartInternalRecvTrailingMetadata(); - } else { - GRPC_CALL_COMBINER_STOP( - call->call_combiner_, - "recv_initial_metadata_ready trailers-only or error"); - } - return; - } - // Received valid initial metadata, so commit the call. - call->RetryCommit(retry_state); - // Invoke the callback to return the result to the surface. - // Manually invoking a callback function; it does not take ownership of error. - call->InvokeRecvInitialMetadataCallback(batch_data, error); -} - -// -// recv_message callback handling -// - -void RetryingCall::InvokeRecvMessageCallback(void* arg, grpc_error* error) { - SubchannelCallBatchData* batch_data = - static_cast(arg); - RetryingCall* call = batch_data->call; - // Find pending op. - PendingBatch* pending = call->PendingBatchFind( - "invoking recv_message_ready for", - [](grpc_transport_stream_op_batch* batch) { - return batch->recv_message && - batch->payload->recv_message.recv_message_ready != nullptr; - }); - GPR_ASSERT(pending != nullptr); - // Return payload. - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - *pending->batch->payload->recv_message.recv_message = - std::move(retry_state->recv_message); - // Update bookkeeping. - // Note: Need to do this before invoking the callback, since invoking - // the callback will result in yielding the call combiner. - grpc_closure* recv_message_ready = - pending->batch->payload->recv_message.recv_message_ready; - pending->batch->payload->recv_message.recv_message_ready = nullptr; - call->MaybeClearPendingBatch(pending); - batch_data->Unref(); - // Invoke callback. - Closure::Run(DEBUG_LOCATION, recv_message_ready, GRPC_ERROR_REF(error)); -} - -void RetryingCall::RecvMessageReady(void* arg, grpc_error* error) { - SubchannelCallBatchData* batch_data = - static_cast(arg); - RetryingCall* call = batch_data->call; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: got recv_message_ready, error=%s", - call->chand_, call, grpc_error_string(error)); - } - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - ++retry_state->completed_recv_message_count; - // If a retry was already dispatched, then we're not going to use the - // result of this recv_message op, so do nothing. - if (retry_state->retry_dispatched) { - GRPC_CALL_COMBINER_STOP(call->call_combiner_, - "recv_message_ready after retry dispatched"); - return; - } - // If we got an error or the payload was nullptr and we have not yet gotten - // the recv_trailing_metadata_ready callback, then defer propagating this - // callback back to the surface. We can evaluate whether to retry when - // recv_trailing_metadata comes back. - if (GPR_UNLIKELY( - (retry_state->recv_message == nullptr || error != GRPC_ERROR_NONE) && - !retry_state->completed_recv_trailing_metadata)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: deferring recv_message_ready (nullptr " - "message and recv_trailing_metadata pending)", - call->chand_, call); - } - retry_state->recv_message_ready_deferred_batch = batch_data; - retry_state->recv_message_error = GRPC_ERROR_REF(error); - if (!retry_state->started_recv_trailing_metadata) { - // recv_trailing_metadata not yet started by application; start it - // ourselves to get status. - call->StartInternalRecvTrailingMetadata(); - } else { - GRPC_CALL_COMBINER_STOP(call->call_combiner_, "recv_message_ready null"); - } - return; - } - // Received a valid message, so commit the call. - call->RetryCommit(retry_state); - // Invoke the callback to return the result to the surface. - // Manually invoking a callback function; it does not take ownership of error. - call->InvokeRecvMessageCallback(batch_data, error); -} - -// -// recv_trailing_metadata handling -// - -void RetryingCall::GetCallStatus(grpc_metadata_batch* md_batch, - grpc_error* error, grpc_status_code* status, - grpc_mdelem** server_pushback_md) { - if (error != GRPC_ERROR_NONE) { - grpc_error_get_status(error, deadline_, status, nullptr, nullptr, nullptr); - } else { - GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr); - *status = - grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md); - if (server_pushback_md != nullptr && - md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { - *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md; - } - } - GRPC_ERROR_UNREF(error); -} - -void RetryingCall::AddClosureForRecvTrailingMetadataReady( - SubchannelCallBatchData* batch_data, grpc_error* error, - CallCombinerClosureList* closures) { - // Find pending batch. - PendingBatch* pending = PendingBatchFind( - "invoking recv_trailing_metadata for", - [](grpc_transport_stream_op_batch* batch) { - return batch->recv_trailing_metadata && - batch->payload->recv_trailing_metadata - .recv_trailing_metadata_ready != nullptr; - }); - // If we generated the recv_trailing_metadata op internally via - // StartInternalRecvTrailingMetadata(), then there will be no pending batch. - if (pending == nullptr) { - GRPC_ERROR_UNREF(error); - return; - } - // Return metadata. - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - grpc_metadata_batch_move( - &retry_state->recv_trailing_metadata, - pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata); - // Add closure. - closures->Add(pending->batch->payload->recv_trailing_metadata - .recv_trailing_metadata_ready, - error, "recv_trailing_metadata_ready for pending batch"); - // Update bookkeeping. - pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = - nullptr; - MaybeClearPendingBatch(pending); -} - -void RetryingCall::AddClosuresForDeferredRecvCallbacks( - SubchannelCallBatchData* batch_data, SubchannelCallRetryState* retry_state, - CallCombinerClosureList* closures) { - if (batch_data->batch.recv_trailing_metadata) { - // Add closure for deferred recv_initial_metadata_ready. - if (GPR_UNLIKELY(retry_state->recv_initial_metadata_ready_deferred_batch != - nullptr)) { - GRPC_CLOSURE_INIT(&retry_state->recv_initial_metadata_ready, - InvokeRecvInitialMetadataCallback, - retry_state->recv_initial_metadata_ready_deferred_batch, - grpc_schedule_on_exec_ctx); - closures->Add(&retry_state->recv_initial_metadata_ready, - retry_state->recv_initial_metadata_error, - "resuming recv_initial_metadata_ready"); - retry_state->recv_initial_metadata_ready_deferred_batch = nullptr; - } - // Add closure for deferred recv_message_ready. - if (GPR_UNLIKELY(retry_state->recv_message_ready_deferred_batch != - nullptr)) { - GRPC_CLOSURE_INIT(&retry_state->recv_message_ready, - InvokeRecvMessageCallback, - retry_state->recv_message_ready_deferred_batch, - grpc_schedule_on_exec_ctx); - closures->Add(&retry_state->recv_message_ready, - retry_state->recv_message_error, - "resuming recv_message_ready"); - retry_state->recv_message_ready_deferred_batch = nullptr; - } - } -} - -bool RetryingCall::PendingBatchIsUnstarted( - PendingBatch* pending, SubchannelCallRetryState* retry_state) { - if (pending->batch == nullptr || pending->batch->on_complete == nullptr) { - return false; - } - if (pending->batch->send_initial_metadata && - !retry_state->started_send_initial_metadata) { - return true; - } - if (pending->batch->send_message && - retry_state->started_send_message_count < send_messages_.size()) { - return true; - } - if (pending->batch->send_trailing_metadata && - !retry_state->started_send_trailing_metadata) { - return true; - } - return false; -} - -void RetryingCall::AddClosuresToFailUnstartedPendingBatches( - SubchannelCallRetryState* retry_state, grpc_error* error, - CallCombinerClosureList* closures) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - PendingBatch* pending = &pending_batches_[i]; - if (PendingBatchIsUnstarted(pending, retry_state)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: failing unstarted pending batch at " - "index " - "%" PRIuPTR, - chand_, this, i); - } - closures->Add(pending->batch->on_complete, GRPC_ERROR_REF(error), - "failing on_complete for pending batch"); - pending->batch->on_complete = nullptr; - MaybeClearPendingBatch(pending); - } - } - GRPC_ERROR_UNREF(error); -} - -void RetryingCall::RunClosuresForCompletedCall( - SubchannelCallBatchData* batch_data, grpc_error* error) { - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - // Construct list of closures to execute. - CallCombinerClosureList closures; - // First, add closure for recv_trailing_metadata_ready. - AddClosureForRecvTrailingMetadataReady(batch_data, GRPC_ERROR_REF(error), - &closures); - // If there are deferred recv_initial_metadata_ready or recv_message_ready - // callbacks, add them to closures. - AddClosuresForDeferredRecvCallbacks(batch_data, retry_state, &closures); - // Add closures to fail any pending batches that have not yet been started. - AddClosuresToFailUnstartedPendingBatches(retry_state, GRPC_ERROR_REF(error), - &closures); - // Don't need batch_data anymore. - batch_data->Unref(); - // Schedule all of the closures identified above. - // Note: This will release the call combiner. - closures.RunClosures(call_combiner_); - GRPC_ERROR_UNREF(error); -} - -void RetryingCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) { - SubchannelCallBatchData* batch_data = - static_cast(arg); - RetryingCall* call = batch_data->call; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: got recv_trailing_metadata_ready, error=%s", - call->chand_, call, grpc_error_string(error)); - } - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - retry_state->completed_recv_trailing_metadata = true; - // Get the call's status and check for server pushback metadata. - grpc_status_code status = GRPC_STATUS_OK; - grpc_mdelem* server_pushback_md = nullptr; - grpc_metadata_batch* md_batch = - batch_data->batch.payload->recv_trailing_metadata.recv_trailing_metadata; - call->GetCallStatus(md_batch, GRPC_ERROR_REF(error), &status, - &server_pushback_md); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: call finished, status=%s", - call->chand_, call, grpc_status_code_to_string(status)); - } - // Check if we should retry. - if (call->MaybeRetry(batch_data, status, server_pushback_md)) { - // Unref batch_data for deferred recv_initial_metadata_ready or - // recv_message_ready callbacks, if any. - if (retry_state->recv_initial_metadata_ready_deferred_batch != nullptr) { - batch_data->Unref(); - GRPC_ERROR_UNREF(retry_state->recv_initial_metadata_error); - } - if (retry_state->recv_message_ready_deferred_batch != nullptr) { - batch_data->Unref(); - GRPC_ERROR_UNREF(retry_state->recv_message_error); - } - batch_data->Unref(); - return; - } - // Not retrying, so commit the call. - call->RetryCommit(retry_state); - // Run any necessary closures. - call->RunClosuresForCompletedCall(batch_data, GRPC_ERROR_REF(error)); -} - -// -// on_complete callback handling -// - -void RetryingCall::AddClosuresForCompletedPendingBatch( - SubchannelCallBatchData* batch_data, grpc_error* error, - CallCombinerClosureList* closures) { - PendingBatch* pending = PendingBatchFind( - "completed", [batch_data](grpc_transport_stream_op_batch* batch) { - // Match the pending batch with the same set of send ops as the - // subchannel batch we've just completed. - return batch->on_complete != nullptr && - batch_data->batch.send_initial_metadata == - batch->send_initial_metadata && - batch_data->batch.send_message == batch->send_message && - batch_data->batch.send_trailing_metadata == - batch->send_trailing_metadata; - }); - // If batch_data is a replay batch, then there will be no pending - // batch to complete. - if (pending == nullptr) { - GRPC_ERROR_UNREF(error); - return; - } - // Add closure. - closures->Add(pending->batch->on_complete, error, - "on_complete for pending batch"); - pending->batch->on_complete = nullptr; - MaybeClearPendingBatch(pending); -} - -void RetryingCall::AddClosuresForReplayOrPendingSendOps( - SubchannelCallBatchData* batch_data, SubchannelCallRetryState* retry_state, - CallCombinerClosureList* closures) { - bool have_pending_send_message_ops = - retry_state->started_send_message_count < send_messages_.size(); - bool have_pending_send_trailing_metadata_op = - seen_send_trailing_metadata_ && - !retry_state->started_send_trailing_metadata; - if (!have_pending_send_message_ops && - !have_pending_send_trailing_metadata_op) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - PendingBatch* pending = &pending_batches_[i]; - grpc_transport_stream_op_batch* batch = pending->batch; - if (batch == nullptr || pending->send_ops_cached) continue; - if (batch->send_message) have_pending_send_message_ops = true; - if (batch->send_trailing_metadata) { - have_pending_send_trailing_metadata_op = true; - } - } - } - if (have_pending_send_message_ops || have_pending_send_trailing_metadata_op) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: starting next batch for pending send " - "op(s)", - chand_, this); - } - GRPC_CLOSURE_INIT(&batch_data->batch.handler_private.closure, - StartRetriableSubchannelBatches, this, - grpc_schedule_on_exec_ctx); - closures->Add(&batch_data->batch.handler_private.closure, GRPC_ERROR_NONE, - "starting next batch for send_* op(s)"); - } -} - -void RetryingCall::OnComplete(void* arg, grpc_error* error) { - SubchannelCallBatchData* batch_data = - static_cast(arg); - RetryingCall* call = batch_data->call; - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: got on_complete, error=%s, batch=%s", - call->chand_, call, grpc_error_string(error), - grpc_transport_stream_op_batch_string(&batch_data->batch).c_str()); - } - SubchannelCallRetryState* retry_state = - static_cast( - batch_data->lb_call->GetParentData()); - // Update bookkeeping in retry_state. - if (batch_data->batch.send_initial_metadata) { - retry_state->completed_send_initial_metadata = true; - } - if (batch_data->batch.send_message) { - ++retry_state->completed_send_message_count; - } - if (batch_data->batch.send_trailing_metadata) { - retry_state->completed_send_trailing_metadata = true; - } - // If the call is committed, free cached data for send ops that we've just - // completed. - if (call->retry_committed_) { - call->FreeCachedSendOpDataForCompletedBatch(batch_data, retry_state); - } - // Construct list of closures to execute. - CallCombinerClosureList closures; - // If a retry was already dispatched, that means we saw - // recv_trailing_metadata before this, so we do nothing here. - // Otherwise, invoke the callback to return the result to the surface. - if (!retry_state->retry_dispatched) { - // Add closure for the completed pending batch, if any. - call->AddClosuresForCompletedPendingBatch(batch_data, GRPC_ERROR_REF(error), - &closures); - // If needed, add a callback to start any replay or pending send ops on - // the subchannel call. - if (!retry_state->completed_recv_trailing_metadata) { - call->AddClosuresForReplayOrPendingSendOps(batch_data, retry_state, - &closures); - } - } - // Track number of pending subchannel send batches and determine if this - // was the last one. - --call->num_pending_retriable_subchannel_send_batches_; - const bool last_send_batch_complete = - call->num_pending_retriable_subchannel_send_batches_ == 0; - // Don't need batch_data anymore. - batch_data->Unref(); - // Schedule all of the closures identified above. - // Note: This yeilds the call combiner. - closures.RunClosures(call->call_combiner_); - // If this was the last subchannel send batch, unref the call stack. - if (last_send_batch_complete) { - GRPC_CALL_STACK_UNREF(call->owning_call_, "subchannel_send_batches"); - } -} - -// -// subchannel batch construction -// - -void RetryingCall::StartBatchInCallCombiner(void* arg, - grpc_error* /*ignored*/) { - grpc_transport_stream_op_batch* batch = - static_cast(arg); - auto* lb_call = - static_cast(batch->handler_private.extra_arg); - // Note: This will release the call combiner. - lb_call->StartTransportStreamOpBatch(batch); -} - -void RetryingCall::AddClosureForSubchannelBatch( - grpc_transport_stream_op_batch* batch, CallCombinerClosureList* closures) { - batch->handler_private.extra_arg = lb_call_.get(); - GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner, - batch, grpc_schedule_on_exec_ctx); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: starting subchannel batch: %s", chand_, - this, grpc_transport_stream_op_batch_string(batch).c_str()); + auto* chand = static_cast(elem->channel_data); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: adding to resolver queued picks list", + chand, this); } - closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE, - "start_subchannel_batch"); + queued_pending_resolver_result_ = true; + resolver_queued_call_.elem = elem; + chand->AddResolverQueuedCall(&resolver_queued_call_, pollent_); + // Register call combiner cancellation callback. + resolver_call_canceller_ = new ResolverQueuedCallCanceller(elem); } -void RetryingCall::AddRetriableSendInitialMetadataOp( - SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data) { - // Maps the number of retries to the corresponding metadata value slice. - const grpc_slice* retry_count_strings[] = {&GRPC_MDSTR_1, &GRPC_MDSTR_2, - &GRPC_MDSTR_3, &GRPC_MDSTR_4}; - // We need to make a copy of the metadata batch for each attempt, since - // the filters in the subchannel stack may modify this batch, and we don't - // want those modifications to be passed forward to subsequent attempts. - // - // If we've already completed one or more attempts, add the - // grpc-retry-attempts header. - retry_state->send_initial_metadata_storage = - static_cast(arena_->Alloc( - sizeof(grpc_linked_mdelem) * - (send_initial_metadata_.list.count + (num_attempts_completed_ > 0)))); - grpc_metadata_batch_copy(&send_initial_metadata_, - &retry_state->send_initial_metadata, - retry_state->send_initial_metadata_storage); - if (GPR_UNLIKELY(retry_state->send_initial_metadata.idx.named - .grpc_previous_rpc_attempts != nullptr)) { - grpc_metadata_batch_remove(&retry_state->send_initial_metadata, - GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS); - } - if (GPR_UNLIKELY(num_attempts_completed_ > 0)) { - grpc_mdelem retry_md = grpc_mdelem_create( - GRPC_MDSTR_GRPC_PREVIOUS_RPC_ATTEMPTS, - *retry_count_strings[num_attempts_completed_ - 1], nullptr); - grpc_error* error = grpc_metadata_batch_add_tail( - &retry_state->send_initial_metadata, - &retry_state - ->send_initial_metadata_storage[send_initial_metadata_.list.count], - retry_md, GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS); - if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { - gpr_log(GPR_ERROR, "error adding retry metadata: %s", - grpc_error_string(error)); - GPR_ASSERT(false); +grpc_error_handle ClientChannel::CallData::ApplyServiceConfigToCallLocked( + grpc_call_element* elem, grpc_metadata_batch* initial_metadata) { + ClientChannel* chand = static_cast(elem->channel_data); + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call", + chand, this); + } + ConfigSelector* config_selector = chand->config_selector_.get(); + if (config_selector != nullptr) { + // Use the ConfigSelector to determine the config for the call. + ConfigSelector::CallConfig call_config = + config_selector->GetCallConfig({&path_, initial_metadata, arena_}); + if (call_config.error != GRPC_ERROR_NONE) return call_config.error; + on_call_committed_ = std::move(call_config.on_call_committed); + // Create a ServiceConfigCallData for the call. This stores a ref to the + // ServiceConfig and caches the right set of parsed configs to use for + // the call. The MethodConfig will store itself in the call context, + // so that it can be accessed by filters in the subchannel, and it + // will be cleaned up when the call ends. + auto* service_config_call_data = arena_->New( + std::move(call_config.service_config), call_config.method_configs, + std::move(call_config.call_attributes), call_context_); + // Apply our own method params to the call. + auto* method_params = static_cast( + service_config_call_data->GetMethodParsedConfig( + internal::ClientChannelServiceConfigParser::ParserIndex())); + if (method_params != nullptr) { + // If the deadline from the service config is shorter than the one + // from the client API, reset the deadline timer. + if (chand->deadline_checking_enabled_ && method_params->timeout() != 0) { + const grpc_millis per_method_deadline = + grpc_cycle_counter_to_millis_round_up(call_start_time_) + + method_params->timeout(); + if (per_method_deadline < deadline_) { + deadline_ = per_method_deadline; + grpc_deadline_state_reset(elem, deadline_); + } + } + // If the service config set wait_for_ready and the application + // did not explicitly set it, use the value from the service config. + uint32_t* send_initial_metadata_flags = + &pending_batches_[0] + ->payload->send_initial_metadata.send_initial_metadata_flags; + if (method_params->wait_for_ready().has_value() && + !(*send_initial_metadata_flags & + GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET)) { + if (method_params->wait_for_ready().value()) { + *send_initial_metadata_flags |= GRPC_INITIAL_METADATA_WAIT_FOR_READY; + } else { + *send_initial_metadata_flags &= ~GRPC_INITIAL_METADATA_WAIT_FOR_READY; + } + } } + // Set the dynamic filter stack. + dynamic_filters_ = chand->dynamic_filters_; } - retry_state->started_send_initial_metadata = true; - batch_data->batch.send_initial_metadata = true; - batch_data->batch.payload->send_initial_metadata.send_initial_metadata = - &retry_state->send_initial_metadata; - batch_data->batch.payload->send_initial_metadata.send_initial_metadata_flags = - send_initial_metadata_flags_; - batch_data->batch.payload->send_initial_metadata.peer_string = peer_string_; -} - -void RetryingCall::AddRetriableSendMessageOp( - SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: starting calld->send_messages[%" PRIuPTR - "]", - chand_, this, retry_state->started_send_message_count); - } - ByteStreamCache* cache = - send_messages_[retry_state->started_send_message_count]; - ++retry_state->started_send_message_count; - retry_state->send_message.Init(cache); - batch_data->batch.send_message = true; - batch_data->batch.payload->send_message.send_message.reset( - retry_state->send_message.get()); -} - -void RetryingCall::AddRetriableSendTrailingMetadataOp( - SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data) { - // We need to make a copy of the metadata batch for each attempt, since - // the filters in the subchannel stack may modify this batch, and we don't - // want those modifications to be passed forward to subsequent attempts. - retry_state->send_trailing_metadata_storage = - static_cast(arena_->Alloc( - sizeof(grpc_linked_mdelem) * send_trailing_metadata_.list.count)); - grpc_metadata_batch_copy(&send_trailing_metadata_, - &retry_state->send_trailing_metadata, - retry_state->send_trailing_metadata_storage); - retry_state->started_send_trailing_metadata = true; - batch_data->batch.send_trailing_metadata = true; - batch_data->batch.payload->send_trailing_metadata.send_trailing_metadata = - &retry_state->send_trailing_metadata; -} - -void RetryingCall::AddRetriableRecvInitialMetadataOp( - SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data) { - retry_state->started_recv_initial_metadata = true; - batch_data->batch.recv_initial_metadata = true; - grpc_metadata_batch_init(&retry_state->recv_initial_metadata); - batch_data->batch.payload->recv_initial_metadata.recv_initial_metadata = - &retry_state->recv_initial_metadata; - batch_data->batch.payload->recv_initial_metadata.trailing_metadata_available = - &retry_state->trailing_metadata_available; - GRPC_CLOSURE_INIT(&retry_state->recv_initial_metadata_ready, - RecvInitialMetadataReady, batch_data, - grpc_schedule_on_exec_ctx); - batch_data->batch.payload->recv_initial_metadata.recv_initial_metadata_ready = - &retry_state->recv_initial_metadata_ready; + return GRPC_ERROR_NONE; } -void RetryingCall::AddRetriableRecvMessageOp( - SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data) { - ++retry_state->started_recv_message_count; - batch_data->batch.recv_message = true; - batch_data->batch.payload->recv_message.recv_message = - &retry_state->recv_message; - GRPC_CLOSURE_INIT(&retry_state->recv_message_ready, RecvMessageReady, - batch_data, grpc_schedule_on_exec_ctx); - batch_data->batch.payload->recv_message.recv_message_ready = - &retry_state->recv_message_ready; +void ClientChannel::CallData:: + RecvInitialMetadataReadyForConfigSelectorCommitCallback( + void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + if (self->on_call_committed_ != nullptr) { + self->on_call_committed_(); + self->on_call_committed_ = nullptr; + } + // Chain to original callback. + Closure::Run(DEBUG_LOCATION, self->original_recv_initial_metadata_ready_, + GRPC_ERROR_REF(error)); } -void RetryingCall::AddRetriableRecvTrailingMetadataOp( - SubchannelCallRetryState* retry_state, - SubchannelCallBatchData* batch_data) { - retry_state->started_recv_trailing_metadata = true; - batch_data->batch.recv_trailing_metadata = true; - grpc_metadata_batch_init(&retry_state->recv_trailing_metadata); - batch_data->batch.payload->recv_trailing_metadata.recv_trailing_metadata = - &retry_state->recv_trailing_metadata; - batch_data->batch.payload->recv_trailing_metadata.collect_stats = - &retry_state->collect_stats; - GRPC_CLOSURE_INIT(&retry_state->recv_trailing_metadata_ready, - RecvTrailingMetadataReady, batch_data, - grpc_schedule_on_exec_ctx); - batch_data->batch.payload->recv_trailing_metadata - .recv_trailing_metadata_ready = - &retry_state->recv_trailing_metadata_ready; +// TODO(roth): Consider not intercepting this callback unless we +// actually need to, if this causes a performance problem. +void ClientChannel::CallData:: + InjectRecvInitialMetadataReadyForConfigSelectorCommitCallback( + grpc_transport_stream_op_batch* batch) { + original_recv_initial_metadata_ready_ = + batch->payload->recv_initial_metadata.recv_initial_metadata_ready; + GRPC_CLOSURE_INIT(&recv_initial_metadata_ready_, + RecvInitialMetadataReadyForConfigSelectorCommitCallback, + this, nullptr); + batch->payload->recv_initial_metadata.recv_initial_metadata_ready = + &recv_initial_metadata_ready_; } -void RetryingCall::StartInternalRecvTrailingMetadata() { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log( - GPR_INFO, - "chand=%p retrying_call=%p: call failed but recv_trailing_metadata not " - "started; starting it internally", - chand_, this); - } - SubchannelCallRetryState* retry_state = - static_cast(lb_call_->GetParentData()); - // Create batch_data with 2 refs, since this batch will be unreffed twice: - // once for the recv_trailing_metadata_ready callback when the subchannel - // batch returns, and again when we actually get a recv_trailing_metadata - // op from the surface. - SubchannelCallBatchData* batch_data = - SubchannelCallBatchData::Create(this, 2, false /* set_on_complete */); - AddRetriableRecvTrailingMetadataOp(retry_state, batch_data); - retry_state->recv_trailing_metadata_internal_batch = batch_data; - // Note: This will release the call combiner. - lb_call_->StartTransportStreamOpBatch(&batch_data->batch); +void ClientChannel::CallData::AsyncResolutionDone(grpc_call_element* elem, + grpc_error_handle error) { + GRPC_CLOSURE_INIT(&pick_closure_, ResolutionDone, elem, nullptr); + ExecCtx::Run(DEBUG_LOCATION, &pick_closure_, error); } -// If there are any cached send ops that need to be replayed on the -// current subchannel call, creates and returns a new subchannel batch -// to replay those ops. Otherwise, returns nullptr. -RetryingCall::SubchannelCallBatchData* -RetryingCall::MaybeCreateSubchannelBatchForReplay( - SubchannelCallRetryState* retry_state) { - SubchannelCallBatchData* replay_batch_data = nullptr; - // send_initial_metadata. - if (seen_send_initial_metadata_ && - !retry_state->started_send_initial_metadata && - !pending_send_initial_metadata_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: replaying previously completed " - "send_initial_metadata op", - chand_, this); - } - replay_batch_data = - SubchannelCallBatchData::Create(this, 1, true /* set_on_complete */); - AddRetriableSendInitialMetadataOp(retry_state, replay_batch_data); - } - // send_message. - // Note that we can only have one send_message op in flight at a time. - if (retry_state->started_send_message_count < send_messages_.size() && - retry_state->started_send_message_count == - retry_state->completed_send_message_count && - !pending_send_message_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: replaying previously completed " - "send_message op", - chand_, this); - } - if (replay_batch_data == nullptr) { - replay_batch_data = - SubchannelCallBatchData::Create(this, 1, true /* set_on_complete */); - } - AddRetriableSendMessageOp(retry_state, replay_batch_data); - } - // send_trailing_metadata. - // Note that we only add this op if we have no more send_message ops - // to start, since we can't send down any more send_message ops after - // send_trailing_metadata. - if (seen_send_trailing_metadata_ && - retry_state->started_send_message_count == send_messages_.size() && - !retry_state->started_send_trailing_metadata && - !pending_send_trailing_metadata_) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { +void ClientChannel::CallData::ResolutionDone(void* arg, + grpc_error_handle error) { + grpc_call_element* elem = static_cast(arg); + ClientChannel* chand = static_cast(elem->channel_data); + CallData* calld = static_cast(elem->call_data); + if (error != GRPC_ERROR_NONE) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: replaying previously completed " - "send_trailing_metadata op", - chand_, this); - } - if (replay_batch_data == nullptr) { - replay_batch_data = - SubchannelCallBatchData::Create(this, 1, true /* set_on_complete */); + "chand=%p calld=%p: error applying config to call: error=%s", + chand, calld, grpc_error_std_string(error).c_str()); } - AddRetriableSendTrailingMetadataOp(retry_state, replay_batch_data); + calld->PendingBatchesFail(elem, GRPC_ERROR_REF(error), YieldCallCombiner); + return; } - return replay_batch_data; + calld->CreateDynamicCall(elem); } -void RetryingCall::AddSubchannelBatchesForPendingBatches( - SubchannelCallRetryState* retry_state, CallCombinerClosureList* closures) { - for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { - PendingBatch* pending = &pending_batches_[i]; - grpc_transport_stream_op_batch* batch = pending->batch; - if (batch == nullptr) continue; - // Skip any batch that either (a) has already been started on this - // subchannel call or (b) we can't start yet because we're still - // replaying send ops that need to be completed first. - // TODO(roth): Note that if any one op in the batch can't be sent - // yet due to ops that we're replaying, we don't start any of the ops - // in the batch. This is probably okay, but it could conceivably - // lead to increased latency in some cases -- e.g., we could delay - // starting a recv op due to it being in the same batch with a send - // op. If/when we revamp the callback protocol in - // transport_stream_op_batch, we may be able to fix this. - if (batch->send_initial_metadata && - retry_state->started_send_initial_metadata) { - continue; - } - if (batch->send_message && retry_state->completed_send_message_count < - retry_state->started_send_message_count) { - continue; - } - // Note that we only start send_trailing_metadata if we have no more - // send_message ops to start, since we can't send down any more - // send_message ops after send_trailing_metadata. - if (batch->send_trailing_metadata && - (retry_state->started_send_message_count + batch->send_message < - send_messages_.size() || - retry_state->started_send_trailing_metadata)) { - continue; - } - if (batch->recv_initial_metadata && - retry_state->started_recv_initial_metadata) { - continue; - } - if (batch->recv_message && retry_state->completed_recv_message_count < - retry_state->started_recv_message_count) { - continue; - } - if (batch->recv_trailing_metadata && - retry_state->started_recv_trailing_metadata) { - // If we previously completed a recv_trailing_metadata op - // initiated by StartInternalRecvTrailingMetadata(), use the - // result of that instead of trying to re-start this op. - if (GPR_UNLIKELY((retry_state->recv_trailing_metadata_internal_batch != - nullptr))) { - // If the batch completed, then trigger the completion callback - // directly, so that we return the previously returned results to - // the application. Otherwise, just unref the internally - // started subchannel batch, since we'll propagate the - // completion when it completes. - if (retry_state->completed_recv_trailing_metadata) { - // Batches containing recv_trailing_metadata always succeed. - closures->Add( - &retry_state->recv_trailing_metadata_ready, GRPC_ERROR_NONE, - "re-executing recv_trailing_metadata_ready to propagate " - "internally triggered result"); - } else { - retry_state->recv_trailing_metadata_internal_batch->Unref(); - } - retry_state->recv_trailing_metadata_internal_batch = nullptr; - } - continue; - } - // If we're not retrying, just send the batch as-is. - // TODO(roth): This condition doesn't seem exactly right -- maybe need a - // notion of "draining" once we've committed and are done replaying? - if (retry_policy_ == nullptr || retry_committed_) { - AddClosureForSubchannelBatch(batch, closures); - PendingBatchClear(pending); - continue; - } - // Create batch with the right number of callbacks. - const bool has_send_ops = batch->send_initial_metadata || - batch->send_message || - batch->send_trailing_metadata; - const int num_callbacks = has_send_ops + batch->recv_initial_metadata + - batch->recv_message + - batch->recv_trailing_metadata; - SubchannelCallBatchData* batch_data = SubchannelCallBatchData::Create( - this, num_callbacks, has_send_ops /* set_on_complete */); - // Cache send ops if needed. - MaybeCacheSendOpsForBatch(pending); - // send_initial_metadata. - if (batch->send_initial_metadata) { - AddRetriableSendInitialMetadataOp(retry_state, batch_data); - } - // send_message. - if (batch->send_message) { - AddRetriableSendMessageOp(retry_state, batch_data); - } - // send_trailing_metadata. - if (batch->send_trailing_metadata) { - AddRetriableSendTrailingMetadataOp(retry_state, batch_data); - } - // recv_initial_metadata. - if (batch->recv_initial_metadata) { - // recv_flags is only used on the server side. - GPR_ASSERT(batch->payload->recv_initial_metadata.recv_flags == nullptr); - AddRetriableRecvInitialMetadataOp(retry_state, batch_data); - } - // recv_message. - if (batch->recv_message) { - AddRetriableRecvMessageOp(retry_state, batch_data); - } - // recv_trailing_metadata. - if (batch->recv_trailing_metadata) { - AddRetriableRecvTrailingMetadataOp(retry_state, batch_data); - } - AddClosureForSubchannelBatch(&batch_data->batch, closures); - // Track number of pending subchannel send batches. - // If this is the first one, take a ref to the call stack. - if (batch->send_initial_metadata || batch->send_message || - batch->send_trailing_metadata) { - if (num_pending_retriable_subchannel_send_batches_ == 0) { - GRPC_CALL_STACK_REF(owning_call_, "subchannel_send_batches"); - } - ++num_pending_retriable_subchannel_send_batches_; - } +void ClientChannel::CallData::CheckResolution(void* arg, + grpc_error_handle error) { + grpc_call_element* elem = static_cast(arg); + CallData* calld = static_cast(elem->call_data); + ClientChannel* chand = static_cast(elem->channel_data); + bool resolution_complete; + { + MutexLock lock(&chand->resolution_mu_); + resolution_complete = calld->CheckResolutionLocked(elem, &error); + } + if (resolution_complete) { + ResolutionDone(elem, error); + GRPC_ERROR_UNREF(error); } } -void RetryingCall::StartRetriableSubchannelBatches(void* arg, - grpc_error* /*ignored*/) { - RetryingCall* call = static_cast(arg); - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: constructing retriable batches", - call->chand_, call); +bool ClientChannel::CallData::CheckResolutionLocked(grpc_call_element* elem, + grpc_error_handle* error) { + ClientChannel* chand = static_cast(elem->channel_data); + // If we're still in IDLE, we need to start resolving. + if (GPR_UNLIKELY(chand->CheckConnectivityState(false) == GRPC_CHANNEL_IDLE)) { + // Bounce into the control plane work serializer to start resolving, + // in case we are still in IDLE state. Since we are holding on to the + // resolution mutex here, we offload it on the ExecCtx so that we don't + // deadlock with ourselves. + GRPC_CHANNEL_STACK_REF(chand->owning_stack_, "CheckResolutionLocked"); + ExecCtx::Run( + DEBUG_LOCATION, + GRPC_CLOSURE_CREATE( + [](void* arg, grpc_error_handle /*error*/) { + auto* chand = static_cast(arg); + chand->work_serializer_->Run( + [chand]() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand->work_serializer_) { + chand->CheckConnectivityState(/*try_to_connect=*/true); + GRPC_CHANNEL_STACK_UNREF(chand->owning_stack_, + "CheckResolutionLocked"); + }, + DEBUG_LOCATION); + }, + chand, nullptr), + GRPC_ERROR_NONE); } - SubchannelCallRetryState* retry_state = - static_cast(call->lb_call_->GetParentData()); - // Construct list of closures to execute, one for each pending batch. - CallCombinerClosureList closures; - // Replay previously-returned send_* ops if needed. - SubchannelCallBatchData* replay_batch_data = - call->MaybeCreateSubchannelBatchForReplay(retry_state); - if (replay_batch_data != nullptr) { - call->AddClosureForSubchannelBatch(&replay_batch_data->batch, &closures); - // Track number of pending subchannel send batches. - // If this is the first one, take a ref to the call stack. - if (call->num_pending_retriable_subchannel_send_batches_ == 0) { - GRPC_CALL_STACK_REF(call->owning_call_, "subchannel_send_batches"); + // Get send_initial_metadata batch and flags. + auto& send_initial_metadata = + pending_batches_[0]->payload->send_initial_metadata; + grpc_metadata_batch* initial_metadata_batch = + send_initial_metadata.send_initial_metadata; + const uint32_t send_initial_metadata_flags = + send_initial_metadata.send_initial_metadata_flags; + // If we don't yet have a resolver result, we need to queue the call + // until we get one. + if (GPR_UNLIKELY(!chand->received_service_config_data_)) { + // If the resolver returned transient failure before returning the + // first service config, fail any non-wait_for_ready calls. + grpc_error_handle resolver_error = chand->resolver_transient_failure_error_; + if (resolver_error != GRPC_ERROR_NONE && + (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) == + 0) { + MaybeRemoveCallFromResolverQueuedCallsLocked(elem); + *error = GRPC_ERROR_REF(resolver_error); + return true; } - ++call->num_pending_retriable_subchannel_send_batches_; + // Either the resolver has not yet returned a result, or it has + // returned transient failure but the call is wait_for_ready. In + // either case, queue the call. + MaybeAddCallToResolverQueuedCallsLocked(elem); + return false; } - // Now add pending batches. - call->AddSubchannelBatchesForPendingBatches(retry_state, &closures); - // Start batches on subchannel call. - if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { - gpr_log(GPR_INFO, - "chand=%p retrying_call=%p: starting %" PRIuPTR - " retriable batches on lb_call=%p", - call->chand_, call, closures.size(), call->lb_call_.get()); + // Apply service config to call if not yet applied. + if (GPR_LIKELY(!service_config_applied_)) { + service_config_applied_ = true; + *error = ApplyServiceConfigToCallLocked(elem, initial_metadata_batch); } - // Note: This will yield the call combiner. - closures.RunClosures(call->call_combiner_); + MaybeRemoveCallFromResolverQueuedCallsLocked(elem); + return true; } -void RetryingCall::CreateLbCall(void* arg, grpc_error* /*error*/) { - auto* call = static_cast(arg); - const size_t parent_data_size = - call->enable_retries_ ? sizeof(SubchannelCallRetryState) : 0; - grpc_call_element_args args = {call->owning_call_, nullptr, - call->call_context_, call->path_, - call->call_start_time_, call->deadline_, - call->arena_, call->call_combiner_}; - call->lb_call_ = LoadBalancedCall::Create(call->chand_, args, call->pollent_, - parent_data_size); +void ClientChannel::CallData::CreateDynamicCall(grpc_call_element* elem) { + auto* chand = static_cast(elem->channel_data); + DynamicFilters::Call::Args args = {std::move(dynamic_filters_), + pollent_, + path_, + call_start_time_, + deadline_, + arena_, + call_context_, + call_combiner_}; + grpc_error_handle error = GRPC_ERROR_NONE; + DynamicFilters* channel_stack = args.channel_stack.get(); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { - gpr_log(GPR_INFO, "chand=%p retrying_call=%p: create lb_call=%p", - call->chand_, call, call->lb_call_.get()); + gpr_log( + GPR_INFO, + "chand=%p calld=%p: creating dynamic call stack on channel_stack=%p", + chand, this, channel_stack); } - if (parent_data_size > 0) { - new (call->lb_call_->GetParentData()) - SubchannelCallRetryState(call->call_context_); + dynamic_call_ = channel_stack->CreateCall(std::move(args), &error); + if (error != GRPC_ERROR_NONE) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: failed to create dynamic call: error=%s", + chand, this, grpc_error_std_string(error).c_str()); + } + PendingBatchesFail(elem, error, YieldCallCombiner); + return; } - call->PendingBatchesResume(); + PendingBatchesResume(elem); } // -// LoadBalancedCall::Metadata +// ClientChannel::LoadBalancedCall::Metadata // -class LoadBalancedCall::Metadata +class ClientChannel::LoadBalancedCall::Metadata : public LoadBalancingPolicy::MetadataInterface { public: Metadata(LoadBalancedCall* lb_call, grpc_metadata_batch* batch) @@ -4856,10 +2490,11 @@ class LoadBalancedCall::Metadata }; // -// LoadBalancedCall::LbCallState +// ClientChannel::LoadBalancedCall::LbCallState // -class LoadBalancedCall::LbCallState : public LoadBalancingPolicy::CallState { +class ClientChannel::LoadBalancedCall::LbCallState + : public LoadBalancingPolicy::CallState { public: explicit LbCallState(LoadBalancedCall* lb_call) : lb_call_(lb_call) {} @@ -4895,25 +2530,12 @@ class LoadBalancedCall::LbCallState : public LoadBalancingPolicy::CallState { // LoadBalancedCall // -RefCountedPtr LoadBalancedCall::Create( - ChannelData* chand, const grpc_call_element_args& args, - grpc_polling_entity* pollent, size_t parent_data_size) { - const size_t alloc_size = - parent_data_size > 0 - ? (GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(LoadBalancedCall)) + - parent_data_size) - : sizeof(LoadBalancedCall); - auto* lb_call = static_cast(args.arena->Alloc(alloc_size)); - new (lb_call) LoadBalancedCall(chand, args, pollent); - return lb_call; -} - -LoadBalancedCall::LoadBalancedCall(ChannelData* chand, - const grpc_call_element_args& args, - grpc_polling_entity* pollent) - : refs_(1, GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace) - ? "LoadBalancedCall" - : nullptr), +ClientChannel::LoadBalancedCall::LoadBalancedCall( + ClientChannel* chand, const grpc_call_element_args& args, + grpc_polling_entity* pollent, grpc_closure* on_call_destruction_complete) + : RefCounted(GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace) + ? "LoadBalancedCall" + : nullptr), chand_(chand), path_(grpc_slice_ref_internal(args.path)), call_start_time_(args.start_time), @@ -4922,11 +2544,13 @@ LoadBalancedCall::LoadBalancedCall(ChannelData* chand, owning_call_(args.call_stack), call_combiner_(args.call_combiner), call_context_(args.context), - pollent_(pollent) {} + pollent_(pollent), + on_call_destruction_complete_(on_call_destruction_complete) {} -LoadBalancedCall::~LoadBalancedCall() { +ClientChannel::LoadBalancedCall::~LoadBalancedCall() { grpc_slice_unref_internal(path_); GRPC_ERROR_UNREF(cancel_error_); + GRPC_ERROR_UNREF(failure_error_); if (backend_metric_data_ != nullptr) { backend_metric_data_ ->LoadBalancingPolicy::BackendMetricData::~BackendMetricData(); @@ -4935,47 +2559,16 @@ LoadBalancedCall::~LoadBalancedCall() { for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { GPR_ASSERT(pending_batches_[i] == nullptr); } -} - -RefCountedPtr LoadBalancedCall::Ref() { - IncrementRefCount(); - return RefCountedPtr(this); -} - -RefCountedPtr LoadBalancedCall::Ref( - const DebugLocation& location, const char* reason) { - IncrementRefCount(location, reason); - return RefCountedPtr(this); -} - -void LoadBalancedCall::Unref() { - if (GPR_UNLIKELY(refs_.Unref())) { - this->~LoadBalancedCall(); - } -} - -void LoadBalancedCall::Unref(const DebugLocation& location, - const char* reason) { - if (GPR_UNLIKELY(refs_.Unref(location, reason))) { - this->~LoadBalancedCall(); + if (on_call_destruction_complete_ != nullptr) { + ExecCtx::Run(DEBUG_LOCATION, on_call_destruction_complete_, + GRPC_ERROR_NONE); } } -void LoadBalancedCall::IncrementRefCount() { refs_.Ref(); } - -void LoadBalancedCall::IncrementRefCount(const DebugLocation& location, - const char* reason) { - refs_.Ref(location, reason); -} - -void* LoadBalancedCall::GetParentData() { - return reinterpret_cast(this) + - GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(LoadBalancedCall)); -} - -size_t LoadBalancedCall::GetBatchIndex(grpc_transport_stream_op_batch* batch) { +size_t ClientChannel::LoadBalancedCall::GetBatchIndex( + grpc_transport_stream_op_batch* batch) { // Note: It is important the send_initial_metadata be the first entry - // here, since the code in pick_subchannel_locked() assumes it will be. + // here, since the code in PickSubchannelLocked() assumes it will be. if (batch->send_initial_metadata) return 0; if (batch->send_message) return 1; if (batch->send_trailing_metadata) return 2; @@ -4986,7 +2579,7 @@ size_t LoadBalancedCall::GetBatchIndex(grpc_transport_stream_op_batch* batch) { } // This is called via the call combiner, so access to calld is synchronized. -void LoadBalancedCall::PendingBatchesAdd( +void ClientChannel::LoadBalancedCall::PendingBatchesAdd( grpc_transport_stream_op_batch* batch) { const size_t idx = GetBatchIndex(batch); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { @@ -4999,8 +2592,8 @@ void LoadBalancedCall::PendingBatchesAdd( } // This is called via the call combiner, so access to calld is synchronized. -void LoadBalancedCall::FailPendingBatchInCallCombiner(void* arg, - grpc_error* error) { +void ClientChannel::LoadBalancedCall::FailPendingBatchInCallCombiner( + void* arg, grpc_error_handle error) { grpc_transport_stream_op_batch* batch = static_cast(arg); auto* self = static_cast(batch->handler_private.extra_arg); @@ -5010,10 +2603,12 @@ void LoadBalancedCall::FailPendingBatchInCallCombiner(void* arg, } // This is called via the call combiner, so access to calld is synchronized. -void LoadBalancedCall::PendingBatchesFail( - grpc_error* error, +void ClientChannel::LoadBalancedCall::PendingBatchesFail( + grpc_error_handle error, YieldCallCombinerPredicate yield_call_combiner_predicate) { GPR_ASSERT(error != GRPC_ERROR_NONE); + GRPC_ERROR_UNREF(failure_error_); + failure_error_ = error; if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { size_t num_batches = 0; for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { @@ -5021,7 +2616,7 @@ void LoadBalancedCall::PendingBatchesFail( } gpr_log(GPR_INFO, "chand=%p lb_call=%p: failing %" PRIuPTR " pending batches: %s", - chand_, this, num_batches, grpc_error_string(error)); + chand_, this, num_batches, grpc_error_std_string(error).c_str()); } CallCombinerClosureList closures; for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { @@ -5041,12 +2636,11 @@ void LoadBalancedCall::PendingBatchesFail( } else { closures.RunClosuresWithoutYielding(call_combiner_); } - GRPC_ERROR_UNREF(error); } // This is called via the call combiner, so access to calld is synchronized. -void LoadBalancedCall::ResumePendingBatchInCallCombiner( - void* arg, grpc_error* /*ignored*/) { +void ClientChannel::LoadBalancedCall::ResumePendingBatchInCallCombiner( + void* arg, grpc_error_handle /*ignored*/) { grpc_transport_stream_op_batch* batch = static_cast(arg); SubchannelCall* subchannel_call = @@ -5056,7 +2650,7 @@ void LoadBalancedCall::ResumePendingBatchInCallCombiner( } // This is called via the call combiner, so access to calld is synchronized. -void LoadBalancedCall::PendingBatchesResume() { +void ClientChannel::LoadBalancedCall::PendingBatchesResume() { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { size_t num_batches = 0; for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { @@ -5084,7 +2678,7 @@ void LoadBalancedCall::PendingBatchesResume() { closures.RunClosures(call_combiner_); } -void LoadBalancedCall::StartTransportStreamOpBatch( +void ClientChannel::LoadBalancedCall::StartTransportStreamOpBatch( grpc_transport_stream_op_batch* batch) { // Intercept recv_trailing_metadata_ready for LB callback. if (batch->recv_trailing_metadata) { @@ -5094,7 +2688,7 @@ void LoadBalancedCall::StartTransportStreamOpBatch( if (GPR_UNLIKELY(cancel_error_ != GRPC_ERROR_NONE)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: failing batch with error: %s", - chand_, this, grpc_error_string(cancel_error_)); + chand_, this, grpc_error_std_string(cancel_error_).c_str()); } // Note: This will release the call combiner. grpc_transport_stream_op_batch_finish_with_failure( @@ -5112,7 +2706,7 @@ void LoadBalancedCall::StartTransportStreamOpBatch( cancel_error_ = GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_call_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: recording cancel_error=%s", - chand_, this, grpc_error_string(cancel_error_)); + chand_, this, grpc_error_std_string(cancel_error_).c_str()); } // If we do not have a subchannel call (i.e., a pick has not yet // been started), fail all pending batches. Otherwise, send the @@ -5165,12 +2759,13 @@ void LoadBalancedCall::StartTransportStreamOpBatch( } } -void LoadBalancedCall::RecvTrailingMetadataReadyForLoadBalancingPolicy( - void* arg, grpc_error* error) { +void ClientChannel::LoadBalancedCall:: + RecvTrailingMetadataReadyForLoadBalancingPolicy(void* arg, + grpc_error_handle error) { auto* self = static_cast(arg); if (self->lb_recv_trailing_metadata_ready_ != nullptr) { // Set error if call did not succeed. - grpc_error* error_for_lb = GRPC_ERROR_NONE; + grpc_error_handle error_for_lb = GRPC_ERROR_NONE; if (error != GRPC_ERROR_NONE) { error_for_lb = error; } else { @@ -5198,14 +2793,19 @@ void LoadBalancedCall::RecvTrailingMetadataReadyForLoadBalancingPolicy( if (error == GRPC_ERROR_NONE) GRPC_ERROR_UNREF(error_for_lb); } // Chain to original callback. + if (self->failure_error_ != GRPC_ERROR_NONE) { + error = self->failure_error_; + self->failure_error_ = GRPC_ERROR_NONE; + } else { + error = GRPC_ERROR_REF(error); + } Closure::Run(DEBUG_LOCATION, self->original_recv_trailing_metadata_ready_, - GRPC_ERROR_REF(error)); + error); } -// TODO(roth): Consider not intercepting this callback unless we -// actually need to, if this causes a performance problem. -void LoadBalancedCall::InjectRecvTrailingMetadataReadyForLoadBalancingPolicy( - grpc_transport_stream_op_batch* batch) { +void ClientChannel::LoadBalancedCall:: + InjectRecvTrailingMetadataReadyForLoadBalancingPolicy( + grpc_transport_stream_op_batch* batch) { recv_trailing_metadata_ = batch->payload->recv_trailing_metadata.recv_trailing_metadata; original_recv_trailing_metadata_ready_ = @@ -5217,19 +2817,23 @@ void LoadBalancedCall::InjectRecvTrailingMetadataReadyForLoadBalancingPolicy( &recv_trailing_metadata_ready_; } -void LoadBalancedCall::CreateSubchannelCall() { +void ClientChannel::LoadBalancedCall::CreateSubchannelCall() { SubchannelCall::Args call_args = { std::move(connected_subchannel_), pollent_, path_, call_start_time_, deadline_, arena_, // TODO(roth): When we implement hedging support, we will probably // need to use a separate call context for each subchannel call. call_context_, call_combiner_}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; subchannel_call_ = SubchannelCall::Create(std::move(call_args), &error); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: create subchannel_call=%p: error=%s", chand_, - this, subchannel_call_.get(), grpc_error_string(error)); + this, subchannel_call_.get(), grpc_error_std_string(error).c_str()); + } + if (on_call_destruction_complete_ != nullptr) { + subchannel_call_->SetAfterCallStackDestroy(on_call_destruction_complete_); + on_call_destruction_complete_ = nullptr; } if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { PendingBatchesFail(error, YieldCallCombiner); @@ -5245,7 +2849,7 @@ void LoadBalancedCall::CreateSubchannelCall() { // because there may be multiple LB picks happening in parallel. // Instead, we will probably need to maintain a list in the CallData // object of pending LB picks to be cancelled when the closure runs. -class LoadBalancedCall::LbQueuedCallCanceller { +class ClientChannel::LoadBalancedCall::LbQueuedCallCanceller { public: explicit LbQueuedCallCanceller(RefCountedPtr lb_call) : lb_call_(std::move(lb_call)) { @@ -5255,17 +2859,17 @@ class LoadBalancedCall::LbQueuedCallCanceller { } private: - static void CancelLocked(void* arg, grpc_error* error) { + static void CancelLocked(void* arg, grpc_error_handle error) { auto* self = static_cast(arg); auto* lb_call = self->lb_call_.get(); auto* chand = lb_call->chand_; { - MutexLock lock(chand->data_plane_mu()); + MutexLock lock(&chand->data_plane_mu_); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: cancelling queued pick: " "error=%s self=%p calld->pick_canceller=%p", - chand, lb_call, grpc_error_string(error), self, + chand, lb_call, grpc_error_std_string(error).c_str(), self, lb_call->lb_call_canceller_); } if (lb_call->lb_call_canceller_ == self && error != GRPC_ERROR_NONE) { @@ -5284,7 +2888,7 @@ class LoadBalancedCall::LbQueuedCallCanceller { grpc_closure closure_; }; -void LoadBalancedCall::MaybeRemoveCallFromLbQueuedCallsLocked() { +void ClientChannel::LoadBalancedCall::MaybeRemoveCallFromLbQueuedCallsLocked() { if (!queued_pending_lb_pick_) return; if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: removing from queued picks list", @@ -5296,7 +2900,7 @@ void LoadBalancedCall::MaybeRemoveCallFromLbQueuedCallsLocked() { lb_call_canceller_ = nullptr; } -void LoadBalancedCall::MaybeAddCallToLbQueuedCallsLocked() { +void ClientChannel::LoadBalancedCall::MaybeAddCallToLbQueuedCallsLocked() { if (queued_pending_lb_pick_) return; if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: adding to queued picks list", @@ -5309,18 +2913,19 @@ void LoadBalancedCall::MaybeAddCallToLbQueuedCallsLocked() { lb_call_canceller_ = new LbQueuedCallCanceller(Ref()); } -void LoadBalancedCall::AsyncPickDone(grpc_error* error) { +void ClientChannel::LoadBalancedCall::AsyncPickDone(grpc_error_handle error) { GRPC_CLOSURE_INIT(&pick_closure_, PickDone, this, grpc_schedule_on_exec_ctx); ExecCtx::Run(DEBUG_LOCATION, &pick_closure_, error); } -void LoadBalancedCall::PickDone(void* arg, grpc_error* error) { +void ClientChannel::LoadBalancedCall::PickDone(void* arg, + grpc_error_handle error) { auto* self = static_cast(arg); if (error != GRPC_ERROR_NONE) { if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p lb_call=%p: failed to pick subchannel: error=%s", - self->chand_, self, grpc_error_string(error)); + self->chand_, self, grpc_error_std_string(error).c_str()); } self->PendingBatchesFail(GRPC_ERROR_REF(error), YieldCallCombiner); return; @@ -5328,6 +2933,8 @@ void LoadBalancedCall::PickDone(void* arg, grpc_error* error) { self->CreateSubchannelCall(); } +namespace { + const char* PickResultTypeName( LoadBalancingPolicy::PickResult::ResultType type) { switch (type) { @@ -5341,11 +2948,14 @@ const char* PickResultTypeName( GPR_UNREACHABLE_CODE(return "UNKNOWN"); } -void LoadBalancedCall::PickSubchannel(void* arg, grpc_error* error) { +} // namespace + +void ClientChannel::LoadBalancedCall::PickSubchannel(void* arg, + grpc_error_handle error) { auto* self = static_cast(arg); bool pick_complete; { - MutexLock lock(self->chand_->data_plane_mu()); + MutexLock lock(&self->chand_->data_plane_mu_); pick_complete = self->PickSubchannelLocked(&error); } if (pick_complete) { @@ -5354,7 +2964,8 @@ void LoadBalancedCall::PickSubchannel(void* arg, grpc_error* error) { } } -bool LoadBalancedCall::PickSubchannelLocked(grpc_error** error) { +bool ClientChannel::LoadBalancedCall::PickSubchannelLocked( + grpc_error_handle* error) { GPR_ASSERT(connected_subchannel_ == nullptr); GPR_ASSERT(subchannel_call_ == nullptr); // Grab initial metadata. @@ -5371,18 +2982,18 @@ bool LoadBalancedCall::PickSubchannelLocked(grpc_error** error) { pick_args.call_state = &lb_call_state; Metadata initial_metadata(this, initial_metadata_batch); pick_args.initial_metadata = &initial_metadata; - auto result = chand_->picker()->Pick(pick_args); + auto result = chand_->picker_->Pick(pick_args); if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log( GPR_INFO, "chand=%p lb_call=%p: LB pick returned %s (subchannel=%p, error=%s)", chand_, this, PickResultTypeName(result.type), result.subchannel.get(), - grpc_error_string(result.error)); + grpc_error_std_string(result.error).c_str()); } switch (result.type) { case LoadBalancingPolicy::PickResult::PICK_FAILED: { // If we're shutting down, fail all RPCs. - grpc_error* disconnect_error = chand_->disconnect_error(); + grpc_error_handle disconnect_error = chand_->disconnect_error(); if (disconnect_error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(result.error); MaybeRemoveCallFromLbQueuedCallsLocked(); @@ -5393,7 +3004,7 @@ bool LoadBalancedCall::PickSubchannelLocked(grpc_error** error) { // attempt's final status. if ((send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) == 0) { - grpc_error* new_error = + grpc_error_handle new_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to pick subchannel", &result.error, 1); GRPC_ERROR_UNREF(result.error); @@ -5414,9 +3025,11 @@ bool LoadBalancedCall::PickSubchannelLocked(grpc_error** error) { // Handle drops. if (GPR_UNLIKELY(result.subchannel == nullptr)) { result.error = grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Call dropped by load balancing policy"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Call dropped by load balancing policy"), + GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAVAILABLE), + GRPC_ERROR_INT_LB_POLICY_DROP, 1); } else { // Grab a ref to the connected subchannel while we're still // holding the data plane mutex. @@ -5430,69 +3043,4 @@ bool LoadBalancedCall::PickSubchannelLocked(grpc_error** error) { } } -} // namespace } // namespace grpc_core - -/************************************************************************* - * EXPORTED SYMBOLS - */ - -using grpc_core::CallData; -using grpc_core::ChannelData; - -const grpc_channel_filter grpc_client_channel_filter = { - CallData::StartTransportStreamOpBatch, - ChannelData::StartTransportOp, - sizeof(CallData), - CallData::Init, - CallData::SetPollent, - CallData::Destroy, - sizeof(ChannelData), - ChannelData::Init, - ChannelData::Destroy, - ChannelData::GetChannelInfo, - "client-channel", -}; - -grpc_connectivity_state grpc_client_channel_check_connectivity_state( - grpc_channel_element* elem, int try_to_connect) { - auto* chand = static_cast(elem->channel_data); - return chand->CheckConnectivityState(try_to_connect); -} - -int grpc_client_channel_num_external_connectivity_watchers( - grpc_channel_element* elem) { - auto* chand = static_cast(elem->channel_data); - return chand->NumExternalConnectivityWatchers(); -} - -void grpc_client_channel_watch_connectivity_state( - grpc_channel_element* elem, grpc_polling_entity pollent, - grpc_connectivity_state* state, grpc_closure* on_complete, - grpc_closure* watcher_timer_init) { - auto* chand = static_cast(elem->channel_data); - if (state == nullptr) { - // Handle cancellation. - GPR_ASSERT(watcher_timer_init == nullptr); - chand->RemoveExternalConnectivityWatcher(on_complete, /*cancel=*/true); - return; - } - // Handle addition. - return chand->AddExternalConnectivityWatcher(pollent, state, on_complete, - watcher_timer_init); -} - -void grpc_client_channel_start_connectivity_watch( - grpc_channel_element* elem, grpc_connectivity_state initial_state, - grpc_core::OrphanablePtr - watcher) { - auto* chand = static_cast(elem->channel_data); - chand->AddConnectivityWatcher(initial_state, std::move(watcher)); -} - -void grpc_client_channel_stop_connectivity_watch( - grpc_channel_element* elem, - grpc_core::AsyncConnectivityStateWatcherInterface* watcher) { - auto* chand = static_cast(elem->channel_data); - chand->RemoveConnectivityWatcher(watcher); -} diff --git a/src/core/ext/filters/client_channel/client_channel.h b/src/core/ext/filters/client_channel/client_channel.h index af011cafcc7..b7dd1a19db4 100644 --- a/src/core/ext/filters/client_channel/client_channel.h +++ b/src/core/ext/filters/client_channel/client_channel.h @@ -1,76 +1,510 @@ -/* - * - * 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. - * - */ +// +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H #include -#include "src/core/ext/filters/client_channel/client_channel_channelz.h" +#include +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/types/optional.h" + +#include + #include "src/core/ext/filters/client_channel/client_channel_factory.h" +#include "src/core/ext/filters/client_channel/config_selector.h" +#include "src/core/ext/filters/client_channel/dynamic_filters.h" +#include "src/core/ext/filters/client_channel/lb_policy.h" #include "src/core/ext/filters/client_channel/resolver.h" -#include "src/core/lib/channel/channel_stack.h" +#include "src/core/ext/filters/client_channel/resolver_result_parsing.h" +#include "src/core/ext/filters/client_channel/retry_throttle.h" +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/ext/filters/client_channel/subchannel.h" +#include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/iomgr/error.h" +#include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/iomgr/work_serializer.h" +#include "src/core/lib/surface/channel.h" +#include "src/core/lib/transport/connectivity_state.h" + +// +// Client channel filter +// + +// A client channel is a channel that begins disconnected, and can connect +// to some endpoint on demand. If that endpoint disconnects, it will be +// connected to again later. +// +// Calls on a disconnected client channel are queued until a connection is +// established. // Channel arg key for server URI string. #define GRPC_ARG_SERVER_URI "grpc.server_uri" -/* A client channel is a channel that begins disconnected, and can connect - to some endpoint on demand. If that endpoint disconnects, it will be - connected to again later. +// Channel arg containing a pointer to the ClientChannel object. +#define GRPC_ARG_CLIENT_CHANNEL "grpc.internal.client_channel" + +// Channel arg containing a pointer to the ServiceConfig object. +#define GRPC_ARG_SERVICE_CONFIG_OBJ "grpc.internal.service_config_obj" + +// Max number of batches that can be pending on a call at any given +// time. This includes one batch for each of the following ops: +// recv_initial_metadata +// send_initial_metadata +// recv_message +// send_message +// recv_trailing_metadata +// send_trailing_metadata +#define MAX_PENDING_BATCHES 6 + +namespace grpc_core { + +class ClientChannel { + public: + static const grpc_channel_filter kFilterVtable; + + class LoadBalancedCall; + + // Returns the ClientChannel object from channel, or null if channel + // is not a client channel. + static ClientChannel* GetFromChannel(grpc_channel* channel); + + grpc_connectivity_state CheckConnectivityState(bool try_to_connect); + + // Starts a one-time connectivity state watch. When the channel's state + // becomes different from *state, sets *state to the new state and + // schedules on_complete. The watcher_timer_init callback is invoked as + // soon as the watch is actually started (i.e., after hopping into the + // client channel combiner). I/O will be serviced via pollent. + // + // This is intended to be used when starting a watch from outside of C-core + // via grpc_channel_watch_connectivity_state(). It should not be used + // by other callers. + void AddExternalConnectivityWatcher(grpc_polling_entity pollent, + grpc_connectivity_state* state, + grpc_closure* on_complete, + grpc_closure* watcher_timer_init) { + new ExternalConnectivityWatcher(this, pollent, state, on_complete, + watcher_timer_init); + } + + // Cancels a pending external watcher previously added by + // AddExternalConnectivityWatcher(). + void CancelExternalConnectivityWatcher(grpc_closure* on_complete) { + ExternalConnectivityWatcher::RemoveWatcherFromExternalWatchersMap( + this, on_complete, /*cancel=*/true); + } + + int NumExternalConnectivityWatchers() const { + MutexLock lock(&external_watchers_mu_); + return static_cast(external_watchers_.size()); + } + + // Starts and stops a connectivity watch. The watcher will be initially + // notified as soon as the state changes from initial_state and then on + // every subsequent state change until either the watch is stopped or + // it is notified that the state has changed to SHUTDOWN. + // + // This is intended to be used when starting watches from code inside of + // C-core (e.g., for a nested control plane channel for things like xds). + void AddConnectivityWatcher( + grpc_connectivity_state initial_state, + OrphanablePtr watcher); + void RemoveConnectivityWatcher( + AsyncConnectivityStateWatcherInterface* watcher); + + RefCountedPtr CreateLoadBalancedCall( + const grpc_call_element_args& args, grpc_polling_entity* pollent, + grpc_closure* on_call_destruction_complete); + + private: + class CallData; + class ResolverResultHandler; + class SubchannelWrapper; + class ClientChannelControlHelper; + class ConnectivityWatcherAdder; + class ConnectivityWatcherRemover; + + // Represents a pending connectivity callback from an external caller + // via grpc_client_channel_watch_connectivity_state(). + class ExternalConnectivityWatcher : public ConnectivityStateWatcherInterface { + public: + ExternalConnectivityWatcher(ClientChannel* chand, + grpc_polling_entity pollent, + grpc_connectivity_state* state, + grpc_closure* on_complete, + grpc_closure* watcher_timer_init); + + ~ExternalConnectivityWatcher() override; + + // Removes the watcher from the external_watchers_ map. + static void RemoveWatcherFromExternalWatchersMap(ClientChannel* chand, + grpc_closure* on_complete, + bool cancel); + + void Notify(grpc_connectivity_state state, + const absl::Status& /* status */) override; + + void Cancel(); + + private: + // Adds the watcher to state_tracker_. Consumes the ref that is passed to it + // from Start(). + void AddWatcherLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_); + void RemoveWatcherLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_); + + ClientChannel* chand_; + grpc_polling_entity pollent_; + grpc_connectivity_state initial_state_; + grpc_connectivity_state* state_; + grpc_closure* on_complete_; + grpc_closure* watcher_timer_init_; + Atomic done_{false}; + }; + + struct ResolverQueuedCall { + grpc_call_element* elem; + ResolverQueuedCall* next = nullptr; + }; + struct LbQueuedCall { + LoadBalancedCall* lb_call; + LbQueuedCall* next = nullptr; + }; + + ClientChannel(grpc_channel_element_args* args, grpc_error_handle* error); + ~ClientChannel(); + + // Filter vtable functions. + static grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args); + static void Destroy(grpc_channel_element* elem); + static void StartTransportOp(grpc_channel_element* elem, + grpc_transport_op* op); + static void GetChannelInfo(grpc_channel_element* elem, + const grpc_channel_info* info); - Calls on a disconnected client channel are queued until a connection is - established. */ + // Note: Does NOT return a new ref. + grpc_error_handle disconnect_error() const { + return disconnect_error_.Load(MemoryOrder::ACQUIRE); + } -extern const grpc_channel_filter grpc_client_channel_filter; + // Note: All methods with "Locked" suffix must be invoked from within + // work_serializer_. -grpc_connectivity_state grpc_client_channel_check_connectivity_state( - grpc_channel_element* elem, int try_to_connect); + void OnResolverResultChangedLocked(Resolver::Result result) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + void OnResolverErrorLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); -int grpc_client_channel_num_external_connectivity_watchers( - grpc_channel_element* elem); + void CreateOrUpdateLbPolicyLocked( + RefCountedPtr lb_policy_config, + Resolver::Result result) ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + OrphanablePtr CreateLbPolicyLocked( + const grpc_channel_args& args) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + void UpdateStateAndPickerLocked( + grpc_connectivity_state state, const absl::Status& status, + const char* reason, + std::unique_ptr picker) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + void UpdateServiceConfigInControlPlaneLocked( + RefCountedPtr service_config, + RefCountedPtr config_selector, + const internal::ClientChannelGlobalParsedConfig* parsed_service_config, + const char* lb_policy_name) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + void UpdateServiceConfigInDataPlaneLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + void CreateResolverLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + void DestroyResolverAndLbPolicyLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + grpc_error_handle DoPingLocked(grpc_transport_op* op) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + void StartTransportOpLocked(grpc_transport_op* op) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + void TryToConnectLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); + + // These methods all require holding resolution_mu_. + void AddResolverQueuedCall(ResolverQueuedCall* call, + grpc_polling_entity* pollent) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(resolution_mu_); + void RemoveResolverQueuedCall(ResolverQueuedCall* to_remove, + grpc_polling_entity* pollent) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(resolution_mu_); + + // These methods all require holding data_plane_mu_. + void AddLbQueuedCall(LbQueuedCall* call, grpc_polling_entity* pollent) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_); + void RemoveLbQueuedCall(LbQueuedCall* to_remove, grpc_polling_entity* pollent) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_); + RefCountedPtr GetConnectedSubchannelInDataPlane( + SubchannelInterface* subchannel) const + ABSL_EXCLUSIVE_LOCKS_REQUIRED(data_plane_mu_); + + // + // Fields set at construction and never modified. + // + const bool deadline_checking_enabled_; + const bool enable_retries_; + grpc_channel_stack* owning_stack_; + ClientChannelFactory* client_channel_factory_; + const grpc_channel_args* channel_args_; + RefCountedPtr default_service_config_; + std::string server_name_; + UniquePtr target_uri_; + channelz::ChannelNode* channelz_node_; + grpc_pollset_set* interested_parties_; + + // + // Fields related to name resolution. Guarded by resolution_mu_. + // + mutable Mutex resolution_mu_; + // Linked list of calls queued waiting for resolver result. + ResolverQueuedCall* resolver_queued_calls_ ABSL_GUARDED_BY(resolution_mu_) = + nullptr; + // Data from service config. + grpc_error_handle resolver_transient_failure_error_ + ABSL_GUARDED_BY(resolution_mu_) = GRPC_ERROR_NONE; + bool received_service_config_data_ ABSL_GUARDED_BY(resolution_mu_) = false; + RefCountedPtr service_config_ ABSL_GUARDED_BY(resolution_mu_); + RefCountedPtr config_selector_ + ABSL_GUARDED_BY(resolution_mu_); + RefCountedPtr dynamic_filters_ + ABSL_GUARDED_BY(resolution_mu_); + + // + // Fields used in the data plane. Guarded by data_plane_mu_. + // + mutable Mutex data_plane_mu_; + std::unique_ptr picker_ + ABSL_GUARDED_BY(data_plane_mu_); + // Linked list of calls queued waiting for LB pick. + LbQueuedCall* lb_queued_calls_ ABSL_GUARDED_BY(data_plane_mu_) = nullptr; + + // + // Fields used in the control plane. Guarded by work_serializer. + // + std::shared_ptr work_serializer_; + ConnectivityStateTracker state_tracker_ ABSL_GUARDED_BY(work_serializer_); + OrphanablePtr resolver_ ABSL_GUARDED_BY(work_serializer_); + bool previous_resolution_contained_addresses_ + ABSL_GUARDED_BY(work_serializer_) = false; + RefCountedPtr saved_service_config_ + ABSL_GUARDED_BY(work_serializer_); + RefCountedPtr saved_config_selector_ + ABSL_GUARDED_BY(work_serializer_); + absl::optional health_check_service_name_ + ABSL_GUARDED_BY(work_serializer_); + OrphanablePtr lb_policy_ + ABSL_GUARDED_BY(work_serializer_); + RefCountedPtr subchannel_pool_ + ABSL_GUARDED_BY(work_serializer_); + // The number of SubchannelWrapper instances referencing a given Subchannel. + std::map subchannel_refcount_map_ + ABSL_GUARDED_BY(work_serializer_); + // The set of SubchannelWrappers that currently exist. + // No need to hold a ref, since the map is updated in the control-plane + // work_serializer when the SubchannelWrappers are created and destroyed. + std::set subchannel_wrappers_ + ABSL_GUARDED_BY(work_serializer_); + // Pending ConnectedSubchannel updates for each SubchannelWrapper. + // Updates are queued here in the control plane work_serializer and then + // applied in the data plane mutex when the picker is updated. + std::map, RefCountedPtr> + pending_subchannel_updates_ ABSL_GUARDED_BY(work_serializer_); + int keepalive_time_ ABSL_GUARDED_BY(work_serializer_) = -1; + + // + // Fields accessed from both data plane mutex and control plane + // work_serializer. + // + Atomic disconnect_error_; + + // + // Fields guarded by a mutex, since they need to be accessed + // synchronously via get_channel_info(). + // + Mutex info_mu_; + UniquePtr info_lb_policy_name_ ABSL_GUARDED_BY(info_mu_); + UniquePtr info_service_config_json_ ABSL_GUARDED_BY(info_mu_); + + // + // Fields guarded by a mutex, since they need to be accessed + // synchronously via grpc_channel_num_external_connectivity_watchers(). + // + mutable Mutex external_watchers_mu_; + std::map> + external_watchers_ ABSL_GUARDED_BY(external_watchers_mu_); +}; -// Starts a one-time connectivity state watch. When the channel's state -// becomes different from *state, sets *state to the new state and -// schedules on_complete. The watcher_timer_init callback is invoked as -// soon as the watch is actually started (i.e., after hopping into the -// client channel combiner). I/O will be serviced via pollent. // -// This is intended to be used when starting a watch from outside of C-core -// via grpc_channel_watch_connectivity_state(). It should not be used -// by other callers. -void grpc_client_channel_watch_connectivity_state( - grpc_channel_element* elem, grpc_polling_entity pollent, - grpc_connectivity_state* state, grpc_closure* on_complete, - grpc_closure* watcher_timer_init); - -// Starts and stops a connectivity watch. The watcher will be initially -// notified as soon as the state changes from initial_state and then on -// every subsequent state change until either the watch is stopped or -// it is notified that the state has changed to SHUTDOWN. +// ClientChannel::LoadBalancedCall // -// This is intended to be used when starting watches from code inside of -// C-core (e.g., for a nested control plane channel for things like xds). -void grpc_client_channel_start_connectivity_watch( - grpc_channel_element* elem, grpc_connectivity_state initial_state, - grpc_core::OrphanablePtr - watcher); -void grpc_client_channel_stop_connectivity_watch( - grpc_channel_element* elem, - grpc_core::AsyncConnectivityStateWatcherInterface* watcher); + +// This object is ref-counted, but it cannot inherit from RefCounted<>, +// because it is allocated on the arena and can't free its memory when +// its refcount goes to zero. So instead, it manually implements the +// same API as RefCounted<>, so that it can be used with RefCountedPtr<>. +class ClientChannel::LoadBalancedCall + : public RefCounted { + public: + // If on_call_destruction_complete is non-null, then it will be + // invoked once the LoadBalancedCall is completely destroyed. + // If it is null, then the caller is responsible for checking whether + // the LB call has a subchannel call and ensuring that the + // on_call_destruction_complete closure passed down from the surface + // is not invoked until after the subchannel call stack is destroyed. + LoadBalancedCall(ClientChannel* chand, const grpc_call_element_args& args, + grpc_polling_entity* pollent, + grpc_closure* on_call_destruction_complete); + ~LoadBalancedCall() override; + + void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); + + // Invoked by channel for queued LB picks when the picker is updated. + static void PickSubchannel(void* arg, grpc_error_handle error); + // Helper function for performing an LB pick while holding the data plane + // mutex. Returns true if the pick is complete, in which case the caller + // must invoke PickDone() or AsyncPickDone() with the returned error. + bool PickSubchannelLocked(grpc_error_handle* error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_); + // Schedules a callback to process the completed pick. The callback + // will not run until after this method returns. + void AsyncPickDone(grpc_error_handle error); + + RefCountedPtr subchannel_call() const { + return subchannel_call_; + } + + private: + class LbQueuedCallCanceller; + class Metadata; + class LbCallState; + + // Returns the index into pending_batches_ to be used for batch. + static size_t GetBatchIndex(grpc_transport_stream_op_batch* batch); + void PendingBatchesAdd(grpc_transport_stream_op_batch* batch); + static void FailPendingBatchInCallCombiner(void* arg, + grpc_error_handle error); + // A predicate type and some useful implementations for PendingBatchesFail(). + typedef bool (*YieldCallCombinerPredicate)( + const CallCombinerClosureList& closures); + static bool YieldCallCombiner(const CallCombinerClosureList& /*closures*/) { + return true; + } + static bool NoYieldCallCombiner(const CallCombinerClosureList& /*closures*/) { + return false; + } + static bool YieldCallCombinerIfPendingBatchesFound( + const CallCombinerClosureList& closures) { + return closures.size() > 0; + } + // Fails all pending batches. + // If yield_call_combiner_predicate returns true, assumes responsibility for + // yielding the call combiner. + void PendingBatchesFail( + grpc_error_handle error, + YieldCallCombinerPredicate yield_call_combiner_predicate); + static void ResumePendingBatchInCallCombiner(void* arg, + grpc_error_handle ignored); + // Resumes all pending batches on subchannel_call_. + void PendingBatchesResume(); + + static void RecvTrailingMetadataReadyForLoadBalancingPolicy( + void* arg, grpc_error_handle error); + void InjectRecvTrailingMetadataReadyForLoadBalancingPolicy( + grpc_transport_stream_op_batch* batch); + + void CreateSubchannelCall(); + // Invoked when a pick is completed, on both success or failure. + static void PickDone(void* arg, grpc_error_handle error); + // Removes the call from the channel's list of queued picks if present. + void MaybeRemoveCallFromLbQueuedCallsLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_); + // Adds the call to the channel's list of queued picks if not already present. + void MaybeAddCallToLbQueuedCallsLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ClientChannel::data_plane_mu_); + + ClientChannel* chand_; + + // TODO(roth): Instead of duplicating these fields in every filter + // that uses any one of them, we should store them in the call + // context. This will save per-call memory overhead. + grpc_slice path_; // Request path. + gpr_cycle_counter call_start_time_; + grpc_millis deadline_; + Arena* arena_; + grpc_call_stack* owning_call_; + CallCombiner* call_combiner_; + grpc_call_context_element* call_context_; + grpc_polling_entity* pollent_; + grpc_closure* on_call_destruction_complete_; + + // Set when we get a cancel_stream op. + grpc_error_handle cancel_error_ = GRPC_ERROR_NONE; + + // Set when we fail inside the LB call. + grpc_error_handle failure_error_ = GRPC_ERROR_NONE; + + grpc_closure pick_closure_; + + // Accessed while holding ClientChannel::data_plane_mu_. + ClientChannel::LbQueuedCall queued_call_ + ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_); + bool queued_pending_lb_pick_ ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_) = + false; + LbQueuedCallCanceller* lb_call_canceller_ + ABSL_GUARDED_BY(&ClientChannel::data_plane_mu_) = nullptr; + + RefCountedPtr connected_subchannel_; + const LoadBalancingPolicy::BackendMetricData* backend_metric_data_ = nullptr; + std::function + lb_recv_trailing_metadata_ready_; + + RefCountedPtr subchannel_call_; + + // For intercepting recv_trailing_metadata_ready for the LB policy. + grpc_metadata_batch* recv_trailing_metadata_ = nullptr; + grpc_closure recv_trailing_metadata_ready_; + grpc_closure* original_recv_trailing_metadata_ready_ = nullptr; + + // Batches are added to this list when received from above. + // They are removed when we are done handling the batch (i.e., when + // either we have invoked all of the batch's callbacks or we have + // passed the batch down to the subchannel call and are not + // intercepting any of its callbacks). + grpc_transport_stream_op_batch* pending_batches_[MAX_PENDING_BATCHES] = {}; +}; + +} // namespace grpc_core #endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_CLIENT_CHANNEL_H diff --git a/src/core/ext/filters/client_channel/client_channel_channelz.h b/src/core/ext/filters/client_channel/client_channel_channelz.h index 1a35abe4d50..a106897bd28 100644 --- a/src/core/ext/filters/client_channel/client_channel_channelz.h +++ b/src/core/ext/filters/client_channel/client_channel_channelz.h @@ -63,7 +63,7 @@ class SubchannelNode : public BaseNode { private: Atomic connectivity_state_{GRPC_CHANNEL_IDLE}; Mutex socket_mu_; - RefCountedPtr child_socket_; + RefCountedPtr child_socket_ ABSL_GUARDED_BY(socket_mu_); std::string target_; CallCountingHelper call_counter_; ChannelTrace trace_; diff --git a/src/core/ext/filters/client_channel/client_channel_factory.h b/src/core/ext/filters/client_channel/client_channel_factory.h index 79797bbc454..75d74d676b2 100644 --- a/src/core/ext/filters/client_channel/client_channel_factory.h +++ b/src/core/ext/filters/client_channel/client_channel_factory.h @@ -32,7 +32,8 @@ class ClientChannelFactory { virtual ~ClientChannelFactory() = default; // Creates a subchannel with the specified args. - virtual Subchannel* CreateSubchannel(const grpc_channel_args* args) = 0; + virtual RefCountedPtr CreateSubchannel( + const grpc_channel_args* args) = 0; // Returns a channel arg containing the specified factory. static grpc_arg CreateChannelArg(ClientChannelFactory* factory); diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc index 5690545cbb7..1d33d25b491 100644 --- a/src/core/ext/filters/client_channel/client_channel_plugin.cc +++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc @@ -34,6 +34,7 @@ #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/resolver_result_parsing.h" +#include "src/core/ext/filters/client_channel/retry_service_config.h" #include "src/core/ext/filters/client_channel/retry_throttle.h" #include "src/core/ext/filters/client_channel/service_config_parser.h" #include "src/core/lib/surface/channel_init.h" @@ -46,6 +47,7 @@ static bool append_filter(grpc_channel_stack_builder* builder, void* arg) { void grpc_client_channel_init(void) { grpc_core::ServiceConfigParser::Init(); grpc_core::internal::ClientChannelServiceConfigParser::Register(); + grpc_core::internal::RetryServiceConfigParser::Register(); grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry(); grpc_core::ResolverRegistry::Builder::InitRegistry(); grpc_core::internal::ServerRetryThrottleMap::Init(); @@ -54,7 +56,8 @@ void grpc_client_channel_init(void) { grpc_core::GlobalSubchannelPool::Init(); grpc_channel_init_register_stage( GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter, - const_cast(&grpc_client_channel_filter)); + const_cast( + &grpc_core::ClientChannel::kFilterVtable)); grpc_http_connect_register_handshaker_factory(); grpc_client_channel_global_init_backup_polling(); } diff --git a/src/core/ext/filters/client_channel/config_selector.h b/src/core/ext/filters/client_channel/config_selector.h index 61916d2bc3a..98ae07e46e9 100644 --- a/src/core/ext/filters/client_channel/config_selector.h +++ b/src/core/ext/filters/client_channel/config_selector.h @@ -52,7 +52,7 @@ class ConfigSelector : public RefCounted { struct CallConfig { // Can be set to indicate the call should be failed. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; // The per-method parsed configs that will be passed to // ServiceConfigCallData. const ServiceConfigParser::ParsedConfigVector* method_configs = nullptr; diff --git a/src/core/ext/filters/client_channel/connector.h b/src/core/ext/filters/client_channel/connector.h index 256471456e3..20e25b5bc19 100644 --- a/src/core/ext/filters/client_channel/connector.h +++ b/src/core/ext/filters/client_channel/connector.h @@ -66,7 +66,7 @@ class SubchannelConnector : public InternallyRefCounted { // Cancels any in-flight connection attempt and shuts down the // connector. - virtual void Shutdown(grpc_error* error) = 0; + virtual void Shutdown(grpc_error_handle error) = 0; void Orphan() override { Shutdown(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Subchannel disconnected")); diff --git a/src/core/ext/filters/client_channel/dynamic_filters.cc b/src/core/ext/filters/client_channel/dynamic_filters.cc index 1286fcec42c..47c05a30644 100644 --- a/src/core/ext/filters/client_channel/dynamic_filters.cc +++ b/src/core/ext/filters/client_channel/dynamic_filters.cc @@ -37,7 +37,7 @@ namespace grpc_core { // DynamicFilters::Call // -DynamicFilters::Call::Call(Args args, grpc_error** error) +DynamicFilters::Call::Call(Args args, grpc_error_handle* error) : channel_stack_(std::move(args.channel_stack)) { grpc_call_stack* call_stack = CALL_TO_CALL_STACK(this); const grpc_call_element_args call_args = { @@ -53,8 +53,7 @@ DynamicFilters::Call::Call(Args args, grpc_error** error) *error = grpc_call_stack_init(channel_stack_->channel_stack_, 1, Destroy, this, &call_args); if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) { - const char* error_string = grpc_error_string(*error); - gpr_log(GPR_ERROR, "error: %s", error_string); + gpr_log(GPR_ERROR, "error: %s", grpc_error_std_string(*error).c_str()); return; } grpc_call_stack_set_pollset_or_pollset_set(call_stack, args.pollent); @@ -94,7 +93,7 @@ void DynamicFilters::Call::Unref(const DebugLocation& /*location*/, GRPC_CALL_STACK_UNREF(CALL_TO_CALL_STACK(this), reason); } -void DynamicFilters::Call::Destroy(void* arg, grpc_error* /*error*/) { +void DynamicFilters::Call::Destroy(void* arg, grpc_error_handle /*error*/) { DynamicFilters::Call* self = static_cast(arg); // Keep some members before destroying the subchannel call. grpc_closure* after_call_stack_destroy = self->after_call_stack_destroy_; @@ -124,13 +123,13 @@ void DynamicFilters::Call::IncrementRefCount( namespace { -void DestroyChannelStack(void* arg, grpc_error* /*error*/) { +void DestroyChannelStack(void* arg, grpc_error_handle /*error*/) { grpc_channel_stack* channel_stack = static_cast(arg); grpc_channel_stack_destroy(channel_stack); gpr_free(channel_stack); } -std::pair CreateChannelStack( +std::pair CreateChannelStack( const grpc_channel_args* args, std::vector filters) { // Allocate memory for channel stack. @@ -139,13 +138,13 @@ std::pair CreateChannelStack( grpc_channel_stack* channel_stack = reinterpret_cast(gpr_zalloc(channel_stack_size)); // Initialize stack. - grpc_error* error = grpc_channel_stack_init( + grpc_error_handle error = grpc_channel_stack_init( /*initial_refs=*/1, DestroyChannelStack, channel_stack, filters.data(), filters.size(), args, /*optional_transport=*/nullptr, "DynamicFilters", channel_stack); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "error initializing client internal stack: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); grpc_channel_stack_destroy(channel_stack); gpr_free(channel_stack); return {nullptr, error}; @@ -163,7 +162,7 @@ RefCountedPtr DynamicFilters::Create( if (p.second != GRPC_ERROR_NONE) { // Channel stack creation failed with requested filters. // Create with lame filter instead. - grpc_error* error = p.second; + grpc_error_handle error = p.second; grpc_arg error_arg = MakeLameClientErrorArg(error); grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &error_arg, 1); @@ -180,7 +179,7 @@ DynamicFilters::~DynamicFilters() { } RefCountedPtr DynamicFilters::CreateCall( - DynamicFilters::Call::Args args, grpc_error** error) { + DynamicFilters::Call::Args args, grpc_error_handle* error) { size_t allocation_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Call)) + channel_stack_->call_stack_size; Call* call = static_cast(args.arena->Alloc(allocation_size)); diff --git a/src/core/ext/filters/client_channel/dynamic_filters.h b/src/core/ext/filters/client_channel/dynamic_filters.h index bcdc6d3b61d..08a7f4985eb 100644 --- a/src/core/ext/filters/client_channel/dynamic_filters.h +++ b/src/core/ext/filters/client_channel/dynamic_filters.h @@ -46,7 +46,7 @@ class DynamicFilters : public RefCounted { CallCombiner* call_combiner; }; - Call(Args args, grpc_error** error); + Call(Args args, grpc_error_handle* error); // Continues processing a transport stream op batch. void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); @@ -73,7 +73,7 @@ class DynamicFilters : public RefCounted { void IncrementRefCount(); void IncrementRefCount(const DebugLocation& location, const char* reason); - static void Destroy(void* arg, grpc_error* error); + static void Destroy(void* arg, grpc_error_handle error); RefCountedPtr channel_stack_; grpc_closure* after_call_stack_destroy_ = nullptr; @@ -88,7 +88,7 @@ class DynamicFilters : public RefCounted { ~DynamicFilters() override; - RefCountedPtr CreateCall(Call::Args args, grpc_error** error); + RefCountedPtr CreateCall(Call::Args args, grpc_error_handle* error); private: grpc_channel_stack* channel_stack_; diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.cc b/src/core/ext/filters/client_channel/global_subchannel_pool.cc index 546d1c44160..72593a6f4a2 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.cc @@ -27,16 +27,6 @@ namespace grpc_core { #define GRPC_REGISTER_SUBCHANNEL_CALM_DOWN_AFTER_ATTEMPTS 100 #define GRPC_REGISTER_SUBCHANNEL_CALM_DOWN_MICROS 10 -GlobalSubchannelPool::GlobalSubchannelPool() { - subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_); - gpr_mu_init(&mu_); -} - -GlobalSubchannelPool::~GlobalSubchannelPool() { - gpr_mu_destroy(&mu_); - grpc_avl_unref(subchannel_map_, nullptr); -} - void GlobalSubchannelPool::Init() { instance_ = new RefCountedPtr( MakeRefCounted()); @@ -57,145 +47,37 @@ RefCountedPtr GlobalSubchannelPool::instance() { return *instance_; } -Subchannel* GlobalSubchannelPool::RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) { - Subchannel* c = nullptr; - // Compare and swap (CAS) loop: - for (int attempt_count = 0; c == nullptr; attempt_count++) { - // Ref the shared map to have a local copy. - gpr_mu_lock(&mu_); - grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); - gpr_mu_unlock(&mu_); - // Check to see if a subchannel already exists. - c = static_cast(grpc_avl_get(old_map, key, nullptr)); - if (c != nullptr) { - // The subchannel already exists. Try to reuse it. - c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "subchannel_register+reuse"); - if (c != nullptr) { - GRPC_SUBCHANNEL_UNREF(constructed, - "subchannel_register+found_existing"); - // Exit the CAS loop without modifying the shared map. - } else { - // Reuse of the subchannel failed, so retry CAS loop - if (attempt_count >= - GRPC_REGISTER_SUBCHANNEL_CALM_DOWN_AFTER_ATTEMPTS) { - // GRPC_SUBCHANNEL_REF_FROM_WEAK_REF returning nullptr means that the - // subchannel we got is no longer valid and it's going to be removed - // from the AVL tree soon. Spinning here excesively here can actually - // prevent another thread from removing the subchannel, basically - // resulting in a live lock. See b/157516542 for more details. - // TODO(jtattermusch): the entire ref-counting mechanism for - // subchannels should be overhaulded, but the current workaround - // is fine for short-term. - // TODO(jtattermusch): gpr does not support thread yield operation, - // so a very short wait is the best we can do. - gpr_sleep_until(gpr_time_add( - gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(GRPC_REGISTER_SUBCHANNEL_CALM_DOWN_MICROS, - GPR_TIMESPAN))); - } - } - } else { - // There hasn't been such subchannel. Add one. - // Note that we should ref the old map first because grpc_avl_add() will - // unref it while we still need to access it later. - grpc_avl new_map = grpc_avl_add( - grpc_avl_ref(old_map, nullptr), new SubchannelKey(*key), - GRPC_SUBCHANNEL_WEAK_REF(constructed, "subchannel_register+new"), - nullptr); - // Try to publish the change to the shared map. It may happen (but - // unlikely) that some other thread has changed the shared map, so compare - // to make sure it's unchanged before swapping. Retry if it's changed. - gpr_mu_lock(&mu_); - if (old_map.root == subchannel_map_.root) { - GPR_SWAP(grpc_avl, new_map, subchannel_map_); - c = constructed; - } - gpr_mu_unlock(&mu_); - grpc_avl_unref(new_map, nullptr); - } - grpc_avl_unref(old_map, nullptr); - } - return c; -} - -void GlobalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { - bool done = false; - // Compare and swap (CAS) loop: - while (!done) { - // Ref the shared map to have a local copy. - gpr_mu_lock(&mu_); - grpc_avl old_map = grpc_avl_ref(subchannel_map_, nullptr); - gpr_mu_unlock(&mu_); - // Remove the subchannel. - // Note that we should ref the old map first because grpc_avl_remove() will - // unref it while we still need to access it later. - grpc_avl new_map = - grpc_avl_remove(grpc_avl_ref(old_map, nullptr), key, nullptr); - // Try to publish the change to the shared map. It may happen (but - // unlikely) that some other thread has changed the shared map, so compare - // to make sure it's unchanged before swapping. Retry if it's changed. - gpr_mu_lock(&mu_); - if (old_map.root == subchannel_map_.root) { - GPR_SWAP(grpc_avl, new_map, subchannel_map_); - done = true; - } - gpr_mu_unlock(&mu_); - grpc_avl_unref(new_map, nullptr); - grpc_avl_unref(old_map, nullptr); +RefCountedPtr GlobalSubchannelPool::RegisterSubchannel( + const SubchannelKey& key, RefCountedPtr constructed) { + MutexLock lock(&mu_); + auto it = subchannel_map_.find(key); + if (it != subchannel_map_.end()) { + RefCountedPtr existing = it->second->RefIfNonZero(); + if (existing != nullptr) return existing; } -} - -Subchannel* GlobalSubchannelPool::FindSubchannel(SubchannelKey* key) { - // Lock, and take a reference to the subchannel map. - // We don't need to do the search under a lock as AVL's are immutable. - gpr_mu_lock(&mu_); - grpc_avl index = grpc_avl_ref(subchannel_map_, nullptr); - gpr_mu_unlock(&mu_); - Subchannel* c = static_cast(grpc_avl_get(index, key, nullptr)); - if (c != nullptr) c = GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(c, "found_from_pool"); - grpc_avl_unref(index, nullptr); - return c; + subchannel_map_[key] = constructed.get(); + return constructed; } RefCountedPtr* GlobalSubchannelPool::instance_ = nullptr; -namespace { - -void sck_avl_destroy(void* p, void* /*user_data*/) { - SubchannelKey* key = static_cast(p); - delete key; -} - -void* sck_avl_copy(void* p, void* /*unused*/) { - const SubchannelKey* key = static_cast(p); - auto* new_key = new SubchannelKey(*key); - return static_cast(new_key); -} - -long sck_avl_compare(void* a, void* b, void* /*unused*/) { - const SubchannelKey* key_a = static_cast(a); - const SubchannelKey* key_b = static_cast(b); - return key_a->Cmp(*key_b); -} - -void scv_avl_destroy(void* p, void* /*user_data*/) { - GRPC_SUBCHANNEL_WEAK_UNREF((Subchannel*)p, "global_subchannel_pool"); +void GlobalSubchannelPool::UnregisterSubchannel(const SubchannelKey& key, + Subchannel* subchannel) { + MutexLock lock(&mu_); + auto it = subchannel_map_.find(key); + // delete only if key hasn't been re-registered to a different subchannel + // between strong-unreffing and unregistration of subchannel. + if (it != subchannel_map_.end() && it->second == subchannel) { + subchannel_map_.erase(it); + } } -void* scv_avl_copy(void* p, void* /*unused*/) { - GRPC_SUBCHANNEL_WEAK_REF((Subchannel*)p, "global_subchannel_pool"); - return p; +RefCountedPtr GlobalSubchannelPool::FindSubchannel( + const SubchannelKey& key) { + MutexLock lock(&mu_); + auto it = subchannel_map_.find(key); + if (it == subchannel_map_.end()) return nullptr; + return it->second->RefIfNonZero(); } -} // namespace - -const grpc_avl_vtable GlobalSubchannelPool::subchannel_avl_vtable_ = { - sck_avl_destroy, // destroy_key - sck_avl_copy, // copy_key - sck_avl_compare, // compare_keys - scv_avl_destroy, // destroy_value - scv_avl_copy // copy_value -}; - } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/global_subchannel_pool.h b/src/core/ext/filters/client_channel/global_subchannel_pool.h index 96dc8d7b3a4..7ff9b070023 100644 --- a/src/core/ext/filters/client_channel/global_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/global_subchannel_pool.h @@ -21,7 +21,10 @@ #include +#include + #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/gprpp/sync.h" namespace grpc_core { @@ -33,8 +36,8 @@ namespace grpc_core { class GlobalSubchannelPool final : public SubchannelPoolInterface { public: // The ctor and dtor are not intended to use directly. - GlobalSubchannelPool(); - ~GlobalSubchannelPool() override; + GlobalSubchannelPool() {} + ~GlobalSubchannelPool() override {} // Should be called exactly once at filter initialization time. static void Init(); @@ -45,22 +48,24 @@ class GlobalSubchannelPool final : public SubchannelPoolInterface { static RefCountedPtr instance(); // Implements interface methods. - Subchannel* RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) override; - void UnregisterSubchannel(SubchannelKey* key) override; - Subchannel* FindSubchannel(SubchannelKey* key) override; + RefCountedPtr RegisterSubchannel( + const SubchannelKey& key, RefCountedPtr constructed) override + ABSL_LOCKS_EXCLUDED(mu_); + void UnregisterSubchannel(const SubchannelKey& key, + Subchannel* subchannel) override + ABSL_LOCKS_EXCLUDED(mu_); + RefCountedPtr FindSubchannel(const SubchannelKey& key) override + ABSL_LOCKS_EXCLUDED(mu_); private: // The singleton instance. (It's a pointer to RefCountedPtr so that this // non-local static object can be trivially destructible.) static RefCountedPtr* instance_; - // The vtable for subchannel operations in an AVL tree. - static const grpc_avl_vtable subchannel_avl_vtable_; // A map from subchannel key to subchannel. - grpc_avl subchannel_map_; + std::map subchannel_map_ ABSL_GUARDED_BY(mu_); // To protect subchannel_map_. - gpr_mu mu_; + Mutex mu_; }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/health/health_check_client.cc b/src/core/ext/filters/client_channel/health/health_check_client.cc index 7885fadd2c3..adde23d36a8 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -157,7 +157,7 @@ void HealthCheckClient::StartRetryTimerLocked() { grpc_timer_init(&retry_timer_, next_try, &retry_timer_callback_); } -void HealthCheckClient::OnRetryTimer(void* arg, grpc_error* error) { +void HealthCheckClient::OnRetryTimer(void* arg, grpc_error_handle error) { HealthCheckClient* self = static_cast(arg); { MutexLock lock(&self->mu_); @@ -202,7 +202,7 @@ void EncodeRequest(const std::string& service_name, // Returns true if healthy. // If there was an error parsing the response, sets *error and returns false. -bool DecodeResponse(grpc_slice_buffer* slice_buffer, grpc_error** error) { +bool DecodeResponse(grpc_slice_buffer* slice_buffer, grpc_error_handle* error) { // If message is empty, assume unhealthy. if (slice_buffer->length == 0) { *error = @@ -269,11 +269,8 @@ HealthCheckClient::CallState::~CallState() { // Unset the call combiner cancellation closure. This has the // effect of scheduling the previously set cancellation closure, if // any, so that it can release any internal references it may be - // holding to the call stack. Also flush the closures on exec_ctx so that - // filters that schedule cancel notification closures on exec_ctx do not - // need to take a ref of the call stack to guarantee closure liveness. + // holding to the call stack. call_combiner_.SetNotifyOnCancel(nullptr); - ExecCtx::Get()->Flush(); arena_->Destroy(); } @@ -293,7 +290,7 @@ void HealthCheckClient::CallState::StartCall() { context_, &call_combiner_, }; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; call_ = SubchannelCall::Create(std::move(args), &error).release(); // Register after-destruction callback. GRPC_CLOSURE_INIT(&after_call_stack_destruction_, AfterCallStackDestruction, @@ -304,7 +301,8 @@ void HealthCheckClient::CallState::StartCall() { gpr_log(GPR_ERROR, "HealthCheckClient %p CallState %p: error creating health " "checking call on subchannel (%s); will retry", - health_check_client_.get(), this, grpc_error_string(error)); + health_check_client_.get(), this, + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); CallEndedLocked(/*retry=*/true); return; @@ -381,7 +379,7 @@ void HealthCheckClient::CallState::StartCall() { } void HealthCheckClient::CallState::StartBatchInCallCombiner( - void* arg, grpc_error* /*error*/) { + void* arg, grpc_error_handle /*error*/) { grpc_transport_stream_op_batch* batch = static_cast(arg); SubchannelCall* call = @@ -399,14 +397,14 @@ void HealthCheckClient::CallState::StartBatch( } void HealthCheckClient::CallState::AfterCallStackDestruction( - void* arg, grpc_error* /*error*/) { + void* arg, grpc_error_handle /*error*/) { HealthCheckClient::CallState* self = static_cast(arg); delete self; } -void HealthCheckClient::CallState::OnCancelComplete(void* arg, - grpc_error* /*error*/) { +void HealthCheckClient::CallState::OnCancelComplete( + void* arg, grpc_error_handle /*error*/) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "health_cancel"); @@ -414,7 +412,7 @@ void HealthCheckClient::CallState::OnCancelComplete(void* arg, } void HealthCheckClient::CallState::StartCancel(void* arg, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { HealthCheckClient::CallState* self = static_cast(arg); auto* batch = grpc_make_transport_stream_op( @@ -437,7 +435,7 @@ void HealthCheckClient::CallState::Cancel() { } void HealthCheckClient::CallState::OnComplete(void* arg, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "on_complete"); @@ -447,7 +445,7 @@ void HealthCheckClient::CallState::OnComplete(void* arg, } void HealthCheckClient::CallState::RecvInitialMetadataReady( - void* arg, grpc_error* /*error*/) { + void* arg, grpc_error_handle /*error*/) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "recv_initial_metadata_ready"); @@ -455,7 +453,8 @@ void HealthCheckClient::CallState::RecvInitialMetadataReady( self->call_->Unref(DEBUG_LOCATION, "recv_initial_metadata_ready"); } -void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { +void HealthCheckClient::CallState::DoneReadingRecvMessage( + grpc_error_handle error) { recv_message_.reset(); if (error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(error); @@ -467,10 +466,10 @@ void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { const bool healthy = DecodeResponse(&recv_message_buffer_, &error); const grpc_connectivity_state state = healthy ? GRPC_CHANNEL_READY : GRPC_CHANNEL_TRANSIENT_FAILURE; - const char* reason = error == GRPC_ERROR_NONE && !healthy - ? "backend unhealthy" - : grpc_error_string(error); - health_check_client_->SetHealthStatus(state, reason); + health_check_client_->SetHealthStatus( + state, error == GRPC_ERROR_NONE && !healthy + ? "backend unhealthy" + : grpc_error_std_string(error).c_str()); seen_response_.Store(true, MemoryOrder::RELEASE); grpc_slice_buffer_destroy_internal(&recv_message_buffer_); // Start another recv_message batch. @@ -485,9 +484,9 @@ void HealthCheckClient::CallState::DoneReadingRecvMessage(grpc_error* error) { StartBatch(&recv_message_batch_); } -grpc_error* HealthCheckClient::CallState::PullSliceFromRecvMessage() { +grpc_error_handle HealthCheckClient::CallState::PullSliceFromRecvMessage() { grpc_slice slice; - grpc_error* error = recv_message_->Pull(&slice); + grpc_error_handle error = recv_message_->Pull(&slice); if (error == GRPC_ERROR_NONE) { grpc_slice_buffer_add(&recv_message_buffer_, slice); } @@ -496,7 +495,7 @@ grpc_error* HealthCheckClient::CallState::PullSliceFromRecvMessage() { void HealthCheckClient::CallState::ContinueReadingRecvMessage() { while (recv_message_->Next(SIZE_MAX, &recv_message_ready_)) { - grpc_error* error = PullSliceFromRecvMessage(); + grpc_error_handle error = PullSliceFromRecvMessage(); if (error != GRPC_ERROR_NONE) { DoneReadingRecvMessage(error); return; @@ -509,7 +508,7 @@ void HealthCheckClient::CallState::ContinueReadingRecvMessage() { } void HealthCheckClient::CallState::OnByteStreamNext(void* arg, - grpc_error* error) { + grpc_error_handle error) { HealthCheckClient::CallState* self = static_cast(arg); if (error != GRPC_ERROR_NONE) { @@ -528,8 +527,8 @@ void HealthCheckClient::CallState::OnByteStreamNext(void* arg, } } -void HealthCheckClient::CallState::RecvMessageReady(void* arg, - grpc_error* /*error*/) { +void HealthCheckClient::CallState::RecvMessageReady( + void* arg, grpc_error_handle /*error*/) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "recv_message_ready"); @@ -545,7 +544,7 @@ void HealthCheckClient::CallState::RecvMessageReady(void* arg, } void HealthCheckClient::CallState::RecvTrailingMetadataReady( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { HealthCheckClient::CallState* self = static_cast(arg); GRPC_CALL_COMBINER_STOP(&self->call_combiner_, diff --git a/src/core/ext/filters/client_channel/health/health_check_client.h b/src/core/ext/filters/client_channel/health/health_check_client.h index 0fc39b0410b..d1f063b5024 100644 --- a/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/src/core/ext/filters/client_channel/health/health_check_client.h @@ -64,30 +64,30 @@ class HealthCheckClient : public InternallyRefCounted { void Orphan() override; - void StartCall(); + void StartCall() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&HealthCheckClient::mu_); private: void Cancel(); void StartBatch(grpc_transport_stream_op_batch* batch); - static void StartBatchInCallCombiner(void* arg, grpc_error* error); + static void StartBatchInCallCombiner(void* arg, grpc_error_handle error); - // Requires holding health_check_client_->mu_. - void CallEndedLocked(bool retry); + void CallEndedLocked(bool retry) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(health_check_client_->mu_); - static void OnComplete(void* arg, grpc_error* error); - static void RecvInitialMetadataReady(void* arg, grpc_error* error); - static void RecvMessageReady(void* arg, grpc_error* error); - static void RecvTrailingMetadataReady(void* arg, grpc_error* error); - static void StartCancel(void* arg, grpc_error* error); - static void OnCancelComplete(void* arg, grpc_error* error); + static void OnComplete(void* arg, grpc_error_handle error); + static void RecvInitialMetadataReady(void* arg, grpc_error_handle error); + static void RecvMessageReady(void* arg, grpc_error_handle error); + static void RecvTrailingMetadataReady(void* arg, grpc_error_handle error); + static void StartCancel(void* arg, grpc_error_handle error); + static void OnCancelComplete(void* arg, grpc_error_handle error); - static void OnByteStreamNext(void* arg, grpc_error* error); + static void OnByteStreamNext(void* arg, grpc_error_handle error); void ContinueReadingRecvMessage(); - grpc_error* PullSliceFromRecvMessage(); - void DoneReadingRecvMessage(grpc_error* error); + grpc_error_handle PullSliceFromRecvMessage(); + void DoneReadingRecvMessage(grpc_error_handle error); - static void AfterCallStackDestruction(void* arg, grpc_error* error); + static void AfterCallStackDestruction(void* arg, grpc_error_handle error); RefCountedPtr health_check_client_; grpc_polling_entity pollent_; @@ -141,14 +141,14 @@ class HealthCheckClient : public InternallyRefCounted { }; void StartCall(); - void StartCallLocked(); // Requires holding mu_. + void StartCallLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); - void StartRetryTimerLocked(); // Requires holding mu_. - static void OnRetryTimer(void* arg, grpc_error* error); + void StartRetryTimerLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + static void OnRetryTimer(void* arg, grpc_error_handle error); void SetHealthStatus(grpc_connectivity_state state, const char* reason); - void SetHealthStatusLocked(grpc_connectivity_state state, - const char* reason); // Requires holding mu_. + void SetHealthStatusLocked(grpc_connectivity_state state, const char* reason) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); std::string service_name_; RefCountedPtr connected_subchannel_; @@ -156,18 +156,19 @@ class HealthCheckClient : public InternallyRefCounted { RefCountedPtr channelz_node_; Mutex mu_; - RefCountedPtr watcher_; - bool shutting_down_ = false; + RefCountedPtr watcher_ + ABSL_GUARDED_BY(mu_); + bool shutting_down_ ABSL_GUARDED_BY(mu_) = false; // The data associated with the current health check call. It holds a ref // to this HealthCheckClient object. - OrphanablePtr call_state_; + OrphanablePtr call_state_ ABSL_GUARDED_BY(mu_); // Call retry state. - BackOff retry_backoff_; - grpc_timer retry_timer_; - grpc_closure retry_timer_callback_; - bool retry_timer_callback_pending_ = false; + BackOff retry_backoff_ ABSL_GUARDED_BY(mu_); + grpc_timer retry_timer_ ABSL_GUARDED_BY(mu_); + grpc_closure retry_timer_callback_ ABSL_GUARDED_BY(mu_); + bool retry_timer_callback_pending_ ABSL_GUARDED_BY(mu_) = false; }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 8880806440d..3dff8249d08 100644 --- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -47,7 +47,7 @@ namespace { class HttpConnectHandshaker : public Handshaker { public: HttpConnectHandshaker(); - void Shutdown(grpc_error* why) override; + void Shutdown(grpc_error_handle why) override; void DoHandshake(grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, HandshakerArgs* args) override; @@ -55,30 +55,31 @@ class HttpConnectHandshaker : public Handshaker { private: ~HttpConnectHandshaker() override; - void CleanupArgsForFailureLocked(); - void HandshakeFailedLocked(grpc_error* error); - static void OnWriteDone(void* arg, grpc_error* error); - static void OnReadDone(void* arg, grpc_error* error); - static void OnWriteDoneScheduler(void* arg, grpc_error* error); - static void OnReadDoneScheduler(void* arg, grpc_error* error); + void CleanupArgsForFailureLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + void HandshakeFailedLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + static void OnWriteDone(void* arg, grpc_error_handle error); + static void OnReadDone(void* arg, grpc_error_handle error); + static void OnWriteDoneScheduler(void* arg, grpc_error_handle error); + static void OnReadDoneScheduler(void* arg, grpc_error_handle error); Mutex mu_; - bool is_shutdown_ = false; + bool is_shutdown_ ABSL_GUARDED_BY(mu_) = false; // Endpoint and read buffer to destroy after a shutdown. - grpc_endpoint* endpoint_to_destroy_ = nullptr; - grpc_slice_buffer* read_buffer_to_destroy_ = nullptr; + grpc_endpoint* endpoint_to_destroy_ ABSL_GUARDED_BY(mu_) = nullptr; + grpc_slice_buffer* read_buffer_to_destroy_ ABSL_GUARDED_BY(mu_) = nullptr; // State saved while performing the handshake. HandshakerArgs* args_ = nullptr; grpc_closure* on_handshake_done_ = nullptr; // Objects for processing the HTTP CONNECT request and response. - grpc_slice_buffer write_buffer_; - grpc_closure request_done_closure_; - grpc_closure response_read_closure_; - grpc_http_parser http_parser_; - grpc_http_response http_response_; + grpc_slice_buffer write_buffer_ ABSL_GUARDED_BY(mu_); + grpc_closure request_done_closure_ ABSL_GUARDED_BY(mu_); + grpc_closure response_read_closure_ ABSL_GUARDED_BY(mu_); + grpc_http_parser http_parser_ ABSL_GUARDED_BY(mu_); + grpc_http_response http_response_ ABSL_GUARDED_BY(mu_); }; HttpConnectHandshaker::~HttpConnectHandshaker() { @@ -107,7 +108,7 @@ void HttpConnectHandshaker::CleanupArgsForFailureLocked() { // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. -void HttpConnectHandshaker::HandshakeFailedLocked(grpc_error* error) { +void HttpConnectHandshaker::HandshakeFailedLocked(grpc_error_handle error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after an endpoint operation succeeded but // before the endpoint callback was invoked, we need to generate our @@ -133,7 +134,8 @@ void HttpConnectHandshaker::HandshakeFailedLocked(grpc_error* error) { // This callback can be invoked inline while already holding onto the mutex. To // avoid deadlocks, schedule OnWriteDone on ExecCtx. -void HttpConnectHandshaker::OnWriteDoneScheduler(void* arg, grpc_error* error) { +void HttpConnectHandshaker::OnWriteDoneScheduler(void* arg, + grpc_error_handle error) { auto* handshaker = static_cast(arg); grpc_core::ExecCtx::Run( DEBUG_LOCATION, @@ -144,7 +146,7 @@ void HttpConnectHandshaker::OnWriteDoneScheduler(void* arg, grpc_error* error) { } // Callback invoked when finished writing HTTP CONNECT request. -void HttpConnectHandshaker::OnWriteDone(void* arg, grpc_error* error) { +void HttpConnectHandshaker::OnWriteDone(void* arg, grpc_error_handle error) { auto* handshaker = static_cast(arg); ReleasableMutexLock lock(&handshaker->mu_); if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) { @@ -167,7 +169,8 @@ void HttpConnectHandshaker::OnWriteDone(void* arg, grpc_error* error) { // This callback can be invoked inline while already holding onto the mutex. To // avoid deadlocks, schedule OnReadDone on ExecCtx. -void HttpConnectHandshaker::OnReadDoneScheduler(void* arg, grpc_error* error) { +void HttpConnectHandshaker::OnReadDoneScheduler(void* arg, + grpc_error_handle error) { auto* handshaker = static_cast(arg); grpc_core::ExecCtx::Run( DEBUG_LOCATION, @@ -178,7 +181,7 @@ void HttpConnectHandshaker::OnReadDoneScheduler(void* arg, grpc_error* error) { } // Callback invoked for reading HTTP CONNECT response. -void HttpConnectHandshaker::OnReadDone(void* arg, grpc_error* error) { +void HttpConnectHandshaker::OnReadDone(void* arg, grpc_error_handle error) { auto* handshaker = static_cast(arg); ReleasableMutexLock lock(&handshaker->mu_); if (error != GRPC_ERROR_NONE || handshaker->is_shutdown_) { @@ -264,7 +267,7 @@ done: // Public handshaker methods // -void HttpConnectHandshaker::Shutdown(grpc_error* why) { +void HttpConnectHandshaker::Shutdown(grpc_error_handle why) { { MutexLock lock(&mu_); if (!is_shutdown_) { diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc index 4ef8cbb8b23..b9272249c4d 100644 --- a/src/core/ext/filters/client_channel/lb_policy.cc +++ b/src/core/ext/filters/client_channel/lb_policy.cc @@ -70,6 +70,9 @@ LoadBalancingPolicy::UpdateArgs::UpdateArgs(UpdateArgs&& other) noexcept { LoadBalancingPolicy::UpdateArgs& LoadBalancingPolicy::UpdateArgs::operator=( const UpdateArgs& other) { + if (&other == this) { + return *this; + } addresses = other.addresses; config = other.config; grpc_channel_args_destroy(args); @@ -110,7 +113,7 @@ LoadBalancingPolicy::PickResult LoadBalancingPolicy::QueuePicker::Pick( auto* parent = parent_->Ref().release(); // ref held by lambda. ExecCtx::Run(DEBUG_LOCATION, GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error* /*error*/) { + [](void* arg, grpc_error_handle /*error*/) { auto* parent = static_cast(arg); parent->work_serializer()->Run( [parent]() { diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h index c9fc1429ac8..1c6f3098233 100644 --- a/src/core/ext/filters/client_channel/lb_policy.h +++ b/src/core/ext/filters/client_channel/lb_policy.h @@ -230,7 +230,7 @@ class LoadBalancingPolicy : public InternallyRefCounted { /// Error to be set when returning a failure. // TODO(roth): Replace this with something similar to grpc::Status, // so that we don't expose grpc_error to this API. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; /// Used only if type is PICK_COMPLETE. /// Callback set by LB policy to be notified of trailing metadata. @@ -243,7 +243,7 @@ class LoadBalancingPolicy : public InternallyRefCounted { // TODO(roth): The arguments to this callback should be moved into a // struct, so that we can later add new fields without breaking // existing implementations. - std::function + std::function recv_trailing_metadata_ready; }; @@ -387,13 +387,13 @@ class LoadBalancingPolicy : public InternallyRefCounted { // A picker that returns PICK_TRANSIENT_FAILURE for all picks. class TransientFailurePicker : public SubchannelPicker { public: - explicit TransientFailurePicker(grpc_error* error) : error_(error) {} + explicit TransientFailurePicker(grpc_error_handle error) : error_(error) {} ~TransientFailurePicker() override { GRPC_ERROR_UNREF(error_); } PickResult Pick(PickArgs args) override; private: - grpc_error* error_; + grpc_error_handle error_; }; protected: diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc index c8d1b1d7af8..5f7d75c0fd4 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc @@ -30,8 +30,8 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/profiling/timers.h" -static grpc_error* clr_init_channel_elem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +static grpc_error_handle clr_init_channel_elem( + grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -54,7 +54,7 @@ struct call_data { } // namespace -static void on_complete_for_send(void* arg, grpc_error* error) { +static void on_complete_for_send(void* arg, grpc_error_handle error) { call_data* calld = static_cast(arg); if (error == GRPC_ERROR_NONE) { calld->send_initial_metadata_succeeded = true; @@ -63,7 +63,7 @@ static void on_complete_for_send(void* arg, grpc_error* error) { GRPC_ERROR_REF(error)); } -static void recv_initial_metadata_ready(void* arg, grpc_error* error) { +static void recv_initial_metadata_ready(void* arg, grpc_error_handle error) { call_data* calld = static_cast(arg); if (error == GRPC_ERROR_NONE) { calld->recv_initial_metadata_succeeded = true; @@ -73,8 +73,8 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { GRPC_ERROR_REF(error)); } -static grpc_error* clr_init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { +static grpc_error_handle clr_init_call_elem( + grpc_call_element* elem, const grpc_call_element_args* args) { GPR_ASSERT(args->context != nullptr); new (elem->call_data) call_data(); return GRPC_ERROR_NONE; diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 3b6e59b5f5a..4b4f1ab6c07 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -90,6 +90,8 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" @@ -98,9 +100,7 @@ #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" @@ -186,17 +186,17 @@ class GrpcLb : public LoadBalancingPolicy { void ScheduleNextClientLoadReportLocked(); void SendClientLoadReportLocked(); - static void MaybeSendClientLoadReport(void* arg, grpc_error* error); - static void ClientLoadReportDone(void* arg, grpc_error* error); - static void OnInitialRequestSent(void* arg, grpc_error* error); - static void OnBalancerMessageReceived(void* arg, grpc_error* error); - static void OnBalancerStatusReceived(void* arg, grpc_error* error); + static void MaybeSendClientLoadReport(void* arg, grpc_error_handle error); + static void ClientLoadReportDone(void* arg, grpc_error_handle error); + static void OnInitialRequestSent(void* arg, grpc_error_handle error); + static void OnBalancerMessageReceived(void* arg, grpc_error_handle error); + static void OnBalancerStatusReceived(void* arg, grpc_error_handle error); - void MaybeSendClientLoadReportLocked(grpc_error* error); - void ClientLoadReportDoneLocked(grpc_error* error); + void MaybeSendClientLoadReportLocked(grpc_error_handle error); + void ClientLoadReportDoneLocked(grpc_error_handle error); void OnInitialRequestSentLocked(); void OnBalancerMessageReceivedLocked(); - void OnBalancerStatusReceivedLocked(grpc_error* error); + void OnBalancerStatusReceivedLocked(grpc_error_handle error); // The owning LB policy. RefCountedPtr grpclb_policy_; @@ -410,14 +410,14 @@ class GrpcLb : public LoadBalancingPolicy { // Methods for dealing with fallback state. void MaybeEnterFallbackModeAfterStartup(); - static void OnFallbackTimer(void* arg, grpc_error* error); - void OnFallbackTimerLocked(grpc_error* error); + static void OnFallbackTimer(void* arg, grpc_error_handle error); + void OnFallbackTimerLocked(grpc_error_handle error); // Methods for dealing with the balancer call. void StartBalancerCallLocked(); void StartBalancerCallRetryTimerLocked(); - static void OnBalancerCallRetryTimer(void* arg, grpc_error* error); - void OnBalancerCallRetryTimerLocked(grpc_error* error); + static void OnBalancerCallRetryTimer(void* arg, grpc_error_handle error); + void OnBalancerCallRetryTimerLocked(grpc_error_handle error); // Methods for dealing with the child policy. grpc_channel_args* CreateChildPolicyArgsLocked( @@ -893,6 +893,10 @@ void GrpcLb::BalancerCallState::StartQuery() { } void GrpcLb::BalancerCallState::ScheduleNextClientLoadReportLocked() { + // InvalidateNow to avoid getting stuck re-initializing this timer + // in a loop while draining the currently-held WorkSerializer. + // Also see https://github.com/grpc/grpc/issues/26079. + ExecCtx::Get()->InvalidateNow(); const grpc_millis next_client_load_report_time = ExecCtx::Get()->Now() + client_stats_report_interval_; GRPC_CLOSURE_INIT(&client_load_report_closure_, MaybeSendClientLoadReport, @@ -902,8 +906,8 @@ void GrpcLb::BalancerCallState::ScheduleNextClientLoadReportLocked() { client_load_report_timer_callback_pending_ = true; } -void GrpcLb::BalancerCallState::MaybeSendClientLoadReport(void* arg, - grpc_error* error) { +void GrpcLb::BalancerCallState::MaybeSendClientLoadReport( + void* arg, grpc_error_handle error) { BalancerCallState* lb_calld = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda lb_calld->grpclb_policy()->work_serializer()->Run( @@ -912,7 +916,7 @@ void GrpcLb::BalancerCallState::MaybeSendClientLoadReport(void* arg, } void GrpcLb::BalancerCallState::MaybeSendClientLoadReportLocked( - grpc_error* error) { + grpc_error_handle error) { client_load_report_timer_callback_pending_ = false; if (error != GRPC_ERROR_NONE || this != grpclb_policy()->lb_calld_.get()) { Unref(DEBUG_LOCATION, "client_load_report"); @@ -982,7 +986,7 @@ void GrpcLb::BalancerCallState::SendClientLoadReportLocked() { } void GrpcLb::BalancerCallState::ClientLoadReportDone(void* arg, - grpc_error* error) { + grpc_error_handle error) { BalancerCallState* lb_calld = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda lb_calld->grpclb_policy()->work_serializer()->Run( @@ -990,7 +994,8 @@ void GrpcLb::BalancerCallState::ClientLoadReportDone(void* arg, DEBUG_LOCATION); } -void GrpcLb::BalancerCallState::ClientLoadReportDoneLocked(grpc_error* error) { +void GrpcLb::BalancerCallState::ClientLoadReportDoneLocked( + grpc_error_handle error) { grpc_byte_buffer_destroy(send_message_payload_); send_message_payload_ = nullptr; if (error != GRPC_ERROR_NONE || this != grpclb_policy()->lb_calld_.get()) { @@ -1001,8 +1006,8 @@ void GrpcLb::BalancerCallState::ClientLoadReportDoneLocked(grpc_error* error) { ScheduleNextClientLoadReportLocked(); } -void GrpcLb::BalancerCallState::OnInitialRequestSent(void* arg, - grpc_error* /*error*/) { +void GrpcLb::BalancerCallState::OnInitialRequestSent( + void* arg, grpc_error_handle /*error*/) { BalancerCallState* lb_calld = static_cast(arg); lb_calld->grpclb_policy()->work_serializer()->Run( [lb_calld]() { lb_calld->OnInitialRequestSentLocked(); }, DEBUG_LOCATION); @@ -1021,7 +1026,7 @@ void GrpcLb::BalancerCallState::OnInitialRequestSentLocked() { } void GrpcLb::BalancerCallState::OnBalancerMessageReceived( - void* arg, grpc_error* /*error*/) { + void* arg, grpc_error_handle /*error*/) { BalancerCallState* lb_calld = static_cast(arg); lb_calld->grpclb_policy()->work_serializer()->Run( [lb_calld]() { lb_calld->OnBalancerMessageReceivedLocked(); }, @@ -1183,8 +1188,8 @@ void GrpcLb::BalancerCallState::OnBalancerMessageReceivedLocked() { } } -void GrpcLb::BalancerCallState::OnBalancerStatusReceived(void* arg, - grpc_error* error) { +void GrpcLb::BalancerCallState::OnBalancerStatusReceived( + void* arg, grpc_error_handle error) { BalancerCallState* lb_calld = static_cast(arg); GRPC_ERROR_REF(error); // owned by lambda lb_calld->grpclb_policy()->work_serializer()->Run( @@ -1193,7 +1198,7 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceived(void* arg, } void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked( - grpc_error* error) { + grpc_error_handle error) { GPR_ASSERT(lb_call_ != nullptr); if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) { char* status_details = grpc_slice_to_c_string(lb_call_status_details_); @@ -1201,7 +1206,7 @@ void GrpcLb::BalancerCallState::OnBalancerStatusReceivedLocked( "[grpclb %p] lb_calld=%p: Status from LB server received. " "Status = %d, details = '%s', (lb_call: %p), error '%s'", grpclb_policy(), this, lb_call_status_, status_details, lb_call_, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); gpr_free(status_details); } GRPC_ERROR_UNREF(error); @@ -1420,13 +1425,12 @@ void GrpcLb::UpdateLocked(UpdateArgs args) { // Start watching the channel's connectivity state. If the channel // goes into state TRANSIENT_FAILURE before the timer fires, we go into // fallback mode even if the fallback timeout has not elapsed. - grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element( - grpc_channel_get_channel_stack(lb_channel_)); - GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter); + ClientChannel* client_channel = ClientChannel::GetFromChannel(lb_channel_); + GPR_ASSERT(client_channel != nullptr); // Ref held by callback. watcher_ = new StateWatcher(Ref(DEBUG_LOCATION, "StateWatcher")); - grpc_client_channel_start_connectivity_watch( - client_channel_elem, GRPC_CHANNEL_IDLE, + client_channel->AddConnectivityWatcher( + GRPC_CHANNEL_IDLE, OrphanablePtr(watcher_)); // Start balancer call. StartBalancerCallLocked(); @@ -1490,10 +1494,9 @@ void GrpcLb::ProcessAddressesAndChannelArgsLocked( } void GrpcLb::CancelBalancerChannelConnectivityWatchLocked() { - grpc_channel_element* client_channel_elem = grpc_channel_stack_last_element( - grpc_channel_get_channel_stack(lb_channel_)); - GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter); - grpc_client_channel_stop_connectivity_watch(client_channel_elem, watcher_); + ClientChannel* client_channel = ClientChannel::GetFromChannel(lb_channel_); + GPR_ASSERT(client_channel != nullptr); + client_channel->RemoveConnectivityWatcher(watcher_); } // @@ -1536,7 +1539,7 @@ void GrpcLb::StartBalancerCallRetryTimerLocked() { grpc_timer_init(&lb_call_retry_timer_, next_try, &lb_on_call_retry_); } -void GrpcLb::OnBalancerCallRetryTimer(void* arg, grpc_error* error) { +void GrpcLb::OnBalancerCallRetryTimer(void* arg, grpc_error_handle error) { GrpcLb* grpclb_policy = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda grpclb_policy->work_serializer()->Run( @@ -1546,7 +1549,7 @@ void GrpcLb::OnBalancerCallRetryTimer(void* arg, grpc_error* error) { DEBUG_LOCATION); } -void GrpcLb::OnBalancerCallRetryTimerLocked(grpc_error* error) { +void GrpcLb::OnBalancerCallRetryTimerLocked(grpc_error_handle error) { retry_timer_callback_pending_ = false; if (!shutting_down_ && error == GRPC_ERROR_NONE && lb_calld_ == nullptr) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_glb_trace)) { @@ -1580,7 +1583,7 @@ void GrpcLb::MaybeEnterFallbackModeAfterStartup() { } } -void GrpcLb::OnFallbackTimer(void* arg, grpc_error* error) { +void GrpcLb::OnFallbackTimer(void* arg, grpc_error_handle error) { GrpcLb* grpclb_policy = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda grpclb_policy->work_serializer()->Run( @@ -1588,7 +1591,7 @@ void GrpcLb::OnFallbackTimer(void* arg, grpc_error* error) { DEBUG_LOCATION); } -void GrpcLb::OnFallbackTimerLocked(grpc_error* error) { +void GrpcLb::OnFallbackTimerLocked(grpc_error_handle error) { // If we receive a serverlist after the timer fires but before this callback // actually runs, don't fall back. if (fallback_at_startup_checks_pending_ && !shutting_down_ && @@ -1692,12 +1695,12 @@ class GrpcLbFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kGrpclb; } RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const override { + const Json& json, grpc_error_handle* error) const override { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (json.type() == Json::Type::JSON_NULL) { return MakeRefCounted(nullptr, ""); } - std::vector error_list; + std::vector error_list; Json child_policy_config_json_tmp; const Json* child_policy_config_json; std::string service_name; @@ -1720,12 +1723,12 @@ class GrpcLbFactory : public LoadBalancingPolicyFactory { } else { child_policy_config_json = &it->second; } - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; RefCountedPtr child_policy_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( *child_policy_config_json, &parse_error); if (parse_error != GRPC_ERROR_NONE) { - std::vector child_errors; + std::vector child_errors; child_errors.push_back(parse_error); error_list.push_back( GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors)); diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc index d2a10296f5f..837cc09bb6f 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc @@ -31,9 +31,9 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/slice/slice_internal.h" diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h index f6e9440d3ee..c369827d32f 100644 --- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h @@ -66,7 +66,8 @@ class GrpcLbClientStats : public RefCounted { gpr_atm num_calls_finished_with_client_failed_to_send_ = 0; gpr_atm num_calls_finished_known_received_ = 0; Mutex drop_count_mu_; // Guards drop_token_counts_. - std::unique_ptr drop_token_counts_; + std::unique_ptr drop_token_counts_ + ABSL_GUARDED_BY(drop_count_mu_); }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index e7e98d97130..6b7568c8131 100644 --- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -26,9 +26,9 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/error_utils.h" @@ -197,7 +197,7 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() { // (If we are idle, then this will happen in ExitIdleLocked() if we // haven't gotten a non-empty update by the time the application tries // to start a new call.) - grpc_error* error = + grpc_error_handle error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); channel_control_helper()->UpdateState( @@ -314,7 +314,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_); // Set our state to that of the pending subchannel list. if (p->subchannel_list_->in_transient_failure()) { - grpc_error* error = grpc_error_set_int( + grpc_error_handle error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "selected subchannel failed; switching to pending update"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); @@ -393,7 +393,7 @@ void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked( subchannel_list()->set_in_transient_failure(true); // Only report new state in case 1. if (subchannel_list() == p->subchannel_list_.get()) { - grpc_error* error = grpc_error_set_int( + grpc_error_handle error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "failed to connect to all addresses"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); @@ -497,7 +497,7 @@ class PickFirstFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kPickFirst; } RefCountedPtr ParseLoadBalancingConfig( - const Json& /*json*/, grpc_error** /*error*/) const override { + const Json& /*json*/, grpc_error_handle* /*error*/) const override { return MakeRefCounted(); } }; diff --git a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc index ca4bc90a09d..3cd7c541878 100644 --- a/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +++ b/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc @@ -179,10 +179,10 @@ class PriorityLb : public LoadBalancingPolicy { void StartFailoverTimerLocked(); - static void OnFailoverTimer(void* arg, grpc_error* error); - void OnFailoverTimerLocked(grpc_error* error); - static void OnDeactivationTimer(void* arg, grpc_error* error); - void OnDeactivationTimerLocked(grpc_error* error); + static void OnFailoverTimer(void* arg, grpc_error_handle error); + void OnFailoverTimerLocked(grpc_error_handle error); + static void OnDeactivationTimer(void* arg, grpc_error_handle error); + void OnDeactivationTimerLocked(grpc_error_handle error); RefCountedPtr priority_policy_; const std::string name_; @@ -472,7 +472,7 @@ void PriorityLb::TryNextPriorityLocked(bool report_connecting) { this); } current_child_from_before_update_ = nullptr; - grpc_error* error = grpc_error_set_int( + grpc_error_handle error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ready priority"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); channel_control_helper()->UpdateState( @@ -655,14 +655,15 @@ void PriorityLb::ChildPriority::MaybeCancelFailoverTimerLocked() { } } -void PriorityLb::ChildPriority::OnFailoverTimer(void* arg, grpc_error* error) { +void PriorityLb::ChildPriority::OnFailoverTimer(void* arg, + grpc_error_handle error) { ChildPriority* self = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda self->priority_policy_->work_serializer()->Run( [self, error]() { self->OnFailoverTimerLocked(error); }, DEBUG_LOCATION); } -void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error* error) { +void PriorityLb::ChildPriority::OnFailoverTimerLocked(grpc_error_handle error) { if (error == GRPC_ERROR_NONE && failover_timer_callback_pending_ && !priority_policy_->shutting_down_) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { @@ -712,7 +713,7 @@ void PriorityLb::ChildPriority::MaybeReactivateLocked() { } void PriorityLb::ChildPriority::OnDeactivationTimer(void* arg, - grpc_error* error) { + grpc_error_handle error) { ChildPriority* self = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda self->priority_policy_->work_serializer()->Run( @@ -720,7 +721,8 @@ void PriorityLb::ChildPriority::OnDeactivationTimer(void* arg, DEBUG_LOCATION); } -void PriorityLb::ChildPriority::OnDeactivationTimerLocked(grpc_error* error) { +void PriorityLb::ChildPriority::OnDeactivationTimerLocked( + grpc_error_handle error) { if (error == GRPC_ERROR_NONE && deactivation_timer_callback_pending_ && !priority_policy_->shutting_down_) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { @@ -785,7 +787,7 @@ class PriorityLbFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kPriority; } RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const override { + const Json& json, grpc_error_handle* error) const override { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (json.type() == Json::Type::JSON_NULL) { // priority was mentioned as a policy in the deprecated @@ -796,7 +798,7 @@ class PriorityLbFactory : public LoadBalancingPolicyFactory { "config instead."); return nullptr; } - std::vector error_list; + std::vector error_list; // Children. std::map children; auto it = json.object_value().find("children"); @@ -824,7 +826,7 @@ class PriorityLbFactory : public LoadBalancingPolicyFactory { " error:missing 'config' field") .c_str())); } else { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; auto config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( it2->second, &parse_error); bool ignore_resolution_requests = false; diff --git a/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc b/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc new file mode 100644 index 00000000000..921bd2e0078 --- /dev/null +++ b/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc @@ -0,0 +1,23 @@ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// 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 + +namespace grpc_core { + +const char* kRequestRingHashAttribute = "request_ring_hash"; + +} // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h b/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h new file mode 100644 index 00000000000..dc176c2dc49 --- /dev/null +++ b/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h @@ -0,0 +1,27 @@ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_RING_HASH_RING_HASH_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_RING_HASH_RING_HASH_H + +#include + +namespace grpc_core { +extern const char* kRequestRingHashAttribute; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_RING_HASH_RING_HASH_H diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index efc7942a6a0..529d90d3478 100644 --- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -34,11 +34,11 @@ #include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/subchannel.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/static_metadata.h" @@ -331,7 +331,7 @@ void RoundRobin::RoundRobinSubchannelList:: absl::make_unique(p->Ref(DEBUG_LOCATION, "QueuePicker"))); } else if (num_transient_failure_ == num_subchannels()) { /* 3) TRANSIENT_FAILURE */ - grpc_error* error = + grpc_error_handle error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "connections to all backends failing"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); @@ -449,7 +449,7 @@ void RoundRobin::UpdateLocked(UpdateArgs args) { if (latest_pending_subchannel_list_->num_subchannels() == 0) { // If the new list is empty, immediately promote the new list to the // current list and transition to TRANSIENT_FAILURE. - grpc_error* error = + grpc_error_handle error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); channel_control_helper()->UpdateState( @@ -487,7 +487,7 @@ class RoundRobinFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kRoundRobin; } RefCountedPtr ParseLoadBalancingConfig( - const Json& /*json*/, grpc_error** /*error*/) const override { + const Json& /*json*/, grpc_error_handle* /*error*/) const override { return MakeRefCounted(); } }; diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index a240a2d0e17..b894c592c66 100644 --- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -33,13 +33,13 @@ // that implementation should be hidden from the LB policy API. #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/ext/filters/client_channel/subchannel_interface.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/transport/connectivity_state.h" // Code for maintaining a list of subchannels within an LB policy. diff --git a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc index 1eca478b488..ac1857be694 100644 --- a/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +++ b/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc @@ -165,8 +165,8 @@ class WeightedTargetLb : public LoadBalancingPolicy { grpc_connectivity_state state, const absl::Status& status, std::unique_ptr picker); - static void OnDelayedRemovalTimer(void* arg, grpc_error* error); - void OnDelayedRemovalTimerLocked(grpc_error* error); + static void OnDelayedRemovalTimer(void* arg, grpc_error_handle error); + void OnDelayedRemovalTimerLocked(grpc_error_handle error); // The owning LB policy. RefCountedPtr weighted_target_policy_; @@ -387,7 +387,7 @@ void WeightedTargetLb::UpdateStateLocked() { absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker")); break; default: - grpc_error* error = grpc_error_set_int( + grpc_error_handle error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "weighted_target: all children report state TRANSIENT_FAILURE"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); @@ -564,8 +564,8 @@ void WeightedTargetLb::WeightedChild::DeactivateLocked() { &on_delayed_removal_timer_); } -void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimer(void* arg, - grpc_error* error) { +void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimer( + void* arg, grpc_error_handle error) { WeightedChild* self = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda self->weighted_target_policy_->work_serializer()->Run( @@ -574,7 +574,7 @@ void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimer(void* arg, } void WeightedTargetLb::WeightedChild::OnDelayedRemovalTimerLocked( - grpc_error* error) { + grpc_error_handle error) { if (error == GRPC_ERROR_NONE && delayed_removal_timer_callback_pending_ && !shutdown_ && weight_ == 0) { delayed_removal_timer_callback_pending_ = false; @@ -631,7 +631,7 @@ class WeightedTargetLbFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kWeightedTarget; } RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const override { + const Json& json, grpc_error_handle* error) const override { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (json.type() == Json::Type::JSON_NULL) { // weighted_target was mentioned as a policy in the deprecated @@ -642,7 +642,7 @@ class WeightedTargetLbFactory : public LoadBalancingPolicyFactory { "config instead."); return nullptr; } - std::vector error_list; + std::vector error_list; // Weight map. WeightedTargetLbConfig::TargetMap target_map; auto it = json.object_value().find("targets"); @@ -655,14 +655,14 @@ class WeightedTargetLbFactory : public LoadBalancingPolicyFactory { } else { for (const auto& p : it->second.object_value()) { WeightedTargetLbConfig::ChildConfig child_config; - std::vector child_errors = + std::vector child_errors = ParseChildConfig(p.second, &child_config); if (!child_errors.empty()) { // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error // string is not static in this case. - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("field:targets key:", p.first).c_str()); - for (grpc_error* child_error : child_errors) { + for (grpc_error_handle child_error : child_errors) { error = grpc_error_add_child(error, child_error); } error_list.push_back(error); @@ -680,9 +680,9 @@ class WeightedTargetLbFactory : public LoadBalancingPolicyFactory { } private: - static std::vector ParseChildConfig( + static std::vector ParseChildConfig( const Json& json, WeightedTargetLbConfig::ChildConfig* child_config) { - std::vector error_list; + std::vector error_list; if (json.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "value should be of type object")); @@ -711,13 +711,13 @@ class WeightedTargetLbFactory : public LoadBalancingPolicyFactory { // Child policy. it = json.object_value().find("childPolicy"); if (it != json.object_value().end()) { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; child_config->config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(it->second, &parse_error); if (child_config->config == nullptr) { GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE); - std::vector child_errors; + std::vector child_errors; child_errors.push_back(parse_error); error_list.push_back( GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors)); diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc index 46cdb32f72a..49bff276958 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc @@ -75,7 +75,7 @@ class CdsLb : public LoadBalancingPolicy { void OnClusterChanged(XdsApi::CdsUpdate cluster_data) override { new Notifier(parent_, name_, std::move(cluster_data)); } - void OnError(grpc_error* error) override { + void OnError(grpc_error_handle error) override { new Notifier(parent_, name_, error); } void OnResourceDoesNotExist() override { new Notifier(parent_, name_); } @@ -86,14 +86,14 @@ class CdsLb : public LoadBalancingPolicy { Notifier(RefCountedPtr parent, std::string name, XdsApi::CdsUpdate update); Notifier(RefCountedPtr parent, std::string name, - grpc_error* error); + grpc_error_handle error); explicit Notifier(RefCountedPtr parent, std::string name); private: enum Type { kUpdate, kError, kDoesNotExist }; - static void RunInExecCtx(void* arg, grpc_error* error); - void RunInWorkSerializer(grpc_error* error); + static void RunInExecCtx(void* arg, grpc_error_handle error); + void RunInWorkSerializer(grpc_error_handle error); RefCountedPtr parent_; std::string name_; @@ -139,10 +139,10 @@ class CdsLb : public LoadBalancingPolicy { std::set* clusters_needed); void OnClusterChanged(const std::string& name, XdsApi::CdsUpdate cluster_data); - void OnError(const std::string& name, grpc_error* error); + void OnError(const std::string& name, grpc_error_handle error); void OnResourceDoesNotExist(const std::string& name); - grpc_error* UpdateXdsCertificateProvider( + grpc_error_handle UpdateXdsCertificateProvider( const std::string& cluster_name, const XdsApi::CdsUpdate& cluster_data); void CancelClusterDataWatch(absl::string_view cluster_name, @@ -190,7 +190,8 @@ CdsLb::ClusterWatcher::Notifier::Notifier(RefCountedPtr parent, } CdsLb::ClusterWatcher::Notifier::Notifier(RefCountedPtr parent, - std::string name, grpc_error* error) + std::string name, + grpc_error_handle error) : parent_(std::move(parent)), name_(std::move(name)), type_(kError) { GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr); ExecCtx::Run(DEBUG_LOCATION, &closure_, error); @@ -204,14 +205,15 @@ CdsLb::ClusterWatcher::Notifier::Notifier(RefCountedPtr parent, } void CdsLb::ClusterWatcher::Notifier::RunInExecCtx(void* arg, - grpc_error* error) { + grpc_error_handle error) { Notifier* self = static_cast(arg); GRPC_ERROR_REF(error); self->parent_->work_serializer()->Run( [self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION); } -void CdsLb::ClusterWatcher::Notifier::RunInWorkSerializer(grpc_error* error) { +void CdsLb::ClusterWatcher::Notifier::RunInWorkSerializer( + grpc_error_handle error) { switch (type_) { case kUpdate: parent_->OnClusterChanged(name_, std::move(update_)); @@ -434,7 +436,7 @@ void CdsLb::OnClusterChanged(const std::string& name, if (it == watchers_.end()) return; it->second.update = cluster_data; // Take care of integration with new certificate code. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; error = UpdateXdsCertificateProvider(name, it->second.update.value()); if (error != GRPC_ERROR_NONE) { return OnError(name, error); @@ -541,9 +543,9 @@ void CdsLb::OnClusterChanged(const std::string& name, } } -void CdsLb::OnError(const std::string& name, grpc_error* error) { +void CdsLb::OnError(const std::string& name, grpc_error_handle error) { gpr_log(GPR_ERROR, "[cdslb %p] xds error obtaining data for cluster %s: %s", - this, name.c_str(), grpc_error_string(error)); + this, name.c_str(), grpc_error_std_string(error).c_str()); // Go into TRANSIENT_FAILURE if we have not yet created the child // policy (i.e., we have not yet received data from xds). Otherwise, // we keep running with the data we had previously. @@ -561,7 +563,7 @@ void CdsLb::OnResourceDoesNotExist(const std::string& name) { "[cdslb %p] CDS resource for %s does not exist -- reporting " "TRANSIENT_FAILURE", this, name.c_str()); - grpc_error* error = + grpc_error_handle error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("CDS resource \"", config_->cluster(), "\" does not exist") @@ -573,7 +575,7 @@ void CdsLb::OnResourceDoesNotExist(const std::string& name) { MaybeDestroyChildPolicyLocked(); } -grpc_error* CdsLb::UpdateXdsCertificateProvider( +grpc_error_handle CdsLb::UpdateXdsCertificateProvider( const std::string& cluster_name, const XdsApi::CdsUpdate& cluster_data) { // Early out if channel is not configured to use xds security. grpc_channel_credentials* channel_credentials = @@ -599,10 +601,12 @@ grpc_error* CdsLb::UpdateXdsCertificateProvider( xds_client_->certificate_provider_store() .CreateOrGetCertificateProvider(root_provider_instance_name); if (new_root_provider == nullptr) { - return GRPC_ERROR_CREATE_FROM_COPIED_STRING( - absl::StrCat("Certificate provider instance name: \"", - root_provider_instance_name, "\" not recognized.") - .c_str()); + return grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("Certificate provider instance name: \"", + root_provider_instance_name, "\" not recognized.") + .c_str()), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); } } if (root_certificate_provider_ != new_root_provider) { @@ -637,10 +641,13 @@ grpc_error* CdsLb::UpdateXdsCertificateProvider( xds_client_->certificate_provider_store() .CreateOrGetCertificateProvider(identity_provider_instance_name); if (new_identity_provider == nullptr) { - return GRPC_ERROR_CREATE_FROM_COPIED_STRING( - absl::StrCat("Certificate provider instance name: \"", - identity_provider_instance_name, "\" not recognized.") - .c_str()); + return grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("Certificate provider instance name: \"", + identity_provider_instance_name, + "\" not recognized.") + .c_str()), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); } } if (identity_certificate_provider_ != new_identity_provider) { @@ -693,13 +700,12 @@ class CdsLbFactory : public LoadBalancingPolicyFactory { public: OrphanablePtr CreateLoadBalancingPolicy( LoadBalancingPolicy::Args args) const override { - grpc_error* error = GRPC_ERROR_NONE; - RefCountedPtr xds_client = XdsClient::GetOrCreate(&error); - if (error != GRPC_ERROR_NONE) { + RefCountedPtr xds_client = + XdsClient::GetFromChannelArgs(*args.args); + if (xds_client == nullptr) { gpr_log(GPR_ERROR, - "cannot get XdsClient to instantiate cds LB policy: %s", - grpc_error_string(error)); - GRPC_ERROR_UNREF(error); + "XdsClient not present in channel args -- cannot instantiate " + "cds LB policy"); return nullptr; } return MakeOrphanable(std::move(xds_client), std::move(args)); @@ -708,7 +714,7 @@ class CdsLbFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kCds; } RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const override { + const Json& json, grpc_error_handle* error) const override { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (json.type() == Json::Type::JSON_NULL) { // xds was mentioned as a policy in the deprecated loadBalancingPolicy @@ -718,7 +724,7 @@ class CdsLbFactory : public LoadBalancingPolicyFactory { "Please use loadBalancingConfig field of service config instead."); return nullptr; } - std::vector error_list; + std::vector error_list; // cluster name. std::string cluster; auto it = json.object_value().find("cluster"); diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc index b3790cfa7c1..7dbba6467d8 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc @@ -31,6 +31,7 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" @@ -56,6 +57,7 @@ class CircuitBreakerCallCounterMap { explicit CallCounter(Key key) : key_(std::move(key)) {} ~CallCounter() override; + uint32_t Load() { return concurrent_requests_.Load(MemoryOrder::SEQ_CST); } uint32_t Increment() { return concurrent_requests_.FetchAdd(1); } void Decrement() { concurrent_requests_.FetchSub(1); } @@ -69,7 +71,7 @@ class CircuitBreakerCallCounterMap { private: Mutex mu_; - std::map map_; + std::map map_ ABSL_GUARDED_BY(mu_); }; CircuitBreakerCallCounterMap* g_call_counter_map = nullptr; @@ -107,17 +109,6 @@ CircuitBreakerCallCounterMap::CallCounter::~CallCounter() { constexpr char kXdsClusterImpl[] = "xds_cluster_impl_experimental"; -// TODO (donnadionne): Check to see if circuit breaking is enabled, this will be -// removed once circuit breaking feature is fully integrated and enabled by -// default. -bool XdsCircuitBreakingEnabled() { - char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_CIRCUIT_BREAKING"); - bool parsed_value; - bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); - gpr_free(value); - return parse_succeeded && parsed_value; -} - // Config for xDS Cluster Impl LB policy. class XdsClusterImplLbConfig : public LoadBalancingPolicy::Config { public: @@ -208,7 +199,6 @@ class XdsClusterImplLb : public LoadBalancingPolicy { private: RefCountedPtr call_counter_; - bool xds_circuit_breaking_enabled_; uint32_t max_concurrent_requests_; RefCountedPtr drop_config_; RefCountedPtr drop_stats_; @@ -277,7 +267,6 @@ class XdsClusterImplLb : public LoadBalancingPolicy { XdsClusterImplLb::Picker::Picker(XdsClusterImplLb* xds_cluster_impl_lb, RefCountedPtr picker) : call_counter_(xds_cluster_impl_lb->call_counter_), - xds_circuit_breaking_enabled_(XdsCircuitBreakingEnabled()), max_concurrent_requests_( xds_cluster_impl_lb->config_->max_concurrent_requests()), drop_config_(xds_cluster_impl_lb->config_->drop_config()), @@ -300,17 +289,15 @@ LoadBalancingPolicy::PickResult XdsClusterImplLb::Picker::Pick( return result; } // Handle circuit breaking. - uint32_t current = call_counter_->Increment(); - if (xds_circuit_breaking_enabled_) { - // Check and see if we exceeded the max concurrent requests count. - if (current >= max_concurrent_requests_) { - call_counter_->Decrement(); - if (drop_stats_ != nullptr) drop_stats_->AddUncategorizedDrops(); - PickResult result; - result.type = PickResult::PICK_COMPLETE; - return result; - } + uint32_t current = call_counter_->Load(); + // Check and see if we exceeded the max concurrent requests count. + if (current >= max_concurrent_requests_) { + if (drop_stats_ != nullptr) drop_stats_->AddUncategorizedDrops(); + PickResult result; + result.type = PickResult::PICK_COMPLETE; + return result; } + call_counter_->Increment(); // If we're not dropping the call, we should always have a child picker. if (picker_ == nullptr) { // Should never happen. PickResult result; @@ -344,7 +331,7 @@ LoadBalancingPolicy::PickResult XdsClusterImplLb::Picker::Pick( // Note: This callback does not run in either the control plane // work serializer or in the data plane mutex. [locality_stats, original_recv_trailing_metadata_ready, call_counter]( - grpc_error* error, MetadataInterface* metadata, + grpc_error_handle error, MetadataInterface* metadata, CallState* call_state) { // Record call completion for load reporting. if (locality_stats != nullptr) { @@ -609,14 +596,12 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { public: OrphanablePtr CreateLoadBalancingPolicy( LoadBalancingPolicy::Args args) const override { - grpc_error* error = GRPC_ERROR_NONE; - RefCountedPtr xds_client = XdsClient::GetOrCreate(&error); - if (error != GRPC_ERROR_NONE) { - gpr_log( - GPR_ERROR, - "cannot get XdsClient to instantiate xds_cluster_impl LB policy: %s", - grpc_error_string(error)); - GRPC_ERROR_UNREF(error); + RefCountedPtr xds_client = + XdsClient::GetFromChannelArgs(*args.args); + if (xds_client == nullptr) { + gpr_log(GPR_ERROR, + "XdsClient not present in channel args -- cannot instantiate " + "xds_cluster_impl LB policy"); return nullptr; } return MakeOrphanable(std::move(xds_client), @@ -626,7 +611,7 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kXdsClusterImpl; } RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const override { + const Json& json, grpc_error_handle* error) const override { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (json.type() == Json::Type::JSON_NULL) { // This policy was configured in the deprecated loadBalancingPolicy @@ -637,7 +622,7 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { "config instead."); return nullptr; } - std::vector error_list; + std::vector error_list; // Child policy. RefCountedPtr child_policy; auto it = json.object_value().find("childPolicy"); @@ -645,12 +630,12 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "field:childPolicy error:required field missing")); } else { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; child_policy = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( it->second, &parse_error); if (child_policy == nullptr) { GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE); - std::vector child_errors; + std::vector child_errors; child_errors.push_back(parse_error); error_list.push_back( GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors)); @@ -709,7 +694,7 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "field:dropCategories error:required field missing")); } else { - std::vector child_errors = + std::vector child_errors = ParseDropCategories(it->second, drop_config.get()); if (!child_errors.empty()) { error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR( @@ -728,9 +713,9 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { } private: - static std::vector ParseDropCategories( + static std::vector ParseDropCategories( const Json& json, XdsApi::EdsUpdate::DropConfig* drop_config) { - std::vector error_list; + std::vector error_list; if (json.type() != Json::Type::ARRAY) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "dropCategories field is not an array")); @@ -738,10 +723,10 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { } for (size_t i = 0; i < json.array_value().size(); ++i) { const Json& entry = json.array_value()[i]; - std::vector child_errors = + std::vector child_errors = ParseDropCategory(entry, drop_config); if (!child_errors.empty()) { - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("errors parsing index ", i).c_str()); for (size_t i = 0; i < child_errors.size(); ++i) { error = grpc_error_add_child(error, child_errors[i]); @@ -752,9 +737,9 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { return error_list; } - static std::vector ParseDropCategory( + static std::vector ParseDropCategory( const Json& json, XdsApi::EdsUpdate::DropConfig* drop_config) { - std::vector error_list; + std::vector error_list; if (json.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "dropCategories entry is not an object")); diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc index 4d76b39d44c..1d4f1431db6 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc @@ -162,8 +162,8 @@ class XdsClusterManagerLb : public LoadBalancingPolicy { OrphanablePtr CreateChildPolicyLocked( const grpc_channel_args* args); - static void OnDelayedRemovalTimer(void* arg, grpc_error* error); - void OnDelayedRemovalTimerLocked(grpc_error* error); + static void OnDelayedRemovalTimer(void* arg, grpc_error_handle error); + void OnDelayedRemovalTimerLocked(grpc_error_handle error); // The owning LB policy. RefCountedPtr xds_cluster_manager_policy_; @@ -337,44 +337,29 @@ void XdsClusterManagerLb::UpdateStateLocked() { gpr_log(GPR_INFO, "[xds_cluster_manager_lb %p] connectivity changed to %s", this, ConnectivityStateName(connectivity_state)); } - std::unique_ptr picker; - absl::Status status; - switch (connectivity_state) { - case GRPC_CHANNEL_READY: { - ClusterPicker::ClusterMap cluster_map; - for (const auto& p : config_->cluster_map()) { - const std::string& cluster_name = p.first; - RefCountedPtr& child_picker = - cluster_map[cluster_name]; - child_picker = children_[cluster_name]->picker_wrapper(); - if (child_picker == nullptr) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_cluster_manager_lb_trace)) { - gpr_log( - GPR_INFO, + ClusterPicker::ClusterMap cluster_map; + for (const auto& p : config_->cluster_map()) { + const std::string& cluster_name = p.first; + RefCountedPtr& child_picker = cluster_map[cluster_name]; + child_picker = children_[cluster_name]->picker_wrapper(); + if (child_picker == nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_cluster_manager_lb_trace)) { + gpr_log(GPR_INFO, "[xds_cluster_manager_lb %p] child %s has not yet returned a " "picker; creating a QueuePicker.", this, cluster_name.c_str()); - } - child_picker = MakeRefCounted( - cluster_name, absl::make_unique( - Ref(DEBUG_LOCATION, "QueuePicker"))); - } } - picker = absl::make_unique(std::move(cluster_map)); - break; + child_picker = MakeRefCounted( + cluster_name, + absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker"))); } - case GRPC_CHANNEL_CONNECTING: - case GRPC_CHANNEL_IDLE: - picker = - absl::make_unique(Ref(DEBUG_LOCATION, "QueuePicker")); - break; - default: - grpc_error* error = grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "TRANSIENT_FAILURE from XdsClusterManagerLb"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); - status = grpc_error_to_absl_status(error); - picker = absl::make_unique(error); + } + std::unique_ptr picker = + absl::make_unique(std::move(cluster_map)); + absl::Status status; + if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { + status = absl::Status(absl::StatusCode::kUnavailable, + "TRANSIENT_FAILURE from XdsClusterManagerLb"); } channel_control_helper()->UpdateState(connectivity_state, status, std::move(picker)); @@ -501,7 +486,7 @@ void XdsClusterManagerLb::ClusterChild::ResetBackoffLocked() { void XdsClusterManagerLb::ClusterChild::DeactivateLocked() { // If already deactivated, don't do that again. - if (delayed_removal_timer_callback_pending_ == true) return; + if (delayed_removal_timer_callback_pending_) return; // Set the child weight to 0 so that future picker won't contain this child. // Start a timer to delete the child. Ref(DEBUG_LOCATION, "ClusterChild+timer").release(); @@ -513,7 +498,7 @@ void XdsClusterManagerLb::ClusterChild::DeactivateLocked() { } void XdsClusterManagerLb::ClusterChild::OnDelayedRemovalTimer( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { ClusterChild* self = static_cast(arg); GRPC_ERROR_REF(error); // Ref owned by the lambda self->xds_cluster_manager_policy_->work_serializer()->Run( @@ -522,7 +507,7 @@ void XdsClusterManagerLb::ClusterChild::OnDelayedRemovalTimer( } void XdsClusterManagerLb::ClusterChild::OnDelayedRemovalTimerLocked( - grpc_error* error) { + grpc_error_handle error) { delayed_removal_timer_callback_pending_ = false; if (error == GRPC_ERROR_NONE && !shutdown_) { xds_cluster_manager_policy_->children_.erase(name_); @@ -616,7 +601,7 @@ class XdsClusterManagerLbFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kXdsClusterManager; } RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const override { + const Json& json, grpc_error_handle* error) const override { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (json.type() == Json::Type::JSON_NULL) { // xds_cluster_manager was mentioned as a policy in the deprecated @@ -627,7 +612,7 @@ class XdsClusterManagerLbFactory : public LoadBalancingPolicyFactory { "config instead."); return nullptr; } - std::vector error_list; + std::vector error_list; XdsClusterManagerLbConfig::ClusterMap cluster_map; std::set clusters_to_be_used; auto it = json.object_value().find("children"); @@ -646,14 +631,14 @@ class XdsClusterManagerLbFactory : public LoadBalancingPolicyFactory { continue; } RefCountedPtr child_config; - std::vector child_errors = + std::vector child_errors = ParseChildConfig(p.second, &child_config); if (!child_errors.empty()) { // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error // string is not static in this case. - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("field:children name:", child_name).c_str()); - for (grpc_error* child_error : child_errors) { + for (grpc_error_handle child_error : child_errors) { error = grpc_error_add_child(error, child_error); } error_list.push_back(error); @@ -676,10 +661,10 @@ class XdsClusterManagerLbFactory : public LoadBalancingPolicyFactory { } private: - static std::vector ParseChildConfig( + static std::vector ParseChildConfig( const Json& json, RefCountedPtr* child_config) { - std::vector error_list; + std::vector error_list; if (json.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "value should be of type object")); @@ -690,12 +675,12 @@ class XdsClusterManagerLbFactory : public LoadBalancingPolicyFactory { error_list.push_back( GRPC_ERROR_CREATE_FROM_STATIC_STRING("did not find childPolicy")); } else { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; *child_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( it->second, &parse_error); if (*child_config == nullptr) { GPR_DEBUG_ASSERT(parse_error != GRPC_ERROR_NONE); - std::vector child_errors; + std::vector child_errors; child_errors.push_back(parse_error); error_list.push_back( GRPC_ERROR_CREATE_FROM_VECTOR("field:childPolicy", &child_errors)); diff --git a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc index f0e17fbfeaf..bcb8194561b 100644 --- a/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +++ b/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc @@ -101,7 +101,8 @@ class XdsClusterResolverLbConfig : public LoadBalancingPolicy::Config { // Xds Cluster Resolver LB policy. class XdsClusterResolverLb : public LoadBalancingPolicy { public: - XdsClusterResolverLb(RefCountedPtr xds_client, Args args); + XdsClusterResolverLb(RefCountedPtr xds_client, Args args, + std::string server_name, bool is_xds_uri); const char* name() const override { return kXdsClusterResolver; } @@ -131,7 +132,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { virtual bool disable_reresolution() = 0; // Caller must ensure that config_ is set before calling. - const absl::string_view GetXdsClusterResolverResourceName() const { + absl::string_view GetXdsClusterResolverResourceName() const { if (!parent_->is_xds_uri_) return parent_->server_name_; if (!parent_->config_->discovery_mechanisms()[index_] .eds_service_name.empty()) { @@ -184,7 +185,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { void OnEndpointChanged(XdsApi::EdsUpdate update) override { new Notifier(discovery_mechanism_, std::move(update)); } - void OnError(grpc_error* error) override { + void OnError(grpc_error_handle error) override { new Notifier(discovery_mechanism_, error); } void OnResourceDoesNotExist() override { @@ -197,7 +198,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { Notifier(RefCountedPtr discovery_mechanism, XdsApi::EdsUpdate update); Notifier(RefCountedPtr discovery_mechanism, - grpc_error* error); + grpc_error_handle error); explicit Notifier( RefCountedPtr discovery_mechanism); ~Notifier() { discovery_mechanism_.reset(DEBUG_LOCATION, "Notifier"); } @@ -205,8 +206,8 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { private: enum Type { kUpdate, kError, kDoesNotExist }; - static void RunInExecCtx(void* arg, grpc_error* error); - void RunInWorkSerializer(grpc_error* error); + static void RunInExecCtx(void* arg, grpc_error_handle error); + void RunInWorkSerializer(grpc_error_handle error); RefCountedPtr discovery_mechanism_; grpc_closure closure_; @@ -249,7 +250,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { void ReturnResult(Resolver::Result result) override; - void ReturnError(grpc_error* error) override; + void ReturnError(grpc_error_handle error) override; private: RefCountedPtr discovery_mechanism_; @@ -303,7 +304,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { void ShutdownLocked() override; void OnEndpointChanged(size_t index, XdsApi::EdsUpdate update); - void OnError(size_t index, grpc_error* error); + void OnError(size_t index, grpc_error_handle error); void OnResourceDoesNotExist(size_t index); void MaybeDestroyChildPolicyLocked(); @@ -317,6 +318,9 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { grpc_channel_args* CreateChildPolicyArgsLocked( const grpc_channel_args* args_in); + // The xds client and endpoint watcher. + RefCountedPtr xds_client_; + // Server name from target URI. std::string server_name_; bool is_xds_uri_; @@ -328,9 +332,6 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { // Internal state. bool shutting_down_ = false; - // The xds client and endpoint watcher. - RefCountedPtr xds_client_; - // Vector of discovery mechansism entries in priority order. std::vector discovery_mechanisms_; @@ -429,7 +430,7 @@ XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier:: XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier:: Notifier(RefCountedPtr discovery_mechanism, - grpc_error* error) + grpc_error_handle error) : discovery_mechanism_(std::move(discovery_mechanism)), type_(kError) { GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr); ExecCtx::Run(DEBUG_LOCATION, &closure_, error); @@ -445,7 +446,7 @@ XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier:: } void XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier:: - RunInExecCtx(void* arg, grpc_error* error) { + RunInExecCtx(void* arg, grpc_error_handle error) { Notifier* self = static_cast(arg); GRPC_ERROR_REF(error); self->discovery_mechanism_->parent()->work_serializer()->Run( @@ -453,7 +454,7 @@ void XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier:: } void XdsClusterResolverLb::EdsDiscoveryMechanism::EndpointWatcher::Notifier:: - RunInWorkSerializer(grpc_error* error) { + RunInWorkSerializer(grpc_error_handle error) { switch (type_) { case kUpdate: discovery_mechanism_->parent()->OnEndpointChanged( @@ -541,7 +542,7 @@ void XdsClusterResolverLb::LogicalDNSDiscoveryMechanism::ResolverResultHandler:: } void XdsClusterResolverLb::LogicalDNSDiscoveryMechanism::ResolverResultHandler:: - ReturnError(grpc_error* error) { + ReturnError(grpc_error_handle error) { discovery_mechanism_->parent()->OnError(discovery_mechanism_->index(), error); } @@ -550,26 +551,17 @@ void XdsClusterResolverLb::LogicalDNSDiscoveryMechanism::ResolverResultHandler:: // XdsClusterResolverLb::XdsClusterResolverLb(RefCountedPtr xds_client, - Args args) - : LoadBalancingPolicy(std::move(args)), xds_client_(std::move(xds_client)) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_cluster_resolver_trace)) { - gpr_log(GPR_INFO, - "[xds_cluster_resolver_lb %p] created -- using xds client %p", this, - xds_client_.get()); - } - // Record server name. - const char* server_uri = - grpc_channel_args_find_string(args.args, GRPC_ARG_SERVER_URI); - GPR_ASSERT(server_uri != nullptr); - absl::StatusOr uri = URI::Parse(server_uri); - GPR_ASSERT(uri.ok() && !uri->path().empty()); - server_name_ = std::string(absl::StripPrefix(uri->path(), "/")); - is_xds_uri_ = uri->scheme() == "xds"; + Args args, std::string server_name, + bool is_xds_uri) + : LoadBalancingPolicy(std::move(args)), + xds_client_(std::move(xds_client)), + server_name_(std::move(server_name)), + is_xds_uri_(is_xds_uri) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_cluster_resolver_trace)) { gpr_log(GPR_INFO, - "[xds_cluster_resolver_lb %p] server name from channel " - "(is_xds_uri=%d): %s", - this, is_xds_uri_, server_name_.c_str()); + "[xds_cluster_resolver_lb %p] created -- xds_client=%p, " + "server_name=%s, is_xds_uri=%d", + this, xds_client_.get(), server_name_.c_str(), is_xds_uri_); } // EDS-only flow. if (!is_xds_uri_) { @@ -738,11 +730,11 @@ void XdsClusterResolverLb::OnEndpointChanged(size_t index, UpdatePriorityList(std::move(priority_list)); } -void XdsClusterResolverLb::OnError(size_t index, grpc_error* error) { +void XdsClusterResolverLb::OnError(size_t index, grpc_error_handle error) { gpr_log(GPR_ERROR, "[xds_cluster_resolver_lb %p] discovery mechanism %" PRIuPTR " xds watcher reported error: %s", - this, index, grpc_error_string(error)); + this, index, grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); if (shutting_down_) return; if (!discovery_mechanisms_[index].first_update_received) { @@ -1010,7 +1002,7 @@ XdsClusterResolverLb::CreateChildPolicyConfigLocked() { "[xds_cluster_resolver_lb %p] generated config for child policy: %s", this, json_str.c_str()); } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; RefCountedPtr config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(json, &error); if (error != GRPC_ERROR_NONE) { @@ -1020,7 +1012,7 @@ XdsClusterResolverLb::CreateChildPolicyConfigLocked() { "[xds_cluster_resolver_lb %p] error parsing generated child policy " "config -- " "will put channel in TRANSIENT_FAILURE: %s", - this, grpc_error_string(error)); + this, grpc_error_std_string(error).c_str()); error = grpc_error_set_int( grpc_error_add_child(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "xds_cluster_resolver LB policy: error " @@ -1054,10 +1046,14 @@ void XdsClusterResolverLb::UpdateChildPolicyLocked() { grpc_channel_args* XdsClusterResolverLb::CreateChildPolicyArgsLocked( const grpc_channel_args* args) { - // Inhibit client-side health checking, since the balancer does this for us. - grpc_arg new_arg = grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1); - return grpc_channel_args_copy_and_add(args, &new_arg, 1); + absl::InlinedVector new_args = { + // Inhibit client-side health checking, since the balancer does this + // for us. + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1), + }; + if (!is_xds_uri_) new_args.push_back(xds_client_->MakeChannelArg()); + return grpc_channel_args_copy_and_add(args, new_args.data(), new_args.size()); } OrphanablePtr @@ -1096,24 +1092,45 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { public: OrphanablePtr CreateLoadBalancingPolicy( LoadBalancingPolicy::Args args) const override { - grpc_error* error = GRPC_ERROR_NONE; - RefCountedPtr xds_client = XdsClient::GetOrCreate(&error); - if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, - "cannot get XdsClient to instantiate xds_cluster_resolver LB " - "policy: %s", - grpc_error_string(error)); - GRPC_ERROR_UNREF(error); - return nullptr; + // Find server name. + const char* server_uri = + grpc_channel_args_find_string(args.args, GRPC_ARG_SERVER_URI); + GPR_ASSERT(server_uri != nullptr); + absl::StatusOr uri = URI::Parse(server_uri); + GPR_ASSERT(uri.ok() && !uri->path().empty()); + absl::string_view server_name = absl::StripPrefix(uri->path(), "/"); + // Determine if it's an xds URI. + bool is_xds_uri = uri->scheme() == "xds"; + // Get XdsClient. + RefCountedPtr xds_client = + XdsClient::GetFromChannelArgs(*args.args); + if (xds_client == nullptr) { + if (!is_xds_uri) { + grpc_error_handle error = GRPC_ERROR_NONE; + xds_client = XdsClient::GetOrCreate(args.args, &error); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_ERROR, + "cannot get or create XdsClient to instantiate " + "xds_cluster_resolver LB policy: %s", + grpc_error_std_string(error).c_str()); + GRPC_ERROR_UNREF(error); + return nullptr; + } + } else { + gpr_log(GPR_ERROR, + "XdsClient not present in channel args -- cannot instantiate " + "xds_cluster_resolver LB policy"); + return nullptr; + } } - return MakeOrphanable(std::move(xds_client), - std::move(args)); + return MakeOrphanable( + std::move(xds_client), std::move(args), server_name, is_xds_uri); } const char* name() const override { return kXdsClusterResolver; } RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const override { + const Json& json, grpc_error_handle* error) const override { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (json.type() == Json::Type::JSON_NULL) { // xds_cluster_resolver was mentioned as a policy in the deprecated @@ -1124,7 +1141,7 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { "Please use loadBalancingConfig field of service config instead."); return nullptr; } - std::vector error_list; + std::vector error_list; std::vector discovery_mechanisms; auto it = json.object_value().find("discoveryMechanisms"); @@ -1138,13 +1155,13 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { const Json::Array& array = it->second.array_value(); for (size_t i = 0; i < array.size(); ++i) { XdsClusterResolverLbConfig::DiscoveryMechanism discovery_mechanism; - std::vector discovery_mechanism_errors = + std::vector discovery_mechanism_errors = ParseDiscoveryMechanism(array[i], &discovery_mechanism); if (!discovery_mechanism_errors.empty()) { - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("field:discovery_mechanism element: ", i, " error") .c_str()); - for (grpc_error* discovery_mechanism_error : + for (grpc_error_handle discovery_mechanism_error : discovery_mechanism_errors) { error = grpc_error_add_child(error, discovery_mechanism_error); } @@ -1259,10 +1276,10 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { } private: - static std::vector ParseDiscoveryMechanism( + static std::vector ParseDiscoveryMechanism( const Json& json, XdsClusterResolverLbConfig::DiscoveryMechanism* discovery_mechanism) { - std::vector error_list; + std::vector error_list; if (json.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "value should be of type object")); @@ -1339,10 +1356,13 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { class XdsClusterResolverChildHandler : public ChildPolicyHandler { public: XdsClusterResolverChildHandler(RefCountedPtr xds_client, - Args args) + Args args, absl::string_view server_name, + bool is_xds_uri) : ChildPolicyHandler(std::move(args), &grpc_lb_xds_cluster_resolver_trace), - xds_client_(std::move(xds_client)) {} + xds_client_(std::move(xds_client)), + server_name_(server_name), + is_xds_uri_(is_xds_uri) {} bool ConfigChangeRequiresNewPolicyInstance( LoadBalancingPolicy::Config* old_config, @@ -1359,11 +1379,14 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { OrphanablePtr CreateLoadBalancingPolicy( const char* /*name*/, LoadBalancingPolicy::Args args) const override { - return MakeOrphanable(xds_client_, std::move(args)); + return MakeOrphanable(xds_client_, std::move(args), + server_name_, is_xds_uri_); } private: RefCountedPtr xds_client_; + std::string server_name_; + bool is_xds_uri_; }; }; diff --git a/src/core/ext/filters/client_channel/lb_policy_factory.h b/src/core/ext/filters/client_channel/lb_policy_factory.h index 9e4425fa447..a595c2710d0 100644 --- a/src/core/ext/filters/client_channel/lb_policy_factory.h +++ b/src/core/ext/filters/client_channel/lb_policy_factory.h @@ -39,7 +39,7 @@ class LoadBalancingPolicyFactory { virtual const char* name() const = 0; virtual RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error) const = 0; + const Json& json, grpc_error_handle* error) const = 0; }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/lb_policy_registry.cc b/src/core/ext/filters/client_channel/lb_policy_registry.cc index d64a6434494..a3f03473a79 100644 --- a/src/core/ext/filters/client_channel/lb_policy_registry.cc +++ b/src/core/ext/filters/client_channel/lb_policy_registry.cc @@ -109,7 +109,7 @@ bool LoadBalancingPolicyRegistry::LoadBalancingPolicyExists( return false; } if (requires_config != nullptr) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; // Check if the load balancing policy allows an empty config *requires_config = factory->ParseLoadBalancingConfig(Json(), &error) == nullptr; @@ -122,7 +122,7 @@ namespace { // Returns the JSON node of policy (with both policy name and config content) // given the JSON node of a LoadBalancingConfig array. -grpc_error* ParseLoadBalancingConfigHelper( +grpc_error_handle ParseLoadBalancingConfigHelper( const Json& lb_config_array, Json::Object::const_iterator* result) { if (lb_config_array.type() != Json::Type::ARRAY) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("type should be array"); @@ -163,8 +163,8 @@ grpc_error* ParseLoadBalancingConfigHelper( } // namespace RefCountedPtr -LoadBalancingPolicyRegistry::ParseLoadBalancingConfig(const Json& json, - grpc_error** error) { +LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( + const Json& json, grpc_error_handle* error) { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); GPR_ASSERT(g_state != nullptr); Json::Object::const_iterator policy; diff --git a/src/core/ext/filters/client_channel/lb_policy_registry.h b/src/core/ext/filters/client_channel/lb_policy_registry.h index 8d2e3e395d5..aba44a8a705 100644 --- a/src/core/ext/filters/client_channel/lb_policy_registry.h +++ b/src/core/ext/filters/client_channel/lb_policy_registry.h @@ -57,7 +57,7 @@ class LoadBalancingPolicyRegistry { /// Returns a parsed object of the load balancing policy to be used from a /// LoadBalancingConfig array \a json. static RefCountedPtr ParseLoadBalancingConfig( - const Json& json, grpc_error** error); + const Json& json, grpc_error_handle* error); }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.cc b/src/core/ext/filters/client_channel/local_subchannel_pool.cc index e57599962ad..49338ecc5ea 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.cc +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.cc @@ -24,73 +24,33 @@ namespace grpc_core { -LocalSubchannelPool::LocalSubchannelPool() { - subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_); +RefCountedPtr LocalSubchannelPool::RegisterSubchannel( + const SubchannelKey& key, RefCountedPtr constructed) { + auto it = subchannel_map_.find(key); + // Because this pool is only accessed under the client channel's work + // serializer, and because FindSubchannel is checked before invoking + // RegisterSubchannel, no such subchannel should exist in the map. + GPR_ASSERT(it == subchannel_map_.end()); + subchannel_map_[key] = constructed.get(); + return constructed; +} + +void LocalSubchannelPool::UnregisterSubchannel(const SubchannelKey& key, + Subchannel* subchannel) { + auto it = subchannel_map_.find(key); + // Because this subchannel pool is accessed only under the client + // channel's work serializer, any subchannel created by RegisterSubchannel + // will be deleted from the map in UnregisterSubchannel. + GPR_ASSERT(it != subchannel_map_.end()); + GPR_ASSERT(it->second == subchannel); + subchannel_map_.erase(it); +} + +RefCountedPtr LocalSubchannelPool::FindSubchannel( + const SubchannelKey& key) { + auto it = subchannel_map_.find(key); + if (it == subchannel_map_.end()) return nullptr; + return it->second->Ref(); } -LocalSubchannelPool::~LocalSubchannelPool() { - grpc_avl_unref(subchannel_map_, nullptr); -} - -Subchannel* LocalSubchannelPool::RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) { - // Check to see if a subchannel already exists. - Subchannel* c = - static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); - if (c != nullptr) { - // The subchannel already exists. Reuse it. - c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse"); - GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing"); - } else { - // There hasn't been such subchannel. Add one. - subchannel_map_ = grpc_avl_add(subchannel_map_, new SubchannelKey(*key), - constructed, nullptr); - c = constructed; - } - return c; -} - -void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) { - subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr); -} - -Subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) { - Subchannel* c = - static_cast(grpc_avl_get(subchannel_map_, key, nullptr)); - return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool"); -} - -namespace { - -void sck_avl_destroy(void* p, void* /*user_data*/) { - SubchannelKey* key = static_cast(p); - delete key; -} - -void* sck_avl_copy(void* p, void* /*unused*/) { - const SubchannelKey* key = static_cast(p); - auto new_key = new SubchannelKey(*key); - return static_cast(new_key); -} - -long sck_avl_compare(void* a, void* b, void* /*unused*/) { - const SubchannelKey* key_a = static_cast(a); - const SubchannelKey* key_b = static_cast(b); - return key_a->Cmp(*key_b); -} - -void scv_avl_destroy(void* /*p*/, void* /*user_data*/) {} - -void* scv_avl_copy(void* p, void* /*unused*/) { return p; } - -} // namespace - -const grpc_avl_vtable LocalSubchannelPool::subchannel_avl_vtable_ = { - sck_avl_destroy, // destroy_key - sck_avl_copy, // copy_key - sck_avl_compare, // compare_keys - scv_avl_destroy, // destroy_value - scv_avl_copy // copy_value -}; - } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/local_subchannel_pool.h b/src/core/ext/filters/client_channel/local_subchannel_pool.h index 7d18d9b53f5..f039f6da9ab 100644 --- a/src/core/ext/filters/client_channel/local_subchannel_pool.h +++ b/src/core/ext/filters/client_channel/local_subchannel_pool.h @@ -21,6 +21,8 @@ #include +#include + #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" namespace grpc_core { @@ -34,22 +36,21 @@ namespace grpc_core { // Thread-unsafe. class LocalSubchannelPool final : public SubchannelPoolInterface { public: - LocalSubchannelPool(); - ~LocalSubchannelPool() override; + LocalSubchannelPool() {} + ~LocalSubchannelPool() override {} // Implements interface methods. // Thread-unsafe. Intended to be invoked within the client_channel work // serializer. - Subchannel* RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) override; - void UnregisterSubchannel(SubchannelKey* key) override; - Subchannel* FindSubchannel(SubchannelKey* key) override; + RefCountedPtr RegisterSubchannel( + const SubchannelKey& key, RefCountedPtr constructed) override; + void UnregisterSubchannel(const SubchannelKey& key, + Subchannel* subchannel) override; + RefCountedPtr FindSubchannel(const SubchannelKey& key) override; private: - // The vtable for subchannel operations in an AVL tree. - static const grpc_avl_vtable subchannel_avl_vtable_; // A map from subchannel key to subchannel. - grpc_avl subchannel_map_; + std::map subchannel_map_; }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/resolver.cc b/src/core/ext/filters/client_channel/resolver.cc index bbcf013cc9b..a5494b1666a 100644 --- a/src/core/ext/filters/client_channel/resolver.cc +++ b/src/core/ext/filters/client_channel/resolver.cc @@ -60,6 +60,9 @@ Resolver::Result::Result(Result&& other) noexcept { } Resolver::Result& Resolver::Result::operator=(const Result& other) { + if (&other == this) { + return *this; + } addresses = other.addresses; service_config = other.service_config; GRPC_ERROR_UNREF(service_config_error); diff --git a/src/core/ext/filters/client_channel/resolver.h b/src/core/ext/filters/client_channel/resolver.h index bd556a60c9e..2ab74096fb0 100644 --- a/src/core/ext/filters/client_channel/resolver.h +++ b/src/core/ext/filters/client_channel/resolver.h @@ -55,7 +55,7 @@ class Resolver : public InternallyRefCounted { struct Result { ServerAddressList addresses; RefCountedPtr service_config; - grpc_error* service_config_error = GRPC_ERROR_NONE; + grpc_error_handle service_config_error = GRPC_ERROR_NONE; const grpc_channel_args* args = nullptr; // TODO(roth): Remove everything below once grpc_error and @@ -81,7 +81,7 @@ class Resolver : public InternallyRefCounted { /// Returns a transient error to the channel. /// If the resolver does not set the GRPC_ERROR_INT_GRPC_STATUS /// attribute on the error, calls will be failed with status UNKNOWN. - virtual void ReturnError(grpc_error* error) = 0; + virtual void ReturnError(grpc_error_handle error) = 0; // TODO(yashkt): As part of the service config error handling // changes, add a method to parse the service config JSON string. diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 922ac453df3..2911eae7dc7 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -80,10 +80,10 @@ class AresDnsResolver : public Resolver { void MaybeStartResolvingLocked(); void StartResolvingLocked(); - static void OnNextResolution(void* arg, grpc_error* error); - static void OnResolved(void* arg, grpc_error* error); - void OnNextResolutionLocked(grpc_error* error); - void OnResolvedLocked(grpc_error* error); + static void OnNextResolution(void* arg, grpc_error_handle error); + static void OnResolved(void* arg, grpc_error_handle error); + void OnNextResolutionLocked(grpc_error_handle error); + void OnResolvedLocked(grpc_error_handle error); /// DNS server to use (if not system default) std::string dns_server_; @@ -193,18 +193,18 @@ void AresDnsResolver::ShutdownLocked() { } } -void AresDnsResolver::OnNextResolution(void* arg, grpc_error* error) { +void AresDnsResolver::OnNextResolution(void* arg, grpc_error_handle error) { AresDnsResolver* r = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda r->work_serializer_->Run([r, error]() { r->OnNextResolutionLocked(error); }, DEBUG_LOCATION); } -void AresDnsResolver::OnNextResolutionLocked(grpc_error* error) { +void AresDnsResolver::OnNextResolutionLocked(grpc_error_handle error) { GRPC_CARES_TRACE_LOG( "resolver:%p re-resolution timer fired. error: %s. shutdown_initiated_: " "%d", - this, grpc_error_string(error), shutdown_initiated_); + this, grpc_error_std_string(error).c_str(), shutdown_initiated_); have_next_resolution_timer_ = false; if (error == GRPC_ERROR_NONE && !shutdown_initiated_) { if (!resolving_) { @@ -227,7 +227,7 @@ bool ValueInJsonArray(const Json::Array& array, const char* value) { } std::string ChooseServiceConfig(char* service_config_choice_json, - grpc_error** error) { + grpc_error_handle* error) { Json json = Json::Parse(service_config_choice_json, error); if (*error != GRPC_ERROR_NONE) return ""; if (json.type() != Json::Type::ARRAY) { @@ -236,7 +236,7 @@ std::string ChooseServiceConfig(char* service_config_choice_json, return ""; } const Json* service_config = nullptr; - absl::InlinedVector error_list; + absl::InlinedVector error_list; for (const Json& choice : json.array_value()) { if (choice.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -305,14 +305,14 @@ std::string ChooseServiceConfig(char* service_config_choice_json, return service_config->Dump(); } -void AresDnsResolver::OnResolved(void* arg, grpc_error* error) { +void AresDnsResolver::OnResolved(void* arg, grpc_error_handle error) { AresDnsResolver* r = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda r->work_serializer_->Run([r, error]() { r->OnResolvedLocked(error); }, DEBUG_LOCATION); } -void AresDnsResolver::OnResolvedLocked(grpc_error* error) { +void AresDnsResolver::OnResolvedLocked(grpc_error_handle error) { GPR_ASSERT(resolving_); resolving_ = false; gpr_free(pending_request_); @@ -354,7 +354,7 @@ void AresDnsResolver::OnResolvedLocked(grpc_error* error) { backoff_.Reset(); } else { GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", this, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); std::string error_message = absl::StrCat("DNS resolution failed for service: ", name_to_resolve_); result_handler_->ReturnError(grpc_error_set_int( @@ -362,10 +362,14 @@ void AresDnsResolver::OnResolvedLocked(grpc_error* error) { &error, 1), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); // Set retry timer. + // InvalidateNow to avoid getting stuck re-initializing this timer + // in a loop while draining the currently-held WorkSerializer. + // Also see https://github.com/grpc/grpc/issues/26079. + ExecCtx::Get()->InvalidateNow(); grpc_millis next_try = backoff_.NextAttemptTime(); grpc_millis timeout = next_try - ExecCtx::Get()->Now(); GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed (will retry): %s", - this, grpc_error_string(error)); + this, grpc_error_std_string(error).c_str()); GPR_ASSERT(!have_next_resolution_timer_); have_next_resolution_timer_ = true; // TODO(roth): We currently deal with this ref manually. Once the @@ -389,6 +393,10 @@ void AresDnsResolver::MaybeStartResolvingLocked() { // can start the next resolution. if (have_next_resolution_timer_) return; if (last_resolution_timestamp_ >= 0) { + // InvalidateNow to avoid getting stuck re-initializing this timer + // in a loop while draining the currently-held WorkSerializer. + // Also see https://github.com/grpc/grpc/issues/26079. + ExecCtx::Get()->InvalidateNow(); const grpc_millis earliest_next_resolution = last_resolution_timestamp_ + min_time_between_resolutions_; const grpc_millis ms_until_next_resolution = @@ -455,7 +463,7 @@ class AresDnsResolverFactory : public ResolverFactory { extern grpc_address_resolver_vtable* grpc_resolve_address_impl; static grpc_address_resolver_vtable* default_resolver; -static grpc_error* blocking_resolve_address_ares( +static grpc_error_handle blocking_resolve_address_ares( const char* name, const char* default_port, grpc_resolved_addresses** addresses) { return default_resolver->blocking_resolve_address(name, default_port, @@ -490,7 +498,7 @@ void grpc_resolver_dns_ares_init() { g_use_ares_dns_resolver = true; gpr_log(GPR_DEBUG, "Using ares dns resolver"); address_sorting_init(); - grpc_error* error = grpc_ares_init(); + grpc_error_handle error = grpc_ares_init(); if (error != GRPC_ERROR_NONE) { GRPC_LOG_IF_ERROR("grpc_ares_init() failed", error); return; diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h index cc884864862..08069232b94 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h @@ -42,7 +42,7 @@ class GrpcPolledFd { virtual bool IsFdStillReadableLocked() = 0; /* Called once and only once. Must cause cancellation of any pending * read/write callbacks. */ - virtual void ShutdownLocked(grpc_error* error) = 0; + virtual void ShutdownLocked(grpc_error_handle error) = 0; /* Get the underlying ares_socket_t that this was created from */ virtual ares_socket_t GetWrappedAresSocketLocked() = 0; /* A unique name, for logging */ diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc index e5eea5c6a13..5c4c5350b23 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_libuv.cc @@ -75,7 +75,7 @@ class GrpcPolledFdLibuv : public GrpcPolledFd { return false; } - void ShutdownInternalLocked(grpc_error* error) { + void ShutdownInternalLocked(grpc_error_handle error) { uv_poll_stop(handle_); uv_close(reinterpret_cast(handle_), ares_uv_poll_close_cb); if (read_closure_ != nullptr) { @@ -88,7 +88,7 @@ class GrpcPolledFdLibuv : public GrpcPolledFd { } } - void ShutdownLocked(grpc_error* error) override { + void ShutdownLocked(grpc_error_handle error) override { if (grpc_core::ExecCtx::Get() == nullptr) { grpc_core::ExecCtx exec_ctx; ShutdownInternalLocked(error); @@ -127,7 +127,7 @@ static void ares_uv_poll_cb_locked(AresUvPollCbArg* arg) { int events = arg_struct->events; GrpcPolledFdLibuv* polled_fd = reinterpret_cast(handle->data); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (status < 0) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("cares polling error"); error = diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc index 07f38ba59ab..31de6799e1f 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc @@ -33,10 +33,10 @@ #include #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" namespace grpc_core { @@ -72,7 +72,7 @@ class GrpcPolledFdPosix : public GrpcPolledFd { bytes_available > 0; } - void ShutdownLocked(grpc_error* error) override { + void ShutdownLocked(grpc_error_handle error) override { grpc_fd_shutdown(fd_, error); } diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc index 9b6a0d5023a..0b4675fad5b 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc @@ -30,10 +30,10 @@ #include #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/iocp_windows.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr_windows.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_windows.h" @@ -131,12 +131,12 @@ class GrpcPolledFdWindows { grpc_winsocket_destroy(winsocket_); } - void ScheduleAndNullReadClosure(grpc_error* error) { + void ScheduleAndNullReadClosure(grpc_error_handle error) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, read_closure_, error); read_closure_ = nullptr; } - void ScheduleAndNullWriteClosure(grpc_error* error) { + void ScheduleAndNullWriteClosure(grpc_error_handle error) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, write_closure_, error); write_closure_ = nullptr; } @@ -251,9 +251,9 @@ class GrpcPolledFdWindows { } } - bool IsFdStillReadableLocked() { return GRPC_SLICE_LENGTH(read_buf_) > 0; } + bool IsFdStillReadableLocked() { return read_buf_has_data_; } - void ShutdownLocked(grpc_error* error) { + void ShutdownLocked(grpc_error_handle error) { grpc_winsocket_shutdown(winsocket_); } @@ -362,6 +362,8 @@ class GrpcPolledFdWindows { DWORD bytes_sent = 0; int wsa_error_code = 0; if (SendWriteBuf(&bytes_sent, nullptr, &wsa_error_code) != 0) { + grpc_slice_unref_internal(write_buf_); + write_buf_ = grpc_empty_slice(); wsa_error_ctx->SetWSAError(wsa_error_code); char* msg = gpr_format_message(wsa_error_code); GRPC_CARES_TRACE_LOG( @@ -418,7 +420,7 @@ class GrpcPolledFdWindows { abort(); } - static void OnTcpConnect(void* arg, grpc_error* error) { + static void OnTcpConnect(void* arg, grpc_error_handle error) { GrpcPolledFdWindows* grpc_polled_fd = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda @@ -429,12 +431,12 @@ class GrpcPolledFdWindows { DEBUG_LOCATION); } - void OnTcpConnectLocked(grpc_error* error) { + void OnTcpConnectLocked(grpc_error_handle error) { GRPC_CARES_TRACE_LOG( "fd:%s InnerOnTcpConnectLocked error:|%s| " "pending_register_for_readable:%d" " pending_register_for_writeable:%d", - GetName(), grpc_error_string(error), + GetName(), grpc_error_std_string(error).c_str(), pending_continue_register_for_on_readable_locked_, pending_continue_register_for_on_writeable_locked_); GPR_ASSERT(!connect_done_); @@ -574,7 +576,7 @@ class GrpcPolledFdWindows { return out; } - static void OnIocpReadable(void* arg, grpc_error* error) { + static void OnIocpReadable(void* arg, grpc_error_handle error) { GrpcPolledFdWindows* polled_fd = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda polled_fd->work_serializer_->Run( @@ -587,7 +589,7 @@ class GrpcPolledFdWindows { // c-ares reads from this socket later, but it shouldn't necessarily cancel // the entire resolution attempt. Doing so will allow the "inject broken // nameserver list" test to pass on Windows. - void OnIocpReadableLocked(grpc_error* error) { + void OnIocpReadableLocked(grpc_error_handle error) { if (error == GRPC_ERROR_NONE) { if (winsocket_->read_info.wsa_error != 0) { /* WSAEMSGSIZE would be due to receiving more data @@ -601,7 +603,7 @@ class GrpcPolledFdWindows { "fd:|%s| OnIocpReadableInner winsocket_->read_info.wsa_error " "code:|%d| msg:|%s|", GetName(), winsocket_->read_info.wsa_error, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } } } @@ -619,7 +621,7 @@ class GrpcPolledFdWindows { ScheduleAndNullReadClosure(error); } - static void OnIocpWriteable(void* arg, grpc_error* error) { + static void OnIocpWriteable(void* arg, grpc_error_handle error) { GrpcPolledFdWindows* polled_fd = static_cast(arg); GRPC_ERROR_REF(error); // error owned by lambda polled_fd->work_serializer_->Run( @@ -627,7 +629,7 @@ class GrpcPolledFdWindows { DEBUG_LOCATION); } - void OnIocpWriteableLocked(grpc_error* error) { + void OnIocpWriteableLocked(grpc_error_handle error) { GRPC_CARES_TRACE_LOG("OnIocpWriteableInner. fd:|%s|", GetName()); GPR_ASSERT(socket_type_ == SOCK_STREAM); if (error == GRPC_ERROR_NONE) { @@ -638,7 +640,7 @@ class GrpcPolledFdWindows { "fd:|%s| OnIocpWriteableInner. winsocket_->write_info.wsa_error " "code:|%d| msg:|%s|", GetName(), winsocket_->write_info.wsa_error, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } } GPR_ASSERT(tcp_write_state_ == WRITE_PENDING); @@ -849,7 +851,7 @@ class GrpcPolledFdWindowsWrapper : public GrpcPolledFd { return wrapped_->IsFdStillReadableLocked(); } - void ShutdownLocked(grpc_error* error) override { + void ShutdownLocked(grpc_error_handle error) override { wrapped_->ShutdownLocked(error); } diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index e45c58c92c1..82dbb00e7ab 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -38,14 +38,14 @@ #include #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/nameser.h" -#include "src/core/lib/iomgr/parse_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/transport/authority_override.h" @@ -77,7 +77,7 @@ struct grpc_ares_request { size_t pending_queries; /** the errors explaining query failures, appended to in query callbacks */ - grpc_error* error; + grpc_error_handle error; }; typedef struct fd_node { @@ -268,11 +268,13 @@ static grpc_millis calculate_next_ares_backup_poll_alarm_ms( grpc_core::ExecCtx::Get()->Now(); } -static void on_timeout_locked(grpc_ares_ev_driver* driver, grpc_error* error) { +static void on_timeout_locked(grpc_ares_ev_driver* driver, + grpc_error_handle error) { GRPC_CARES_TRACE_LOG( "request:%p ev_driver=%p on_timeout_locked. driver->shutting_down=%d. " "err=%s", - driver->request, driver, driver->shutting_down, grpc_error_string(error)); + driver->request, driver, driver->shutting_down, + grpc_error_std_string(error).c_str()); if (!driver->shutting_down && error == GRPC_ERROR_NONE) { grpc_ares_ev_driver_shutdown_locked(driver); } @@ -280,7 +282,7 @@ static void on_timeout_locked(grpc_ares_ev_driver* driver, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static void on_timeout(void* arg, grpc_error* error) { +static void on_timeout(void* arg, grpc_error_handle error) { grpc_ares_ev_driver* driver = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda driver->work_serializer->Run( @@ -290,9 +292,9 @@ static void on_timeout(void* arg, grpc_error* error) { static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver); static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver, - grpc_error* error); + grpc_error_handle error); -static void on_ares_backup_poll_alarm(void* arg, grpc_error* error) { +static void on_ares_backup_poll_alarm(void* arg, grpc_error_handle error) { grpc_ares_ev_driver* driver = static_cast(arg); GRPC_ERROR_REF(error); driver->work_serializer->Run( @@ -309,12 +311,13 @@ static void on_ares_backup_poll_alarm(void* arg, grpc_error* error) { * For the latter, we use this backup poller. Also see * https://github.com/grpc/grpc/pull/17688 description for more details. */ static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver, - grpc_error* error) { + grpc_error_handle error) { GRPC_CARES_TRACE_LOG( "request:%p ev_driver=%p on_ares_backup_poll_alarm_locked. " "driver->shutting_down=%d. " "err=%s", - driver->request, driver, driver->shutting_down, grpc_error_string(error)); + driver->request, driver, driver->shutting_down, + grpc_error_std_string(error).c_str()); if (!driver->shutting_down && error == GRPC_ERROR_NONE) { fd_node* fdn = driver->fds; while (fdn != nullptr) { @@ -329,6 +332,10 @@ static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver, fdn = fdn->next; } if (!driver->shutting_down) { + // InvalidateNow to avoid getting stuck re-initializing this timer + // in a loop while draining the currently-held WorkSerializer. + // Also see https://github.com/grpc/grpc/issues/26079. + grpc_core::ExecCtx::Get()->InvalidateNow(); grpc_millis next_ares_backup_poll_alarm = calculate_next_ares_backup_poll_alarm_ms(driver); grpc_ares_ev_driver_ref(driver); @@ -345,7 +352,7 @@ static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver, GRPC_ERROR_UNREF(error); } -static void on_readable_locked(fd_node* fdn, grpc_error* error) { +static void on_readable_locked(fd_node* fdn, grpc_error_handle error) { GPR_ASSERT(fdn->readable_registered); grpc_ares_ev_driver* ev_driver = fdn->ev_driver; const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); @@ -370,14 +377,14 @@ static void on_readable_locked(fd_node* fdn, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static void on_readable(void* arg, grpc_error* error) { +static void on_readable(void* arg, grpc_error_handle error) { fd_node* fdn = static_cast(arg); GRPC_ERROR_REF(error); /* ref owned by lambda */ fdn->ev_driver->work_serializer->Run( [fdn, error]() { on_readable_locked(fdn, error); }, DEBUG_LOCATION); } -static void on_writable_locked(fd_node* fdn, grpc_error* error) { +static void on_writable_locked(fd_node* fdn, grpc_error_handle error) { GPR_ASSERT(fdn->writable_registered); grpc_ares_ev_driver* ev_driver = fdn->ev_driver; const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); @@ -400,7 +407,7 @@ static void on_writable_locked(fd_node* fdn, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static void on_writable(void* arg, grpc_error* error) { +static void on_writable(void* arg, grpc_error_handle error) { fd_node* fdn = static_cast(arg); GRPC_ERROR_REF(error); /* ref owned by lambda */ fdn->ev_driver->work_serializer->Run( @@ -516,7 +523,7 @@ static void noop_inject_channel_config(ares_channel /*channel*/) {} void (*grpc_ares_test_only_inject_config)(ares_channel channel) = noop_inject_channel_config; -grpc_error* grpc_ares_ev_driver_create_locked( +grpc_error_handle grpc_ares_ev_driver_create_locked( grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set, int query_timeout_ms, std::shared_ptr work_serializer, @@ -529,7 +536,7 @@ grpc_error* grpc_ares_ev_driver_create_locked( grpc_ares_test_only_inject_config((*ev_driver)->channel); GRPC_CARES_TRACE_LOG("request:%p grpc_ares_ev_driver_create_locked", request); if (status != ARES_SUCCESS) { - grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("Failed to init ares channel. C-ares error: ", ares_strerror(status)) .c_str()); @@ -713,7 +720,8 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/, hr->qtype, hr->host, hr->is_balancer, ares_strerror(status)); GRPC_CARES_TRACE_LOG("request:%p on_hostbyname_done_locked: %s", r, error_msg.c_str()); - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg.c_str()); + grpc_error_handle error = + GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg.c_str()); r->error = grpc_error_add_child(error, r->error); } destroy_hostbyname_request_locked(hr); @@ -757,7 +765,8 @@ static void on_srv_query_done_locked(void* arg, int status, int /*timeouts*/, ares_strerror(status)); GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked: %s", r, error_msg.c_str()); - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg.c_str()); + grpc_error_handle error = + GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg.c_str()); r->error = grpc_error_add_child(error, r->error); } delete q; @@ -773,7 +782,7 @@ static void on_txt_done_locked(void* arg, int status, int /*timeouts*/, const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1; struct ares_txt_ext* result = nullptr; struct ares_txt_ext* reply = nullptr; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (status != ARES_SUCCESS) goto fail; GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked name=%s ARES_SUCCESS", r, q->name().c_str()); @@ -825,7 +834,7 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( const char* default_port, grpc_pollset_set* interested_parties, int query_timeout_ms, std::shared_ptr work_serializer) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_ares_hostbyname_request* hr = nullptr; /* parse name, splitting it into host and port parts */ std::string host; @@ -971,11 +980,7 @@ static bool target_matches_localhost_inner(const char* name, std::string* host, gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name); return false; } - if (gpr_stricmp(host->c_str(), "localhost") == 0) { - return true; - } else { - return false; - } + return gpr_stricmp(host->c_str(), "localhost") == 0; } static bool target_matches_localhost(const char* name) { @@ -1120,7 +1125,7 @@ void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) = // Windows. Calling them may cause race conditions when other parts of the // binary calls these functions concurrently. #ifdef GPR_WINDOWS -grpc_error* grpc_ares_init(void) { +grpc_error_handle grpc_ares_init(void) { int status = ares_library_init(ARES_LIB_INIT_ALL); if (status != ARES_SUCCESS) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -1132,7 +1137,7 @@ grpc_error* grpc_ares_init(void) { void grpc_ares_cleanup(void) { ares_library_cleanup(); } #else -grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; } +grpc_error_handle grpc_ares_init(void) { return GRPC_ERROR_NONE; } void grpc_ares_cleanup(void) {} #endif // GPR_WINDOWS @@ -1163,7 +1168,7 @@ typedef struct grpc_resolve_address_ares_request { } grpc_resolve_address_ares_request; static void on_dns_lookup_done_locked(grpc_resolve_address_ares_request* r, - grpc_error* error) { + grpc_error_handle error) { gpr_free(r->ares_request); grpc_resolved_addresses** resolved_addresses = r->addrs_out; if (r->addresses == nullptr || r->addresses->empty()) { @@ -1184,7 +1189,7 @@ static void on_dns_lookup_done_locked(grpc_resolve_address_ares_request* r, delete r; } -static void on_dns_lookup_done(void* arg, grpc_error* error) { +static void on_dns_lookup_done(void* arg, grpc_error_handle error) { grpc_resolve_address_ares_request* r = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index 6c29bb68a47..675dfc8e961 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -76,7 +76,7 @@ extern void (*grpc_cancel_ares_request_locked)(grpc_ares_request* request); /* Initialize gRPC ares wrapper. Must be called at least once before grpc_resolve_address_ares(). */ -grpc_error* grpc_ares_init(void); +grpc_error_handle grpc_ares_init(void); /* Uninitialized gRPC ares wrapper. If there was more than one previous call to grpc_ares_init(), this function uninitializes the gRPC ares wrapper only if diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc index 1d4a90fbd90..8735aa8e35c 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_libuv.cc @@ -25,8 +25,8 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/iomgr/parse_address.h" bool grpc_ares_query_ipv6() { /* The libuv grpc code currently does not have the code to probe for this, diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc index df11db3624d..f76c6a4a12b 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc @@ -25,8 +25,8 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/socket_windows.h" bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc index e5ebd11ca2d..3265e29cb45 100644 --- a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc @@ -68,10 +68,10 @@ class NativeDnsResolver : public Resolver { void MaybeStartResolvingLocked(); void StartResolvingLocked(); - static void OnNextResolution(void* arg, grpc_error* error); - void OnNextResolutionLocked(grpc_error* error); - static void OnResolved(void* arg, grpc_error* error); - void OnResolvedLocked(grpc_error* error); + static void OnNextResolution(void* arg, grpc_error_handle error); + void OnNextResolutionLocked(grpc_error_handle error); + static void OnResolved(void* arg, grpc_error_handle error); + void OnResolvedLocked(grpc_error_handle error); /// name to resolve std::string name_to_resolve_; @@ -148,14 +148,14 @@ void NativeDnsResolver::ShutdownLocked() { } } -void NativeDnsResolver::OnNextResolution(void* arg, grpc_error* error) { +void NativeDnsResolver::OnNextResolution(void* arg, grpc_error_handle error) { NativeDnsResolver* r = static_cast(arg); GRPC_ERROR_REF(error); // ref owned by lambda r->work_serializer_->Run([r, error]() { r->OnNextResolutionLocked(error); }, DEBUG_LOCATION); } -void NativeDnsResolver::OnNextResolutionLocked(grpc_error* error) { +void NativeDnsResolver::OnNextResolutionLocked(grpc_error_handle error) { have_next_resolution_timer_ = false; if (error == GRPC_ERROR_NONE && !resolving_) { StartResolvingLocked(); @@ -164,14 +164,14 @@ void NativeDnsResolver::OnNextResolutionLocked(grpc_error* error) { GRPC_ERROR_UNREF(error); } -void NativeDnsResolver::OnResolved(void* arg, grpc_error* error) { +void NativeDnsResolver::OnResolved(void* arg, grpc_error_handle error) { NativeDnsResolver* r = static_cast(arg); GRPC_ERROR_REF(error); // owned by lambda r->work_serializer_->Run([r, error]() { r->OnResolvedLocked(error); }, DEBUG_LOCATION); } -void NativeDnsResolver::OnResolvedLocked(grpc_error* error) { +void NativeDnsResolver::OnResolvedLocked(grpc_error_handle error) { GPR_ASSERT(resolving_); resolving_ = false; if (shutdown_) { @@ -194,7 +194,7 @@ void NativeDnsResolver::OnResolvedLocked(grpc_error* error) { backoff_.Reset(); } else { gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); // Return transient error. std::string error_message = absl::StrCat("DNS resolution failed for service: ", name_to_resolve_); @@ -203,6 +203,10 @@ void NativeDnsResolver::OnResolvedLocked(grpc_error* error) { &error, 1), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); // Set up for retry. + // InvalidateNow to avoid getting stuck re-initializing this timer + // in a loop while draining the currently-held WorkSerializer. + // Also see https://github.com/grpc/grpc/issues/26079. + ExecCtx::Get()->InvalidateNow(); grpc_millis next_try = backoff_.NextAttemptTime(); grpc_millis timeout = next_try - ExecCtx::Get()->Now(); GPR_ASSERT(!have_next_resolution_timer_); @@ -229,6 +233,10 @@ void NativeDnsResolver::MaybeStartResolvingLocked() { // can start the next resolution. if (have_next_resolution_timer_) return; if (last_resolution_timestamp_ >= 0) { + // InvalidateNow to avoid getting stuck re-initializing this timer + // in a loop while draining the currently-held WorkSerializer. + // Also see https://github.com/grpc/grpc/issues/26079. + ExecCtx::Get()->InvalidateNow(); const grpc_millis earliest_next_resolution = last_resolution_timestamp_ + min_time_between_resolutions_; const grpc_millis ms_until_next_resolution = diff --git a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc index 56c16824a19..7978d59e8b6 100644 --- a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc @@ -30,11 +30,11 @@ #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/iomgr/closure.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/iomgr/work_serializer.h" @@ -313,48 +313,40 @@ void FakeResolverResponseGenerator::SetFakeResolver( namespace { -static void* response_generator_arg_copy(void* p) { - FakeResolverResponseGenerator* generator = - static_cast(p); - // TODO(roth): We currently deal with this ref manually. Once the - // new channel args code is converted to C++, find a way to track this ref - // in a cleaner way. - RefCountedPtr copy = generator->Ref(); - copy.release(); +void* ResponseGeneratorChannelArgCopy(void* p) { + auto* generator = static_cast(p); + generator->Ref().release(); return p; } -static void response_generator_arg_destroy(void* p) { - FakeResolverResponseGenerator* generator = - static_cast(p); +void ResponseGeneratorChannelArgDestroy(void* p) { + auto* generator = static_cast(p); generator->Unref(); } -static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); } - -static const grpc_arg_pointer_vtable response_generator_arg_vtable = { - response_generator_arg_copy, response_generator_arg_destroy, - response_generator_cmp}; +int ResponseGeneratorChannelArgCmp(void* a, void* b) { return GPR_ICMP(a, b); } } // namespace +const grpc_arg_pointer_vtable + FakeResolverResponseGenerator::kChannelArgPointerVtable = { + ResponseGeneratorChannelArgCopy, ResponseGeneratorChannelArgDestroy, + ResponseGeneratorChannelArgCmp}; + grpc_arg FakeResolverResponseGenerator::MakeChannelArg( FakeResolverResponseGenerator* generator) { - grpc_arg arg; - arg.type = GRPC_ARG_POINTER; - arg.key = const_cast(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR); - arg.value.pointer.p = generator; - arg.value.pointer.vtable = &response_generator_arg_vtable; - return arg; + return grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR), generator, + &kChannelArgPointerVtable); } RefCountedPtr FakeResolverResponseGenerator::GetFromArgs(const grpc_channel_args* args) { - const grpc_arg* arg = - grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR); - if (arg == nullptr || arg->type != GRPC_ARG_POINTER) return nullptr; - return static_cast(arg->value.pointer.p) - ->Ref(); + auto* response_generator = + grpc_channel_args_find_pointer( + args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR); + if (response_generator == nullptr) return nullptr; + return response_generator->Ref(); } // diff --git a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h index b9ca69df1e0..94d7c22c52c 100644 --- a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +++ b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h @@ -42,6 +42,8 @@ class FakeResolver; class FakeResolverResponseGenerator : public RefCounted { public: + static const grpc_arg_pointer_vtable kChannelArgPointerVtable; + FakeResolverResponseGenerator(); ~FakeResolverResponseGenerator() override; @@ -69,6 +71,7 @@ class FakeResolverResponseGenerator void SetFailureOnReresolution(); // Returns a channel arg containing \a generator. + // TODO(roth): When we have time, make this a non-static method. static grpc_arg MakeChannelArg(FakeResolverResponseGenerator* generator); // Returns the response generator in \a args, or null if not found. @@ -82,12 +85,11 @@ class FakeResolverResponseGenerator // Mutex protecting the members below. Mutex mu_; - RefCountedPtr resolver_; - Resolver::Result result_; - bool has_result_ = false; + RefCountedPtr resolver_ ABSL_GUARDED_BY(mu_); + Resolver::Result result_ ABSL_GUARDED_BY(mu_); + bool has_result_ ABSL_GUARDED_BY(mu_) = false; }; } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FAKE_FAKE_RESOLVER_H \ - */ +#endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FAKE_FAKE_RESOLVER_H diff --git a/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc b/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc index 3488ebc5922..208ec67015e 100644 --- a/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc @@ -48,15 +48,15 @@ class GoogleCloud2ProdResolver : public Resolver { void Orphan() override; private: - static void OnHttpRequestDone(void* arg, grpc_error* error); + static void OnHttpRequestDone(void* arg, grpc_error_handle error); // Calls OnDone() if not already called. Releases a ref. - void MaybeCallOnDone(grpc_error* error); + void MaybeCallOnDone(grpc_error_handle error); // If error is not GRPC_ERROR_NONE, then it's not safe to look at response. virtual void OnDone(GoogleCloud2ProdResolver* resolver, const grpc_http_response* response, - grpc_error* error) = 0; + grpc_error_handle error) = 0; RefCountedPtr resolver_; grpc_httpcli_context context_; @@ -73,7 +73,8 @@ class GoogleCloud2ProdResolver : public Resolver { private: void OnDone(GoogleCloud2ProdResolver* resolver, - const grpc_http_response* response, grpc_error* error) override; + const grpc_http_response* response, + grpc_error_handle error) override; }; // A metadata server query to get the IPv6 address. @@ -84,7 +85,8 @@ class GoogleCloud2ProdResolver : public Resolver { private: void OnDone(GoogleCloud2ProdResolver* resolver, - const grpc_http_response* response, grpc_error* error) override; + const grpc_http_response* response, + grpc_error_handle error) override; }; void ZoneQueryDone(std::string zone); @@ -143,13 +145,13 @@ void GoogleCloud2ProdResolver::MetadataQuery::Orphan() { } void GoogleCloud2ProdResolver::MetadataQuery::OnHttpRequestDone( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { auto* self = static_cast(arg); self->MaybeCallOnDone(GRPC_ERROR_REF(error)); } void GoogleCloud2ProdResolver::MetadataQuery::MaybeCallOnDone( - grpc_error* error) { + grpc_error_handle error) { bool expected = false; if (!on_done_called_.CompareExchangeStrong( &expected, true, MemoryOrder::RELAXED, MemoryOrder::RELAXED)) { @@ -180,10 +182,10 @@ GoogleCloud2ProdResolver::ZoneQuery::ZoneQuery( void GoogleCloud2ProdResolver::ZoneQuery::OnDone( GoogleCloud2ProdResolver* resolver, const grpc_http_response* response, - grpc_error* error) { + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "error fetching zone from metadata server: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } std::string zone; if (error == GRPC_ERROR_NONE && response->status == 200) { @@ -213,10 +215,10 @@ GoogleCloud2ProdResolver::IPv6Query::IPv6Query( void GoogleCloud2ProdResolver::IPv6Query::OnDone( GoogleCloud2ProdResolver* resolver, const grpc_http_response* response, - grpc_error* error) { + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "error fetching IPv6 address from metadata server: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } resolver->IPv6QueryDone(error == GRPC_ERROR_NONE && response->status == 200); GRPC_ERROR_UNREF(error); diff --git a/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc b/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc index f50bb7e0b16..46efbb06b21 100644 --- a/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc @@ -30,9 +30,9 @@ #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/slice/slice_internal.h" diff --git a/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc b/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc index db579d0e22a..3231ca27e63 100644 --- a/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +++ b/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc @@ -22,9 +22,13 @@ #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" #include "re2/re2.h" +#define XXH_INLINE_ALL +#include "xxhash.h" #include "src/core/ext/filters/client_channel/config_selector.h" +#include "src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/ext/xds/xds_channel_args.h" #include "src/core/ext/xds/xds_client.h" #include "src/core/ext/xds/xds_http_filters.h" #include "src/core/lib/channel/channel_args.h" @@ -70,19 +74,23 @@ class XdsResolver : public Resolver { void ShutdownLocked() override; + void ResetBackoffLocked() override { + if (xds_client_ != nullptr) xds_client_->ResetBackoff(); + } + private: class Notifier { public: Notifier(RefCountedPtr resolver, XdsApi::LdsUpdate update); Notifier(RefCountedPtr resolver, XdsApi::RdsUpdate update); - Notifier(RefCountedPtr resolver, grpc_error* error); + Notifier(RefCountedPtr resolver, grpc_error_handle error); explicit Notifier(RefCountedPtr resolver); private: enum Type { kLdsUpdate, kRdsUpdate, kError, kDoesNotExist }; - static void RunInExecCtx(void* arg, grpc_error* error); - void RunInWorkSerializer(grpc_error* error); + static void RunInExecCtx(void* arg, grpc_error_handle error); + void RunInWorkSerializer(grpc_error_handle error); RefCountedPtr resolver_; grpc_closure closure_; @@ -97,7 +105,9 @@ class XdsResolver : public Resolver { void OnListenerChanged(XdsApi::LdsUpdate listener) override { new Notifier(resolver_, std::move(listener)); } - void OnError(grpc_error* error) override { new Notifier(resolver_, error); } + void OnError(grpc_error_handle error) override { + new Notifier(resolver_, error); + } void OnResourceDoesNotExist() override { new Notifier(resolver_); } private: @@ -111,7 +121,9 @@ class XdsResolver : public Resolver { void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override { new Notifier(resolver_, std::move(route_config)); } - void OnError(grpc_error* error) override { new Notifier(resolver_, error); } + void OnError(grpc_error_handle error) override { + new Notifier(resolver_, error); + } void OnResourceDoesNotExist() override { new Notifier(resolver_); } private: @@ -119,7 +131,7 @@ class XdsResolver : public Resolver { }; class ClusterState - : public RefCounted { + : public RefCounted { public: using ClusterStateMap = std::map>; @@ -137,7 +149,8 @@ class XdsResolver : public Resolver { class XdsConfigSelector : public ConfigSelector { public: - XdsConfigSelector(RefCountedPtr resolver, grpc_error** error); + XdsConfigSelector(RefCountedPtr resolver, + grpc_error_handle* error); ~XdsConfigSelector() override; const char* name() const override { return "XdsConfigSelector"; } @@ -176,7 +189,7 @@ class XdsResolver : public Resolver { using RouteTable = std::vector; void MaybeAddCluster(const std::string& name); - grpc_error* CreateMethodConfig( + grpc_error_handle CreateMethodConfig( const XdsApi::Route& route, const XdsApi::Route::ClusterWeight* cluster_weight, RefCountedPtr* method_config); @@ -185,15 +198,16 @@ class XdsResolver : public Resolver { RouteTable route_table_; std::map> clusters_; std::vector filters_; - grpc_error* filter_error_ = GRPC_ERROR_NONE; + grpc_error_handle filter_error_ = GRPC_ERROR_NONE; }; void OnListenerUpdate(XdsApi::LdsUpdate listener); void OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update); - void OnError(grpc_error* error); + void OnError(grpc_error_handle error); void OnResourceDoesNotExist(); - grpc_error* CreateServiceConfig(RefCountedPtr* service_config); + grpc_error_handle CreateServiceConfig( + RefCountedPtr* service_config); void GenerateResult(); void MaybeRemoveUnusedClusters(); @@ -234,13 +248,13 @@ XdsResolver::Notifier::Notifier(RefCountedPtr resolver, XdsResolver::Notifier::Notifier(RefCountedPtr resolver, XdsApi::RdsUpdate update) : resolver_(std::move(resolver)), type_(kRdsUpdate) { - update_.rds_update = std::move(update); + update_.http_connection_manager.rds_update = std::move(update); GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr); ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE); } XdsResolver::Notifier::Notifier(RefCountedPtr resolver, - grpc_error* error) + grpc_error_handle error) : resolver_(std::move(resolver)), type_(kError) { GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr); ExecCtx::Run(DEBUG_LOCATION, &closure_, error); @@ -252,14 +266,14 @@ XdsResolver::Notifier::Notifier(RefCountedPtr resolver) ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE); } -void XdsResolver::Notifier::RunInExecCtx(void* arg, grpc_error* error) { +void XdsResolver::Notifier::RunInExecCtx(void* arg, grpc_error_handle error) { Notifier* self = static_cast(arg); GRPC_ERROR_REF(error); self->resolver_->work_serializer_->Run( [self, error]() { self->RunInWorkSerializer(error); }, DEBUG_LOCATION); } -void XdsResolver::Notifier::RunInWorkSerializer(grpc_error* error) { +void XdsResolver::Notifier::RunInWorkSerializer(grpc_error_handle error) { if (resolver_->xds_client_ == nullptr) { GRPC_ERROR_UNREF(error); delete this; @@ -270,7 +284,8 @@ void XdsResolver::Notifier::RunInWorkSerializer(grpc_error* error) { resolver_->OnListenerUpdate(std::move(update_)); break; case kRdsUpdate: - resolver_->OnRouteConfigUpdate(std::move(*update_.rds_update)); + resolver_->OnRouteConfigUpdate( + std::move(*update_.http_connection_manager.rds_update)); break; case kError: resolver_->OnError(error); @@ -310,7 +325,7 @@ bool XdsResolver::XdsConfigSelector::Route::operator==( // XdsResolver::XdsConfigSelector::XdsConfigSelector( - RefCountedPtr resolver, grpc_error** error) + RefCountedPtr resolver, grpc_error_handle* error) : resolver_(std::move(resolver)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) { gpr_log(GPR_INFO, "[xds_resolver %p] creating XdsConfigSelector %p", @@ -338,7 +353,8 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector( // one. if (!route.max_stream_duration.has_value()) { route_entry.route.max_stream_duration = - resolver_->current_listener_.http_max_stream_duration; + resolver_->current_listener_.http_connection_manager + .http_max_stream_duration; } if (route.weighted_clusters.empty()) { *error = CreateMethodConfig(route_entry.route, nullptr, @@ -361,34 +377,33 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector( } } // Populate filter list. - if (XdsFaultInjectionEnabled()) { - bool found_router = false; - for (const auto& http_filter : resolver_->current_listener_.http_filters) { - // Stop at the router filter. It's a no-op for us, and we ignore - // anything that may come after it, for compatibility with Envoy. - if (http_filter.config.config_proto_type_name == - kXdsHttpRouterFilterConfigName) { - found_router = true; - break; - } - // Find filter. This is guaranteed to succeed, because it's checked - // at config validation time in the XdsApi code. - const XdsHttpFilterImpl* filter_impl = - XdsHttpFilterRegistry::GetFilterForType( - http_filter.config.config_proto_type_name); - GPR_ASSERT(filter_impl != nullptr); - // Add C-core filter to list. - filters_.push_back(filter_impl->channel_filter()); - } - // For compatibility with Envoy, if the router filter is not - // configured, we fail all RPCs. - if (!found_router) { - filter_error_ = grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "no xDS HTTP router filter configured"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); - filters_.push_back(&grpc_lame_filter); + bool found_router = false; + for (const auto& http_filter : + resolver_->current_listener_.http_connection_manager.http_filters) { + // Stop at the router filter. It's a no-op for us, and we ignore + // anything that may come after it, for compatibility with Envoy. + if (http_filter.config.config_proto_type_name == + kXdsHttpRouterFilterConfigName) { + found_router = true; + break; } + // Find filter. This is guaranteed to succeed, because it's checked + // at config validation time in the XdsApi code. + const XdsHttpFilterImpl* filter_impl = + XdsHttpFilterRegistry::GetFilterForType( + http_filter.config.config_proto_type_name); + GPR_ASSERT(filter_impl != nullptr); + // Add C-core filter to list. + filters_.push_back(filter_impl->channel_filter()); + } + // For compatibility with Envoy, if the router filter is not + // configured, we fail all RPCs. + if (!found_router) { + filter_error_ = + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "no xDS HTTP router filter configured"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + filters_.push_back(&grpc_lame_filter); } } @@ -421,7 +436,7 @@ const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride( return nullptr; } -grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig( +grpc_error_handle XdsResolver::XdsConfigSelector::CreateMethodConfig( const XdsApi::Route& route, const XdsApi::Route::ClusterWeight* cluster_weight, RefCountedPtr* method_config) { @@ -437,7 +452,8 @@ grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig( // Handle xDS HTTP filters. std::map> per_filter_configs; grpc_channel_args* args = grpc_channel_args_copy(resolver_->args_); - for (const auto& http_filter : resolver_->current_listener_.http_filters) { + for (const auto& http_filter : + resolver_->current_listener_.http_connection_manager.http_filters) { // Stop at the router filter. It's a no-op for us, and we ignore // anything that may come after it, for compatibility with Envoy. if (http_filter.config.config_proto_type_name == @@ -477,7 +493,7 @@ grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig( "\n ]")); } // Construct service config. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (!fields.empty()) { std::string json = absl::StrCat( "{\n" @@ -518,33 +534,52 @@ void XdsResolver::XdsConfigSelector::MaybeAddCluster(const std::string& name) { } } -bool HeaderMatchHelper(const HeaderMatcher& header_matcher, - grpc_metadata_batch* initial_metadata) { - std::string concatenated_value; - absl::optional value; +absl::optional GetHeaderValue( + grpc_metadata_batch* initial_metadata, absl::string_view header_name, + std::string* concatenated_value) { // Note: If we ever allow binary headers here, we still need to // special-case ignore "grpc-tags-bin" and "grpc-trace-bin", since // they are not visible to the LB policy in grpc-go. - if (absl::EndsWith(header_matcher.name(), "-bin") || - header_matcher.name() == "grpc-previous-rpc-attempts") { - value = absl::nullopt; - } else if (header_matcher.name() == "content-type") { - value = "application/grpc"; - } else { - value = grpc_metadata_batch_get_value( - initial_metadata, header_matcher.name(), &concatenated_value); + if (absl::EndsWith(header_name, "-bin")) { + return absl::nullopt; + } else if (header_name == "content-type") { + return "application/grpc"; } - return header_matcher.Match(value); + return grpc_metadata_batch_get_value(initial_metadata, header_name, + concatenated_value); } bool HeadersMatch(const std::vector& header_matchers, grpc_metadata_batch* initial_metadata) { for (const auto& header_matcher : header_matchers) { - if (!HeaderMatchHelper(header_matcher, initial_metadata)) return false; + std::string concatenated_value; + if (!header_matcher.Match(GetHeaderValue( + initial_metadata, header_matcher.name(), &concatenated_value))) { + return false; + } } return true; } +absl::optional HeaderHashHelper( + const XdsApi::Route::HashPolicy& policy, + grpc_metadata_batch* initial_metadata) { + GPR_ASSERT(policy.type == XdsApi::Route::HashPolicy::HEADER); + std::string value_buffer; + absl::optional header_value = + GetHeaderValue(initial_metadata, policy.header_name, &value_buffer); + if (policy.regex != nullptr) { + // If GetHeaderValue() did not already store the value in + // value_buffer, copy it there now, so we can modify it. + if (header_value->data() != value_buffer.data()) { + value_buffer = std::string(*header_value); + } + RE2::GlobalReplace(&value_buffer, *policy.regex, policy.regex_substitution); + header_value = value_buffer; + } + return XXH64(header_value->data(), header_value->size(), 0); +} + bool UnderFraction(const uint32_t fraction_per_million) { // Generate a random number in [0, 1000000). const uint32_t random_number = rand() % 1000000; @@ -606,6 +641,38 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( XdsResolver* resolver = static_cast(resolver_->Ref().release()); ClusterState* cluster_state = it->second->Ref().release(); + // Generate a hash + absl::optional hash; + for (const auto& hash_policy : entry.route.hash_policies) { + absl::optional new_hash; + switch (hash_policy.type) { + case XdsApi::Route::HashPolicy::HEADER: + new_hash = HeaderHashHelper(hash_policy, args.initial_metadata); + break; + case XdsApi::Route::HashPolicy::CHANNEL_ID: + new_hash = + static_cast(reinterpret_cast(resolver)); + break; + default: + GPR_ASSERT(0); + } + if (new_hash.has_value()) { + // Rotating the old value prevents duplicate hash rules from cancelling + // each other out and preserves all of the entropy + const uint64_t old_value = + hash.has_value() ? ((hash.value() << 1) | (hash.value() >> 63)) : 0; + hash = old_value ^ new_hash.value(); + } + // If the policy is a terminal policy and a hash has been generated, + // ignore the rest of the hash policies. + if (hash_policy.terminal && hash.has_value()) { + break; + } + } + if (!hash.has_value()) { + // If there is no hash, we just choose a random value as a default. + hash = rand(); + } CallConfig call_config; if (method_config != nullptr) { call_config.method_configs = @@ -613,6 +680,8 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( call_config.service_config = std::move(method_config); } call_config.call_attributes[kXdsClusterAttribute] = it->first; + call_config.call_attributes[kRequestRingHashAttribute] = + absl::StrFormat("%" PRIu64, hash.value()); call_config.on_call_committed = [resolver, cluster_state]() { cluster_state->Unref(); ExecCtx::Run( @@ -626,7 +695,7 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( // the data plane mutex. DEBUG_LOCATION, GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error* /*error*/) { + [](void* arg, grpc_error_handle /*error*/) { auto* resolver = static_cast(arg); resolver->work_serializer_->Run( [resolver]() { @@ -648,13 +717,13 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( // void XdsResolver::StartLocked() { - grpc_error* error = GRPC_ERROR_NONE; - xds_client_ = XdsClient::GetOrCreate(&error); + grpc_error_handle error = GRPC_ERROR_NONE; + xds_client_ = XdsClient::GetOrCreate(args_, &error); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to create xds client -- channel will remain in " "TRANSIENT_FAILURE: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); result_handler_->ReturnError(error); return; } @@ -700,14 +769,17 @@ void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) { gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data", this); } - if (listener.route_config_name != route_config_name_) { + if (listener.http_connection_manager.route_config_name != + route_config_name_) { if (route_config_watcher_ != nullptr) { xds_client_->CancelRouteConfigDataWatch( route_config_name_, route_config_watcher_, - /*delay_unsubscription=*/!listener.route_config_name.empty()); + /*delay_unsubscription=*/ + !listener.http_connection_manager.route_config_name.empty()); route_config_watcher_ = nullptr; } - route_config_name_ = std::move(listener.route_config_name); + route_config_name_ = + std::move(listener.http_connection_manager.route_config_name); if (!route_config_name_.empty()) { current_virtual_host_.routes.clear(); auto watcher = absl::make_unique(Ref()); @@ -717,8 +789,10 @@ void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) { } current_listener_ = std::move(listener); if (route_config_name_.empty()) { - GPR_ASSERT(current_listener_.rds_update.has_value()); - OnRouteConfigUpdate(std::move(*current_listener_.rds_update)); + GPR_ASSERT( + current_listener_.http_connection_manager.rds_update.has_value()); + OnRouteConfigUpdate( + std::move(*current_listener_.http_connection_manager.rds_update)); } else { // HCM may contain newer filter config. We need to propagate the update as // config selector to the channel @@ -746,9 +820,9 @@ void XdsResolver::OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update) { GenerateResult(); } -void XdsResolver::OnError(grpc_error* error) { +void XdsResolver::OnError(grpc_error_handle error) { gpr_log(GPR_ERROR, "[xds_resolver %p] received error from XdsClient: %s", - this, grpc_error_string(error)); + this, grpc_error_std_string(error).c_str()); Result result; result.args = grpc_channel_args_copy(args_); result.service_config_error = error; @@ -769,7 +843,7 @@ void XdsResolver::OnResourceDoesNotExist() { result_handler_->ReturnResult(std::move(result)); } -grpc_error* XdsResolver::CreateServiceConfig( +grpc_error_handle XdsResolver::CreateServiceConfig( RefCountedPtr* service_config) { std::vector clusters; for (const auto& cluster : cluster_state_map_) { @@ -796,7 +870,7 @@ grpc_error* XdsResolver::CreateServiceConfig( " ]\n" "}"); std::string json = absl::StrJoin(config_parts, ""); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; *service_config = ServiceConfig::Create(args_, json.c_str(), &error); return error; } @@ -805,7 +879,7 @@ void XdsResolver::GenerateResult() { if (current_virtual_host_.routes.empty()) return; // First create XdsConfigSelector, which may add new entries to the cluster // state map, and then CreateServiceConfig for LB policies. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto config_selector = MakeRefCounted(Ref(), &error); if (error != GRPC_ERROR_NONE) { OnError(error); @@ -821,8 +895,12 @@ void XdsResolver::GenerateResult() { gpr_log(GPR_INFO, "[xds_resolver %p] generated service config: %s", this, result.service_config->json_string().c_str()); } - grpc_arg new_arg = config_selector->MakeChannelArg(); - result.args = grpc_channel_args_copy_and_add(args_, &new_arg, 1); + grpc_arg new_args[] = { + xds_client_->MakeChannelArg(), + config_selector->MakeChannelArg(), + }; + result.args = + grpc_channel_args_copy_and_add(args_, new_args, GPR_ARRAY_SIZE(new_args)); result_handler_->ReturnResult(std::move(result)); } diff --git a/src/core/ext/filters/client_channel/resolver_result_parsing.cc b/src/core/ext/filters/client_channel/resolver_result_parsing.cc index 500c7408a15..b0c8eebe59b 100644 --- a/src/core/ext/filters/client_channel/resolver_result_parsing.cc +++ b/src/core/ext/filters/client_channel/resolver_result_parsing.cc @@ -1,20 +1,18 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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. - * - */ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// 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 @@ -63,200 +61,15 @@ void ClientChannelServiceConfigParser::Register() { namespace { -std::unique_ptr ParseRetryPolicy( - const Json& json, grpc_error** error) { - GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); - auto retry_policy = - absl::make_unique(); - if (json.type() != Json::Type::OBJECT) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryPolicy error:should be of type object"); - return nullptr; - } - std::vector error_list; - // Parse maxAttempts. - auto it = json.object_value().find("maxAttempts"); - if (it != json.object_value().end()) { - if (it->second.type() != Json::Type::NUMBER) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:maxAttempts error:should be of type number")); - } else { - retry_policy->max_attempts = - gpr_parse_nonnegative_int(it->second.string_value().c_str()); - if (retry_policy->max_attempts <= 1) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:maxAttempts error:should be at least 2")); - } else if (retry_policy->max_attempts > MAX_MAX_RETRY_ATTEMPTS) { - gpr_log(GPR_ERROR, - "service config: clamped retryPolicy.maxAttempts at %d", - MAX_MAX_RETRY_ATTEMPTS); - retry_policy->max_attempts = MAX_MAX_RETRY_ATTEMPTS; - } - } - } - // Parse initialBackoff. - if (ParseJsonObjectFieldAsDuration(json.object_value(), "initialBackoff", - &retry_policy->initial_backoff, - &error_list) && - retry_policy->initial_backoff == 0) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:initialBackoff error:must be greater than 0")); - } - // Parse maxBackoff. - if (ParseJsonObjectFieldAsDuration(json.object_value(), "maxBackoff", - &retry_policy->max_backoff, &error_list) && - retry_policy->max_backoff == 0) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:maxBackoff error:should be greater than 0")); - } - // Parse backoffMultiplier. - it = json.object_value().find("backoffMultiplier"); - if (it != json.object_value().end()) { - if (it->second.type() != Json::Type::NUMBER) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:backoffMultiplier error:should be of type number")); - } else { - if (sscanf(it->second.string_value().c_str(), "%f", - &retry_policy->backoff_multiplier) != 1) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:backoffMultiplier error:failed to parse")); - } else if (retry_policy->backoff_multiplier <= 0) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:backoffMultiplier error:should be greater than 0")); - } - } - } - // Parse retryableStatusCodes. - it = json.object_value().find("retryableStatusCodes"); - if (it != json.object_value().end()) { - if (it->second.type() != Json::Type::ARRAY) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryableStatusCodes error:should be of type array")); - } else { - for (const Json& element : it->second.array_value()) { - if (element.type() != Json::Type::STRING) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryableStatusCodes error:status codes should be of type " - "string")); - continue; - } - grpc_status_code status; - if (!grpc_status_code_from_string(element.string_value().c_str(), - &status)) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryableStatusCodes error:failed to parse status code")); - continue; - } - retry_policy->retryable_status_codes.Add(status); - } - if (retry_policy->retryable_status_codes.Empty()) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryableStatusCodes error:should be non-empty")); - }; - } - } - // Make sure required fields are set. - if (error_list.empty()) { - if (retry_policy->max_attempts == 0 || retry_policy->initial_backoff == 0 || - retry_policy->max_backoff == 0 || - retry_policy->backoff_multiplier == 0 || - retry_policy->retryable_status_codes.Empty()) { - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryPolicy error:Missing required field(s)"); - return nullptr; - } - } - *error = GRPC_ERROR_CREATE_FROM_VECTOR("retryPolicy", &error_list); - return *error == GRPC_ERROR_NONE ? std::move(retry_policy) : nullptr; -} - -grpc_error* ParseRetryThrottling( - const Json& json, - ClientChannelGlobalParsedConfig::RetryThrottling* retry_throttling) { - if (json.type() != Json::Type::OBJECT) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling error:Type should be object"); - } - std::vector error_list; - // Parse maxTokens. - auto it = json.object_value().find("maxTokens"); - if (it == json.object_value().end()) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:maxTokens error:Not found")); - } else if (it->second.type() != Json::Type::NUMBER) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:maxTokens error:Type should be " - "number")); - } else { - retry_throttling->max_milli_tokens = - gpr_parse_nonnegative_int(it->second.string_value().c_str()) * 1000; - if (retry_throttling->max_milli_tokens <= 0) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:maxTokens error:should be " - "greater than zero")); - } - } - // Parse tokenRatio. - it = json.object_value().find("tokenRatio"); - if (it == json.object_value().end()) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:tokenRatio error:Not found")); - } else if (it->second.type() != Json::Type::NUMBER) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:tokenRatio error:type should be " - "number")); - } else { - // We support up to 3 decimal digits. - size_t whole_len = it->second.string_value().size(); - const char* value = it->second.string_value().c_str(); - uint32_t multiplier = 1; - uint32_t decimal_value = 0; - const char* decimal_point = strchr(value, '.'); - if (decimal_point != nullptr) { - whole_len = static_cast(decimal_point - value); - multiplier = 1000; - size_t decimal_len = strlen(decimal_point + 1); - if (decimal_len > 3) decimal_len = 3; - if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len, - &decimal_value)) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:tokenRatio error:Failed " - "parsing")); - return GRPC_ERROR_CREATE_FROM_VECTOR("retryPolicy", &error_list); - } - uint32_t decimal_multiplier = 1; - for (size_t i = 0; i < (3 - decimal_len); ++i) { - decimal_multiplier *= 10; - } - decimal_value *= decimal_multiplier; - } - uint32_t whole_value; - if (!gpr_parse_bytes_to_uint32(value, whole_len, &whole_value)) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:tokenRatio error:Failed " - "parsing")); - return GRPC_ERROR_CREATE_FROM_VECTOR("retryPolicy", &error_list); - } - retry_throttling->milli_token_ratio = - static_cast((whole_value * multiplier) + decimal_value); - if (retry_throttling->milli_token_ratio <= 0) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "field:retryThrottling field:tokenRatio error:value should " - "be greater than 0")); - } - } - return GRPC_ERROR_CREATE_FROM_VECTOR("retryPolicy", &error_list); -} - absl::optional ParseHealthCheckConfig(const Json& field, - grpc_error** error) { + grpc_error_handle* error) { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); if (field.type() != Json::Type::OBJECT) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "field:healthCheckConfig error:should be of type object"); return absl::nullopt; } - std::vector error_list; + std::vector error_list; absl::optional service_name; auto it = field.object_value().find("serviceName"); if (it != field.object_value().end()) { @@ -276,18 +89,19 @@ absl::optional ParseHealthCheckConfig(const Json& field, std::unique_ptr ClientChannelServiceConfigParser::ParseGlobalParams( - const grpc_channel_args* /*args*/, const Json& json, grpc_error** error) { + const grpc_channel_args* /*args*/, const Json& json, + grpc_error_handle* error) { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); - std::vector error_list; + std::vector error_list; // Parse LB config. RefCountedPtr parsed_lb_config; auto it = json.object_value().find("loadBalancingConfig"); if (it != json.object_value().end()) { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; parsed_lb_config = LoadBalancingPolicyRegistry::ParseLoadBalancingConfig( it->second, &parse_error); if (parsed_lb_config == nullptr) { - std::vector lb_errors; + std::vector lb_errors; lb_errors.push_back(parse_error); error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR( "field:loadBalancingConfig", &lb_errors)); @@ -319,24 +133,11 @@ ClientChannelServiceConfigParser::ParseGlobalParams( } } } - // Parse retry throttling. - absl::optional - retry_throttling; - it = json.object_value().find("retryThrottling"); - if (it != json.object_value().end()) { - ClientChannelGlobalParsedConfig::RetryThrottling data; - grpc_error* parsing_error = ParseRetryThrottling(it->second, &data); - if (parsing_error != GRPC_ERROR_NONE) { - error_list.push_back(parsing_error); - } else { - retry_throttling.emplace(data); - } - } // Parse health check config. absl::optional health_check_service_name; it = json.object_value().find("healthCheckConfig"); if (it != json.object_value().end()) { - grpc_error* parsing_error = GRPC_ERROR_NONE; + grpc_error_handle parsing_error = GRPC_ERROR_NONE; health_check_service_name = ParseHealthCheckConfig(it->second, &parsing_error); if (parsing_error != GRPC_ERROR_NONE) { @@ -348,20 +149,19 @@ ClientChannelServiceConfigParser::ParseGlobalParams( if (*error == GRPC_ERROR_NONE) { return absl::make_unique( std::move(parsed_lb_config), std::move(lb_policy_name), - retry_throttling, std::move(health_check_service_name)); + std::move(health_check_service_name)); } return nullptr; } std::unique_ptr ClientChannelServiceConfigParser::ParsePerMethodParams( - const grpc_channel_args* /*args*/, const Json& json, grpc_error** error) { + const grpc_channel_args* /*args*/, const Json& json, + grpc_error_handle* error) { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); - std::vector error_list; - absl::optional wait_for_ready; - grpc_millis timeout = 0; - std::unique_ptr retry_policy; + std::vector error_list; // Parse waitForReady. + absl::optional wait_for_ready; auto it = json.object_value().find("waitForReady"); if (it != json.object_value().end()) { if (it->second.type() == Json::Type::JSON_TRUE) { @@ -374,21 +174,14 @@ ClientChannelServiceConfigParser::ParsePerMethodParams( } } // Parse timeout. + grpc_millis timeout = 0; ParseJsonObjectFieldAsDuration(json.object_value(), "timeout", &timeout, &error_list, false); - // Parse retry policy. - it = json.object_value().find("retryPolicy"); - if (it != json.object_value().end()) { - grpc_error* error = GRPC_ERROR_NONE; - retry_policy = ParseRetryPolicy(it->second, &error); - if (retry_policy == nullptr) { - error_list.push_back(error); - } - } + // Return result. *error = GRPC_ERROR_CREATE_FROM_VECTOR("Client channel parser", &error_list); if (*error == GRPC_ERROR_NONE) { - return absl::make_unique( - timeout, wait_for_ready, std::move(retry_policy)); + return absl::make_unique(timeout, + wait_for_ready); } return nullptr; } diff --git a/src/core/ext/filters/client_channel/resolver_result_parsing.h b/src/core/ext/filters/client_channel/resolver_result_parsing.h index cdf89d35ce1..b70068e0017 100644 --- a/src/core/ext/filters/client_channel/resolver_result_parsing.h +++ b/src/core/ext/filters/client_channel/resolver_result_parsing.h @@ -1,20 +1,18 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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. - * - */ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// #ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H #define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H @@ -26,7 +24,6 @@ #include "src/core/ext/filters/client_channel/lb_policy.h" #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/resolver.h" -#include "src/core/ext/filters/client_channel/retry_throttle.h" #include "src/core/ext/filters/client_channel/service_config.h" #include "src/core/lib/channel/status_util.h" #include "src/core/lib/gprpp/ref_counted.h" @@ -40,19 +37,12 @@ namespace internal { class ClientChannelGlobalParsedConfig : public ServiceConfigParser::ParsedConfig { public: - struct RetryThrottling { - intptr_t max_milli_tokens = 0; - intptr_t milli_token_ratio = 0; - }; - ClientChannelGlobalParsedConfig( RefCountedPtr parsed_lb_config, std::string parsed_deprecated_lb_policy, - const absl::optional& retry_throttling, absl::optional health_check_service_name) : parsed_lb_config_(std::move(parsed_lb_config)), parsed_deprecated_lb_policy_(std::move(parsed_deprecated_lb_policy)), - retry_throttling_(retry_throttling), health_check_service_name_(std::move(health_check_service_name)) {} RefCountedPtr parsed_lb_config() const { @@ -63,10 +53,6 @@ class ClientChannelGlobalParsedConfig return parsed_deprecated_lb_policy_; } - absl::optional retry_throttling() const { - return retry_throttling_; - } - const absl::optional& health_check_service_name() const { return health_check_service_name_; } @@ -74,49 +60,34 @@ class ClientChannelGlobalParsedConfig private: RefCountedPtr parsed_lb_config_; std::string parsed_deprecated_lb_policy_; - absl::optional retry_throttling_; absl::optional health_check_service_name_; }; class ClientChannelMethodParsedConfig : public ServiceConfigParser::ParsedConfig { public: - struct RetryPolicy { - int max_attempts = 0; - grpc_millis initial_backoff = 0; - grpc_millis max_backoff = 0; - float backoff_multiplier = 0; - StatusCodeSet retryable_status_codes; - }; - ClientChannelMethodParsedConfig(grpc_millis timeout, - const absl::optional& wait_for_ready, - std::unique_ptr retry_policy) - : timeout_(timeout), - wait_for_ready_(wait_for_ready), - retry_policy_(std::move(retry_policy)) {} + const absl::optional& wait_for_ready) + : timeout_(timeout), wait_for_ready_(wait_for_ready) {} grpc_millis timeout() const { return timeout_; } absl::optional wait_for_ready() const { return wait_for_ready_; } - const RetryPolicy* retry_policy() const { return retry_policy_.get(); } - private: grpc_millis timeout_ = 0; absl::optional wait_for_ready_; - std::unique_ptr retry_policy_; }; class ClientChannelServiceConfigParser : public ServiceConfigParser::Parser { public: std::unique_ptr ParseGlobalParams( const grpc_channel_args* /*args*/, const Json& json, - grpc_error** error) override; + grpc_error_handle* error) override; std::unique_ptr ParsePerMethodParams( const grpc_channel_args* /*args*/, const Json& json, - grpc_error** error) override; + grpc_error_handle* error) override; static size_t ParserIndex(); static void Register(); @@ -125,4 +96,4 @@ class ClientChannelServiceConfigParser : public ServiceConfigParser::Parser { } // namespace internal } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H */ +#endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_RESULT_PARSING_H diff --git a/src/core/ext/filters/client_channel/retry_filter.cc b/src/core/ext/filters/client_channel/retry_filter.cc new file mode 100644 index 00000000000..a03d2da10ed --- /dev/null +++ b/src/core/ext/filters/client_channel/retry_filter.cc @@ -0,0 +1,2188 @@ +// +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "src/core/ext/filters/client_channel/retry_filter.h" + +#include "absl/container/inlined_vector.h" +#include "absl/status/statusor.h" +#include "absl/strings/strip.h" + +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/retry_service_config.h" +#include "src/core/ext/filters/client_channel/retry_throttle.h" +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/ext/filters/client_channel/service_config_call_data.h" +#include "src/core/lib/backoff/backoff.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/transport/error_utils.h" +#include "src/core/lib/transport/metadata.h" +#include "src/core/lib/transport/metadata_batch.h" +#include "src/core/lib/transport/static_metadata.h" +#include "src/core/lib/transport/status_metadata.h" +#include "src/core/lib/uri/uri_parser.h" + +// +// Retry filter +// + +// This filter is intended to be used in the DynamicFilter stack in the +// client channel, which is situated between the name resolver and the +// LB policy. Normally, the last filter in the DynamicFilter stack is +// the DynamicTerminationFilter (see client_channel.cc), which creates a +// LoadBalancedCall and delegates to it. However, when retries are +// enabled, this filter is used instead of the DynamicTerminationFilter. +// +// In order to support retries, we act as a proxy for stream op batches. +// When we get a batch from the surface, we add it to our list of pending +// batches, and we then use those batches to construct separate "child" +// batches to be started on an LB call. When the child batches return, we +// then decide which pending batches have been completed and schedule their +// callbacks accordingly. If a call attempt fails and we want to retry it, +// we create a new LB call and start again, constructing new "child" batches +// for the new LB call. +// +// Note that retries are committed when receiving data from the server +// (except for Trailers-Only responses). However, there may be many +// send ops started before receiving any data, so we may have already +// completed some number of send ops (and returned the completions up to +// the surface) by the time we realize that we need to retry. To deal +// with this, we cache data for send ops, so that we can replay them on a +// different LB call even after we have completed the original batches. +// +// The code is structured as follows: +// - In CallData (in the parent channel), we maintain a list of pending +// ops and cached data for send ops. +// - There is a CallData::CallAttempt object for each retry attempt. +// This object contains the LB call for that attempt and state to indicate +// which ops from the CallData object have already been sent down to that +// LB call. +// - There is a CallData::CallAttempt::BatchData object for each "child" +// batch sent on the LB call. +// +// When constructing the "child" batches, we compare the state in the +// CallAttempt object against the state in the CallData object to see +// which batches need to be sent on the LB call for a given attempt. + +// TODO(roth): In subsequent PRs: +// - add support for transparent retries (including initial metadata) +// - figure out how to record stats in census for retries +// (census filter is on top of this one) +// - add census stats for retries + +// By default, we buffer 256 KiB per RPC for retries. +// TODO(roth): Do we have any data to suggest a better value? +#define DEFAULT_PER_RPC_RETRY_BUFFER_SIZE (256 << 10) + +// This value was picked arbitrarily. It can be changed if there is +// any even moderately compelling reason to do so. +#define RETRY_BACKOFF_JITTER 0.2 + +namespace grpc_core { + +namespace { + +using internal::RetryGlobalConfig; +using internal::RetryMethodConfig; +using internal::RetryServiceConfigParser; +using internal::ServerRetryThrottleData; + +TraceFlag grpc_retry_trace(false, "retry"); + +// +// RetryFilter +// + +class RetryFilter { + public: + class CallData; + + static grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args) { + GPR_ASSERT(args->is_last); + GPR_ASSERT(elem->filter == &kRetryFilterVtable); + grpc_error_handle error = GRPC_ERROR_NONE; + new (elem->channel_data) RetryFilter(args->channel_args, &error); + return error; + } + + static void Destroy(grpc_channel_element* elem) { + auto* chand = static_cast(elem->channel_data); + chand->~RetryFilter(); + } + + // Will never be called. + static void StartTransportOp(grpc_channel_element* /*elem*/, + grpc_transport_op* /*op*/) {} + static void GetChannelInfo(grpc_channel_element* /*elem*/, + const grpc_channel_info* /*info*/) {} + + private: + static size_t GetMaxPerRpcRetryBufferSize(const grpc_channel_args* args) { + return static_cast(grpc_channel_args_find_integer( + args, GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE, + {DEFAULT_PER_RPC_RETRY_BUFFER_SIZE, 0, INT_MAX})); + } + + RetryFilter(const grpc_channel_args* args, grpc_error_handle* error) + : client_channel_(grpc_channel_args_find_pointer( + args, GRPC_ARG_CLIENT_CHANNEL)), + per_rpc_retry_buffer_size_(GetMaxPerRpcRetryBufferSize(args)) { + // Get retry throttling parameters from service config. + auto* service_config = grpc_channel_args_find_pointer( + args, GRPC_ARG_SERVICE_CONFIG_OBJ); + if (service_config == nullptr) return; + const auto* config = static_cast( + service_config->GetGlobalParsedConfig( + RetryServiceConfigParser::ParserIndex())); + if (config == nullptr) return; + // Get server name from target URI. + const char* server_uri = + grpc_channel_args_find_string(args, GRPC_ARG_SERVER_URI); + if (server_uri == nullptr) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "server URI channel arg missing or wrong type in client channel " + "filter"); + return; + } + absl::StatusOr uri = URI::Parse(server_uri); + if (!uri.ok() || uri->path().empty()) { + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "could not extract server name from target URI"); + return; + } + std::string server_name(absl::StripPrefix(uri->path(), "/")); + // Get throttling config for server_name. + retry_throttle_data_ = internal::ServerRetryThrottleMap::GetDataForServer( + server_name, config->max_milli_tokens(), config->milli_token_ratio()); + } + + ClientChannel* client_channel_; + size_t per_rpc_retry_buffer_size_; + RefCountedPtr retry_throttle_data_; +}; + +// +// RetryFilter::CallData +// + +class RetryFilter::CallData { + public: + static grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args); + static void Destroy(grpc_call_element* elem, + const grpc_call_final_info* /*final_info*/, + grpc_closure* then_schedule_closure); + static void StartTransportStreamOpBatch( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch); + static void SetPollent(grpc_call_element* elem, grpc_polling_entity* pollent); + + private: + class Canceller; + class CallStackDestructionBarrier; + + // Pending batches stored in call data. + struct PendingBatch { + // The pending batch. If nullptr, this slot is empty. + grpc_transport_stream_op_batch* batch = nullptr; + // Indicates whether payload for send ops has been cached in CallData. + bool send_ops_cached = false; + }; + + // State associated with each call attempt. + // Allocated on the arena. + class CallAttempt + : public RefCounted { + public: + explicit CallAttempt(CallData* calld); + + ClientChannel::LoadBalancedCall* lb_call() const { return lb_call_.get(); } + + // Constructs and starts whatever batches are needed on this call + // attempt. + void StartRetriableBatches(); + + // Frees cached send ops that have already been completed after + // committing the call. + void FreeCachedSendOpDataAfterCommit(); + + private: + // State used for starting a retryable batch on the call attempt's LB call. + // This provides its own grpc_transport_stream_op_batch and other data + // structures needed to populate the ops in the batch. + // We allocate one struct on the arena for each attempt at starting a + // batch on a given LB call. + class BatchData + : public RefCounted { + public: + BatchData(RefCountedPtr call_attempt, int refcount, + bool set_on_complete); + ~BatchData() override; + + grpc_transport_stream_op_batch* batch() { return &batch_; } + + // Adds retriable send_initial_metadata op to batch_data. + void AddRetriableSendInitialMetadataOp(); + // Adds retriable send_message op to batch_data. + void AddRetriableSendMessageOp(); + // Adds retriable send_trailing_metadata op to batch_data. + void AddRetriableSendTrailingMetadataOp(); + // Adds retriable recv_initial_metadata op to batch_data. + void AddRetriableRecvInitialMetadataOp(); + // Adds retriable recv_message op to batch_data. + void AddRetriableRecvMessageOp(); + // Adds retriable recv_trailing_metadata op to batch_data. + void AddRetriableRecvTrailingMetadataOp(); + + private: + // Returns true if the call is being retried. + bool MaybeRetry(grpc_status_code status, grpc_mdelem* server_pushback_md, + bool is_lb_drop); + + // Frees cached send ops that were completed by the completed batch in + // batch_data. Used when batches are completed after the call is + // committed. + void FreeCachedSendOpDataForCompletedBatch(); + + // Invokes recv_initial_metadata_ready for a batch. + static void InvokeRecvInitialMetadataCallback(void* arg, + grpc_error_handle error); + // Intercepts recv_initial_metadata_ready callback for retries. + // Commits the call and returns the initial metadata up the stack. + static void RecvInitialMetadataReady(void* arg, grpc_error_handle error); + + // Invokes recv_message_ready for a batch. + static void InvokeRecvMessageCallback(void* arg, grpc_error_handle error); + // Intercepts recv_message_ready callback for retries. + // Commits the call and returns the message up the stack. + static void RecvMessageReady(void* arg, grpc_error_handle error); + + // Adds recv_trailing_metadata_ready closure to closures. + void AddClosureForRecvTrailingMetadataReady( + grpc_error_handle error, CallCombinerClosureList* closures); + // Adds any necessary closures for deferred recv_initial_metadata and + // recv_message callbacks to closures. + void AddClosuresForDeferredRecvCallbacks( + CallCombinerClosureList* closures); + // For any pending batch containing an op that has not yet been started, + // adds the pending batch's completion closures to closures. + void AddClosuresToFailUnstartedPendingBatches( + grpc_error_handle error, CallCombinerClosureList* closures); + // Runs necessary closures upon completion of a call attempt. + void RunClosuresForCompletedCall(grpc_error_handle error); + // Intercepts recv_trailing_metadata_ready callback for retries. + // Commits the call and returns the trailing metadata up the stack. + static void RecvTrailingMetadataReady(void* arg, grpc_error_handle error); + + // Adds the on_complete closure for the pending batch completed in + // batch_data to closures. + void AddClosuresForCompletedPendingBatch( + grpc_error_handle error, CallCombinerClosureList* closures); + + // If there are any cached ops to replay or pending ops to start on the + // LB call, adds them to closures. + void AddClosuresForReplayOrPendingSendOps( + CallCombinerClosureList* closures); + + // Callback used to intercept on_complete from LB calls. + static void OnComplete(void* arg, grpc_error_handle error); + + RefCountedPtr call_attempt_; + // The batch to use in the LB call. + // Its payload field points to CallAttempt::batch_payload_. + grpc_transport_stream_op_batch batch_; + // For intercepting on_complete. + grpc_closure on_complete_; + }; + + // Creates a BatchData object on the call's arena with the + // specified refcount. If set_on_complete is true, the batch's + // on_complete callback will be set to point to on_complete(); + // otherwise, the batch's on_complete callback will be null. + BatchData* CreateBatch(int refcount, bool set_on_complete) { + return calld_->arena_->New(Ref(), refcount, set_on_complete); + } + + // If there are any cached send ops that need to be replayed on this + // call attempt, creates and returns a new batch to replay those ops. + // Otherwise, returns nullptr. + BatchData* MaybeCreateBatchForReplay(); + + // Adds batches for pending batches to closures. + void AddBatchesForPendingBatches(CallCombinerClosureList* closures); + + // Adds whatever batches are needed on this attempt to closures. + void AddRetriableBatches(CallCombinerClosureList* closures); + + // Returns true if any op in the batch was not yet started on this attempt. + bool PendingBatchIsUnstarted(PendingBatch* pending); + + // Helper function used to start a recv_trailing_metadata batch. This + // is used in the case where a recv_initial_metadata or recv_message + // op fails in a way that we know the call is over but when the application + // has not yet started its own recv_trailing_metadata op. + void StartInternalRecvTrailingMetadata(); + + CallData* calld_; + RefCountedPtr lb_call_; + + // BatchData.batch.payload points to this. + grpc_transport_stream_op_batch_payload batch_payload_; + // For send_initial_metadata. + // Note that we need to make a copy of the initial metadata for each + // call attempt instead of just referring to the copy in call_data, + // because filters in the subchannel stack may modify the metadata, + // so we need to start in a pristine state for each attempt of the call. + grpc_linked_mdelem* send_initial_metadata_storage_; + grpc_metadata_batch send_initial_metadata_; + // For send_message. + // TODO(roth): Restructure this to eliminate use of ManualConstructor. + ManualConstructor send_message_; + // For send_trailing_metadata. + grpc_linked_mdelem* send_trailing_metadata_storage_; + grpc_metadata_batch send_trailing_metadata_; + // For intercepting recv_initial_metadata. + grpc_metadata_batch recv_initial_metadata_; + grpc_closure recv_initial_metadata_ready_; + bool trailing_metadata_available_ = false; + // For intercepting recv_message. + grpc_closure recv_message_ready_; + OrphanablePtr recv_message_; + // For intercepting recv_trailing_metadata. + grpc_metadata_batch recv_trailing_metadata_; + grpc_transport_stream_stats collect_stats_; + grpc_closure recv_trailing_metadata_ready_; + // These fields indicate which ops have been started and completed on + // this call attempt. + size_t started_send_message_count_ = 0; + size_t completed_send_message_count_ = 0; + size_t started_recv_message_count_ = 0; + size_t completed_recv_message_count_ = 0; + bool started_send_initial_metadata_ : 1; + bool completed_send_initial_metadata_ : 1; + bool started_send_trailing_metadata_ : 1; + bool completed_send_trailing_metadata_ : 1; + bool started_recv_initial_metadata_ : 1; + bool completed_recv_initial_metadata_ : 1; + bool started_recv_trailing_metadata_ : 1; + bool completed_recv_trailing_metadata_ : 1; + // State for callback processing. + BatchData* recv_initial_metadata_ready_deferred_batch_ = nullptr; + grpc_error_handle recv_initial_metadata_error_ = GRPC_ERROR_NONE; + BatchData* recv_message_ready_deferred_batch_ = nullptr; + grpc_error_handle recv_message_error_ = GRPC_ERROR_NONE; + BatchData* recv_trailing_metadata_internal_batch_ = nullptr; + // NOTE: Do not move this next to the metadata bitfields above. That would + // save space but will also result in a data race because compiler + // will generate a 2 byte store which overwrites the meta-data + // fields upon setting this field. + bool retry_dispatched_ : 1; + }; + + CallData(RetryFilter* chand, const grpc_call_element_args& args); + ~CallData(); + + void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); + + // Returns the index into pending_batches_ to be used for batch. + static size_t GetBatchIndex(grpc_transport_stream_op_batch* batch); + PendingBatch* PendingBatchesAdd(grpc_transport_stream_op_batch* batch); + void PendingBatchClear(PendingBatch* pending); + void MaybeClearPendingBatch(PendingBatch* pending); + static void FailPendingBatchInCallCombiner(void* arg, + grpc_error_handle error); + // Fails all pending batches. Does NOT yield call combiner. + void PendingBatchesFail(grpc_error_handle error); + // Returns a pointer to the first pending batch for which predicate(batch) + // returns true, or null if not found. + template + PendingBatch* PendingBatchFind(const char* log_message, Predicate predicate); + + // Caches data for send ops so that it can be retried later, if not + // already cached. + void MaybeCacheSendOpsForBatch(PendingBatch* pending); + void FreeCachedSendInitialMetadata(); + // Frees cached send_message at index idx. + void FreeCachedSendMessage(size_t idx); + void FreeCachedSendTrailingMetadata(); + void FreeAllCachedSendOpData(); + + // Commits the call so that no further retry attempts will be performed. + void RetryCommit(CallAttempt* call_attempt); + + // Starts a retry after appropriate back-off. + void DoRetry(grpc_millis server_pushback_ms); + static void OnRetryTimer(void* arg, grpc_error_handle error); + + RefCountedPtr CreateLoadBalancedCall(); + + void CreateCallAttempt(); + + // Adds a closure to closures that will execute batch in the call combiner. + void AddClosureForBatch(grpc_transport_stream_op_batch* batch, + CallCombinerClosureList* closures); + + RetryFilter* chand_; + grpc_polling_entity* pollent_; + RefCountedPtr retry_throttle_data_; + const RetryMethodConfig* retry_policy_ = nullptr; + BackOff retry_backoff_; + + grpc_slice path_; // Request path. + gpr_cycle_counter call_start_time_; + grpc_millis deadline_; + Arena* arena_; + grpc_call_stack* owning_call_; + CallCombiner* call_combiner_; + grpc_call_context_element* call_context_; + + RefCountedPtr call_stack_destruction_barrier_; + + // TODO(roth): As part of implementing hedging, we will need to maintain a + // list of all pending attempts, so that we can cancel them all if the call + // gets cancelled. + RefCountedPtr call_attempt_; + + // LB call used when the call is commited before any CallAttempt is + // created. + // TODO(roth): Change CallAttempt logic such that once we've committed + // and all cached send ops have been replayed, we move the LB call + // from the CallAttempt here, thus creating a fast path for the + // remainder of the streaming call. + RefCountedPtr committed_call_; + + // When are are not yet fully committed to a particular call (i.e., + // either we might still retry or we have committed to the call but + // there are still some cached ops to be replayed on the call), + // batches received from above will be added to this list, and they + // will not be removed until we have invoked their completion callbacks. + size_t bytes_buffered_for_retry_ = 0; + PendingBatch pending_batches_[MAX_PENDING_BATCHES]; + bool pending_send_initial_metadata_ : 1; + bool pending_send_message_ : 1; + bool pending_send_trailing_metadata_ : 1; + + // Retry state. + bool retry_committed_ : 1; + bool last_attempt_got_server_pushback_ : 1; + int num_attempts_completed_ = 0; + Mutex timer_mu_; + Canceller* canceller_ ABSL_GUARDED_BY(timer_mu_); + grpc_timer retry_timer_ ABSL_GUARDED_BY(timer_mu_); + grpc_closure retry_closure_; + + // The number of batches containing send ops that are currently in-flight + // on any call attempt. + // We hold a ref to the call stack while this is non-zero, since replay + // batches may not complete until after all callbacks have been returned + // to the surface, and we need to make sure that the call is not destroyed + // until all of these batches have completed. + // Note that we actually only need to track replay batches, but it's + // easier to track all batches with send ops. + int num_in_flight_call_attempt_send_batches_ = 0; + + // Cached data for retrying send ops. + // send_initial_metadata + bool seen_send_initial_metadata_ = false; + grpc_linked_mdelem* send_initial_metadata_storage_ = nullptr; + grpc_metadata_batch send_initial_metadata_; + uint32_t send_initial_metadata_flags_; + // TODO(roth): As part of implementing hedging, we'll probably need to + // have the LB call set a value in CallAttempt and then propagate it + // from CallAttempt to the parent call when we commit. Otherwise, we + // may leave this with a value for a peer other than the one we + // actually commit to. + gpr_atm* peer_string_; + // send_message + // When we get a send_message op, we replace the original byte stream + // with a CachingByteStream that caches the slices to a local buffer for + // use in retries. + // Note: We inline the cache for the first 3 send_message ops and use + // dynamic allocation after that. This number was essentially picked + // at random; it could be changed in the future to tune performance. + absl::InlinedVector send_messages_; + // send_trailing_metadata + bool seen_send_trailing_metadata_ = false; + grpc_linked_mdelem* send_trailing_metadata_storage_ = nullptr; + grpc_metadata_batch send_trailing_metadata_; +}; + +// +// RetryFilter::CallData::CallStackDestructionBarrier +// + +// A class to track the existence of LoadBalancedCall call stacks that +// we've created. We wait until all such call stacks have been +// destroyed before we return the on_call_stack_destruction closure up +// to the surface. +// +// The parent RetryFilter::CallData object holds a ref to this object. +// When it is destroyed, it will store the on_call_stack_destruction +// closure from the surface in this object and then release its ref. +// We also take a ref to this object for each LB call we create, and +// those refs are not released until the LB call stack is destroyed. +// When this object is destroyed, it will invoke the +// on_call_stack_destruction closure from the surface. +class RetryFilter::CallData::CallStackDestructionBarrier + : public RefCounted { + public: + CallStackDestructionBarrier() {} + + ~CallStackDestructionBarrier() override { + // TODO(yashkt) : This can potentially be a Closure::Run + ExecCtx::Run(DEBUG_LOCATION, on_call_stack_destruction_, GRPC_ERROR_NONE); + } + + // Set the closure from the surface. This closure will be invoked + // when this object is destroyed. + void set_on_call_stack_destruction(grpc_closure* on_call_stack_destruction) { + on_call_stack_destruction_ = on_call_stack_destruction; + } + + // Invoked to get an on_call_stack_destruction closure for a new LB call. + grpc_closure* MakeLbCallDestructionClosure(CallData* calld) { + Ref().release(); // Ref held by callback. + grpc_closure* on_lb_call_destruction_complete = + calld->arena_->New(); + GRPC_CLOSURE_INIT(on_lb_call_destruction_complete, + OnLbCallDestructionComplete, this, nullptr); + return on_lb_call_destruction_complete; + } + + private: + static void OnLbCallDestructionComplete(void* arg, + grpc_error_handle /*error*/) { + auto* self = static_cast(arg); + self->Unref(); + } + + grpc_closure* on_call_stack_destruction_ = nullptr; +}; + +// +// RetryFilter::CallData::Canceller +// + +class RetryFilter::CallData::Canceller { + public: + explicit Canceller(CallData* calld) : calld_(calld) { + GRPC_CALL_STACK_REF(calld_->owning_call_, "RetryCanceller"); + GRPC_CLOSURE_INIT(&closure_, &Cancel, this, nullptr); + calld_->call_combiner_->SetNotifyOnCancel(&closure_); + } + + private: + static void Cancel(void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + auto* calld = self->calld_; + { + MutexLock lock(&calld->timer_mu_); + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "calld=%p: cancelling retry timer: error=%s self=%p " + "calld->canceller_=%p", + calld, grpc_error_std_string(error).c_str(), self, + calld->canceller_); + } + if (calld->canceller_ == self && error != GRPC_ERROR_NONE) { + calld->canceller_ = nullptr; // Checked by OnRetryTimer(). + grpc_timer_cancel(&calld->retry_timer_); + calld->FreeAllCachedSendOpData(); + GRPC_CALL_COMBINER_STOP(calld->call_combiner_, "Canceller"); + } + } + GRPC_CALL_STACK_UNREF(calld->owning_call_, "RetryCanceller"); + delete self; + } + + CallData* calld_; + grpc_closure closure_; +}; + +// +// RetryFilter::CallData::CallAttempt +// + +RetryFilter::CallData::CallAttempt::CallAttempt(CallData* calld) + : calld_(calld), + batch_payload_(calld->call_context_), + started_send_initial_metadata_(false), + completed_send_initial_metadata_(false), + started_send_trailing_metadata_(false), + completed_send_trailing_metadata_(false), + started_recv_initial_metadata_(false), + completed_recv_initial_metadata_(false), + started_recv_trailing_metadata_(false), + completed_recv_trailing_metadata_(false), + retry_dispatched_(false) { + lb_call_ = calld->CreateLoadBalancedCall(); + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: attempt=%p: create lb_call=%p", + calld->chand_, calld, this, lb_call_.get()); + } +} + +void RetryFilter::CallData::CallAttempt::FreeCachedSendOpDataAfterCommit() { + // TODO(roth): When we implement hedging, this logic will need to get + // a bit more complex, because there may be other (now abandoned) call + // attempts still using this data. We may need to do some sort of + // ref-counting instead. + if (completed_send_initial_metadata_) { + calld_->FreeCachedSendInitialMetadata(); + } + for (size_t i = 0; i < completed_send_message_count_; ++i) { + calld_->FreeCachedSendMessage(i); + } + if (completed_send_trailing_metadata_) { + calld_->FreeCachedSendTrailingMetadata(); + } +} + +bool RetryFilter::CallData::CallAttempt::PendingBatchIsUnstarted( + PendingBatch* pending) { + // Only look at batches containing send ops, since batches containing + // only recv ops are always started immediately. + if (pending->batch == nullptr || pending->batch->on_complete == nullptr) { + return false; + } + if (pending->batch->send_initial_metadata && + !started_send_initial_metadata_) { + return true; + } + if (pending->batch->send_message && + started_send_message_count_ < calld_->send_messages_.size()) { + return true; + } + if (pending->batch->send_trailing_metadata && + !started_send_trailing_metadata_) { + return true; + } + return false; +} + +void RetryFilter::CallData::CallAttempt::StartInternalRecvTrailingMetadata() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: call failed but recv_trailing_metadata not " + "started; starting it internally", + calld_->chand_, calld_); + } + // Create batch_data with 2 refs, since this batch will be unreffed twice: + // once for the recv_trailing_metadata_ready callback when the batch + // completes, and again when we actually get a recv_trailing_metadata + // op from the surface. + BatchData* batch_data = CreateBatch(2, false /* set_on_complete */); + batch_data->AddRetriableRecvTrailingMetadataOp(); + recv_trailing_metadata_internal_batch_ = batch_data; + // Note: This will release the call combiner. + lb_call_->StartTransportStreamOpBatch(batch_data->batch()); +} + +// If there are any cached send ops that need to be replayed on the +// current call attempt, creates and returns a new batch to replay those ops. +// Otherwise, returns nullptr. +RetryFilter::CallData::CallAttempt::BatchData* +RetryFilter::CallData::CallAttempt::MaybeCreateBatchForReplay() { + BatchData* replay_batch_data = nullptr; + // send_initial_metadata. + if (calld_->seen_send_initial_metadata_ && !started_send_initial_metadata_ && + !calld_->pending_send_initial_metadata_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: replaying previously completed " + "send_initial_metadata op", + calld_->chand_, calld_); + } + replay_batch_data = CreateBatch(1, true /* set_on_complete */); + replay_batch_data->AddRetriableSendInitialMetadataOp(); + } + // send_message. + // Note that we can only have one send_message op in flight at a time. + if (started_send_message_count_ < calld_->send_messages_.size() && + started_send_message_count_ == completed_send_message_count_ && + !calld_->pending_send_message_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: replaying previously completed " + "send_message op", + calld_->chand_, calld_); + } + if (replay_batch_data == nullptr) { + replay_batch_data = CreateBatch(1, true /* set_on_complete */); + } + replay_batch_data->AddRetriableSendMessageOp(); + } + // send_trailing_metadata. + // Note that we only add this op if we have no more send_message ops + // to start, since we can't send down any more send_message ops after + // send_trailing_metadata. + if (calld_->seen_send_trailing_metadata_ && + started_send_message_count_ == calld_->send_messages_.size() && + !started_send_trailing_metadata_ && + !calld_->pending_send_trailing_metadata_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: replaying previously completed " + "send_trailing_metadata op", + calld_->chand_, calld_); + } + if (replay_batch_data == nullptr) { + replay_batch_data = CreateBatch(1, true /* set_on_complete */); + } + replay_batch_data->AddRetriableSendTrailingMetadataOp(); + } + return replay_batch_data; +} + +void RetryFilter::CallData::CallAttempt::AddBatchesForPendingBatches( + CallCombinerClosureList* closures) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(calld_->pending_batches_); ++i) { + PendingBatch* pending = &calld_->pending_batches_[i]; + grpc_transport_stream_op_batch* batch = pending->batch; + if (batch == nullptr) continue; + // Skip any batch that either (a) has already been started on this + // call attempt or (b) we can't start yet because we're still + // replaying send ops that need to be completed first. + // TODO(roth): Note that if any one op in the batch can't be sent + // yet due to ops that we're replaying, we don't start any of the ops + // in the batch. This is probably okay, but it could conceivably + // lead to increased latency in some cases -- e.g., we could delay + // starting a recv op due to it being in the same batch with a send + // op. If/when we revamp the callback protocol in + // transport_stream_op_batch, we may be able to fix this. + if (batch->send_initial_metadata && started_send_initial_metadata_) { + continue; + } + if (batch->send_message && + completed_send_message_count_ < started_send_message_count_) { + continue; + } + // Note that we only start send_trailing_metadata if we have no more + // send_message ops to start, since we can't send down any more + // send_message ops after send_trailing_metadata. + if (batch->send_trailing_metadata && + (started_send_message_count_ + batch->send_message < + calld_->send_messages_.size() || + started_send_trailing_metadata_)) { + continue; + } + if (batch->recv_initial_metadata && started_recv_initial_metadata_) { + continue; + } + if (batch->recv_message && + completed_recv_message_count_ < started_recv_message_count_) { + continue; + } + if (batch->recv_trailing_metadata && started_recv_trailing_metadata_) { + // If we previously completed a recv_trailing_metadata op + // initiated by StartInternalRecvTrailingMetadata(), use the + // result of that instead of trying to re-start this op. + if (GPR_UNLIKELY(recv_trailing_metadata_internal_batch_ != nullptr)) { + // If the batch completed, then trigger the completion callback + // directly, so that we return the previously returned results to + // the application. Otherwise, just unref the internally started + // batch, since we'll propagate the completion when it completes. + if (completed_recv_trailing_metadata_) { + // Batches containing recv_trailing_metadata always succeed. + closures->Add( + &recv_trailing_metadata_ready_, GRPC_ERROR_NONE, + "re-executing recv_trailing_metadata_ready to propagate " + "internally triggered result"); + } else { + recv_trailing_metadata_internal_batch_->Unref(); + } + recv_trailing_metadata_internal_batch_ = nullptr; + } + continue; + } + // If we're already committed, just send the batch as-is. + if (calld_->retry_committed_) { + calld_->AddClosureForBatch(batch, closures); + calld_->PendingBatchClear(pending); + continue; + } + // Create batch with the right number of callbacks. + const bool has_send_ops = batch->send_initial_metadata || + batch->send_message || + batch->send_trailing_metadata; + const int num_callbacks = has_send_ops + batch->recv_initial_metadata + + batch->recv_message + + batch->recv_trailing_metadata; + CallAttempt::BatchData* batch_data = + CreateBatch(num_callbacks, has_send_ops /* set_on_complete */); + // Cache send ops if needed. + calld_->MaybeCacheSendOpsForBatch(pending); + // send_initial_metadata. + if (batch->send_initial_metadata) { + batch_data->AddRetriableSendInitialMetadataOp(); + } + // send_message. + if (batch->send_message) { + batch_data->AddRetriableSendMessageOp(); + } + // send_trailing_metadata. + if (batch->send_trailing_metadata) { + batch_data->AddRetriableSendTrailingMetadataOp(); + } + // recv_initial_metadata. + if (batch->recv_initial_metadata) { + // recv_flags is only used on the server side. + GPR_ASSERT(batch->payload->recv_initial_metadata.recv_flags == nullptr); + batch_data->AddRetriableRecvInitialMetadataOp(); + } + // recv_message. + if (batch->recv_message) { + batch_data->AddRetriableRecvMessageOp(); + } + // recv_trailing_metadata. + if (batch->recv_trailing_metadata) { + batch_data->AddRetriableRecvTrailingMetadataOp(); + } + calld_->AddClosureForBatch(batch_data->batch(), closures); + // Track number of in-flight send batches. + // If this is the first one, take a ref to the call stack. + if (batch->send_initial_metadata || batch->send_message || + batch->send_trailing_metadata) { + if (calld_->num_in_flight_call_attempt_send_batches_ == 0) { + GRPC_CALL_STACK_REF(calld_->owning_call_, "retriable_send_batches"); + } + ++calld_->num_in_flight_call_attempt_send_batches_; + } + } +} + +void RetryFilter::CallData::CallAttempt::AddRetriableBatches( + CallCombinerClosureList* closures) { + // Replay previously-returned send_* ops if needed. + BatchData* replay_batch_data = MaybeCreateBatchForReplay(); + if (replay_batch_data != nullptr) { + calld_->AddClosureForBatch(replay_batch_data->batch(), closures); + // Track number of pending send batches. + // If this is the first one, take a ref to the call stack. + if (calld_->num_in_flight_call_attempt_send_batches_ == 0) { + GRPC_CALL_STACK_REF(calld_->owning_call_, "retriable_send_batches"); + } + ++calld_->num_in_flight_call_attempt_send_batches_; + } + // Now add pending batches. + AddBatchesForPendingBatches(closures); +} + +void RetryFilter::CallData::CallAttempt::StartRetriableBatches() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: constructing retriable batches", + calld_->chand_, calld_); + } + // Construct list of closures to execute, one for each pending batch. + CallCombinerClosureList closures; + AddRetriableBatches(&closures); + // Note: This will yield the call combiner. + // Start batches on LB call. + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: starting %" PRIuPTR + " retriable batches on lb_call=%p", + calld_->chand_, calld_, closures.size(), lb_call()); + } + closures.RunClosures(calld_->call_combiner_); +} + +// +// RetryFilter::CallData::CallAttempt::BatchData +// + +RetryFilter::CallData::CallAttempt::BatchData::BatchData( + RefCountedPtr attempt, int refcount, bool set_on_complete) + : RefCounted(nullptr, refcount), call_attempt_(std::move(attempt)) { + // TODO(roth): Consider holding this ref on the call stack in + // CallAttempt instead of here in BatchData. This would eliminate the + // need for CallData::num_in_flight_call_attempt_send_batches_. + // But it would require having a way to unref CallAttempt when it is + // no longer needed (i.e., when the call is committed and all cached + // send ops have been replayed and the LB call is moved into + // CallData::committed_call_). + GRPC_CALL_STACK_REF(call_attempt_->calld_->owning_call_, "CallAttempt"); + batch_.payload = &call_attempt_->batch_payload_; + if (set_on_complete) { + GRPC_CLOSURE_INIT(&on_complete_, OnComplete, this, + grpc_schedule_on_exec_ctx); + batch_.on_complete = &on_complete_; + } +} + +RetryFilter::CallData::CallAttempt::BatchData::~BatchData() { + if (batch_.send_initial_metadata) { + grpc_metadata_batch_destroy(&call_attempt_->send_initial_metadata_); + } + if (batch_.send_trailing_metadata) { + grpc_metadata_batch_destroy(&call_attempt_->send_trailing_metadata_); + } + if (batch_.recv_initial_metadata) { + grpc_metadata_batch_destroy(&call_attempt_->recv_initial_metadata_); + } + if (batch_.recv_trailing_metadata) { + grpc_metadata_batch_destroy(&call_attempt_->recv_trailing_metadata_); + } + GRPC_CALL_STACK_UNREF(call_attempt_->calld_->owning_call_, "CallAttempt"); +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + FreeCachedSendOpDataForCompletedBatch() { + auto* calld = call_attempt_->calld_; + // TODO(roth): When we implement hedging, this logic will need to get + // a bit more complex, because there may be other (now abandoned) call + // attempts still using this data. We may need to do some sort of + // ref-counting instead. + if (batch_.send_initial_metadata) { + calld->FreeCachedSendInitialMetadata(); + } + if (batch_.send_message) { + calld->FreeCachedSendMessage(call_attempt_->completed_send_message_count_ - + 1); + } + if (batch_.send_trailing_metadata) { + calld->FreeCachedSendTrailingMetadata(); + } +} + +bool RetryFilter::CallData::CallAttempt::BatchData::MaybeRetry( + grpc_status_code status, grpc_mdelem* server_pushback_md, bool is_lb_drop) { + auto* calld = call_attempt_->calld_; + // LB drops always inhibit retries. + if (is_lb_drop) return false; + // Get retry policy. + if (calld->retry_policy_ == nullptr) return false; + // If we've already dispatched a retry from this call, return true. + // This catches the case where the batch has multiple callbacks + // (i.e., it includes either recv_message or recv_initial_metadata). + if (call_attempt_->retry_dispatched_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: retry already dispatched", + calld->chand_, calld); + } + return true; + } + // Check status. + if (GPR_LIKELY(status == GRPC_STATUS_OK)) { + if (calld->retry_throttle_data_ != nullptr) { + calld->retry_throttle_data_->RecordSuccess(); + } + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: call succeeded", calld->chand_, + calld); + } + return false; + } + // Status is not OK. Check whether the status is retryable. + if (!calld->retry_policy_->retryable_status_codes().Contains(status)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: status %s not configured as retryable", + calld->chand_, calld, grpc_status_code_to_string(status)); + } + return false; + } + // Record the failure and check whether retries are throttled. + // Note that it's important for this check to come after the status + // code check above, since we should only record failures whose statuses + // match the configured retryable status codes, so that we don't count + // things like failures due to malformed requests (INVALID_ARGUMENT). + // Conversely, it's important for this to come before the remaining + // checks, so that we don't fail to record failures due to other factors. + if (calld->retry_throttle_data_ != nullptr && + !calld->retry_throttle_data_->RecordFailure()) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: retries throttled", calld->chand_, + calld); + } + return false; + } + // Check whether the call is committed. + if (calld->retry_committed_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: retries already committed", + calld->chand_, calld); + } + return false; + } + // Check whether we have retries remaining. + ++calld->num_attempts_completed_; + if (calld->num_attempts_completed_ >= calld->retry_policy_->max_attempts()) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: exceeded %d retry attempts", + calld->chand_, calld, calld->retry_policy_->max_attempts()); + } + return false; + } + // Check server push-back. + grpc_millis server_pushback_ms = -1; + if (server_pushback_md != nullptr) { + // If the value is "-1" or any other unparseable string, we do not retry. + uint32_t ms; + if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(*server_pushback_md), &ms)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: not retrying due to server push-back", + calld->chand_, calld); + } + return false; + } else { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: server push-back: retry in %u ms", + calld->chand_, calld, ms); + } + server_pushback_ms = static_cast(ms); + } + } + // Do retry. + call_attempt_->retry_dispatched_ = true; + calld->DoRetry(server_pushback_ms); + return true; +} + +// +// recv_initial_metadata callback handling +// + +void RetryFilter::CallData::CallAttempt::BatchData:: + InvokeRecvInitialMetadataCallback(void* arg, grpc_error_handle error) { + auto* batch_data = static_cast(arg); + auto* call_attempt = batch_data->call_attempt_.get(); + // Find pending batch. + PendingBatch* pending = call_attempt->calld_->PendingBatchFind( + "invoking recv_initial_metadata_ready for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_initial_metadata && + batch->payload->recv_initial_metadata + .recv_initial_metadata_ready != nullptr; + }); + GPR_ASSERT(pending != nullptr); + // Return metadata. + grpc_metadata_batch_move( + &call_attempt->recv_initial_metadata_, + pending->batch->payload->recv_initial_metadata.recv_initial_metadata); + // Update bookkeeping. + // Note: Need to do this before invoking the callback, since invoking + // the callback will result in yielding the call combiner. + grpc_closure* recv_initial_metadata_ready = + pending->batch->payload->recv_initial_metadata + .recv_initial_metadata_ready; + pending->batch->payload->recv_initial_metadata.recv_initial_metadata_ready = + nullptr; + call_attempt->calld_->MaybeClearPendingBatch(pending); + batch_data->Unref(); + // Invoke callback. + Closure::Run(DEBUG_LOCATION, recv_initial_metadata_ready, + GRPC_ERROR_REF(error)); +} + +void RetryFilter::CallData::CallAttempt::BatchData::RecvInitialMetadataReady( + void* arg, grpc_error_handle error) { + CallAttempt::BatchData* batch_data = + static_cast(arg); + CallAttempt* call_attempt = batch_data->call_attempt_.get(); + CallData* calld = call_attempt->calld_; + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_initial_metadata_ready, error=%s", + calld->chand_, calld, grpc_error_std_string(error).c_str()); + } + call_attempt->completed_recv_initial_metadata_ = true; + // If a retry was already dispatched, then we're not going to use the + // result of this recv_initial_metadata op, so do nothing. + if (call_attempt->retry_dispatched_) { + GRPC_CALL_COMBINER_STOP( + calld->call_combiner_, + "recv_initial_metadata_ready after retry dispatched"); + return; + } + if (!calld->retry_committed_) { + // If we got an error or a Trailers-Only response and have not yet gotten + // the recv_trailing_metadata_ready callback, then defer propagating this + // callback back to the surface. We can evaluate whether to retry when + // recv_trailing_metadata comes back. + if (GPR_UNLIKELY((call_attempt->trailing_metadata_available_ || + error != GRPC_ERROR_NONE) && + !call_attempt->completed_recv_trailing_metadata_)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: deferring recv_initial_metadata_ready " + "(Trailers-Only)", + calld->chand_, calld); + } + call_attempt->recv_initial_metadata_ready_deferred_batch_ = batch_data; + call_attempt->recv_initial_metadata_error_ = GRPC_ERROR_REF(error); + if (!call_attempt->started_recv_trailing_metadata_) { + // recv_trailing_metadata not yet started by application; start it + // ourselves to get status. + call_attempt->StartInternalRecvTrailingMetadata(); + } else { + GRPC_CALL_COMBINER_STOP( + calld->call_combiner_, + "recv_initial_metadata_ready trailers-only or error"); + } + return; + } + // Received valid initial metadata, so commit the call. + calld->RetryCommit(call_attempt); + } + // Invoke the callback to return the result to the surface. + // Manually invoking a callback function; it does not take ownership of error. + InvokeRecvInitialMetadataCallback(batch_data, error); +} + +// +// recv_message callback handling +// + +void RetryFilter::CallData::CallAttempt::BatchData::InvokeRecvMessageCallback( + void* arg, grpc_error_handle error) { + CallAttempt::BatchData* batch_data = + static_cast(arg); + CallAttempt* call_attempt = batch_data->call_attempt_.get(); + CallData* calld = call_attempt->calld_; + // Find pending op. + PendingBatch* pending = calld->PendingBatchFind( + "invoking recv_message_ready for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_message && + batch->payload->recv_message.recv_message_ready != nullptr; + }); + GPR_ASSERT(pending != nullptr); + // Return payload. + *pending->batch->payload->recv_message.recv_message = + std::move(call_attempt->recv_message_); + // Update bookkeeping. + // Note: Need to do this before invoking the callback, since invoking + // the callback will result in yielding the call combiner. + grpc_closure* recv_message_ready = + pending->batch->payload->recv_message.recv_message_ready; + pending->batch->payload->recv_message.recv_message_ready = nullptr; + calld->MaybeClearPendingBatch(pending); + batch_data->Unref(); + // Invoke callback. + Closure::Run(DEBUG_LOCATION, recv_message_ready, GRPC_ERROR_REF(error)); +} + +void RetryFilter::CallData::CallAttempt::BatchData::RecvMessageReady( + void* arg, grpc_error_handle error) { + CallAttempt::BatchData* batch_data = + static_cast(arg); + CallAttempt* call_attempt = batch_data->call_attempt_.get(); + CallData* calld = call_attempt->calld_; + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: got recv_message_ready, error=%s", + calld->chand_, calld, grpc_error_std_string(error).c_str()); + } + ++call_attempt->completed_recv_message_count_; + // If a retry was already dispatched, then we're not going to use the + // result of this recv_message op, so do nothing. + if (call_attempt->retry_dispatched_) { + GRPC_CALL_COMBINER_STOP(calld->call_combiner_, + "recv_message_ready after retry dispatched"); + return; + } + if (!calld->retry_committed_) { + // If we got an error or the payload was nullptr and we have not yet gotten + // the recv_trailing_metadata_ready callback, then defer propagating this + // callback back to the surface. We can evaluate whether to retry when + // recv_trailing_metadata comes back. + if (GPR_UNLIKELY((call_attempt->recv_message_ == nullptr || + error != GRPC_ERROR_NONE) && + !call_attempt->completed_recv_trailing_metadata_)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: deferring recv_message_ready (nullptr " + "message and recv_trailing_metadata pending)", + calld->chand_, calld); + } + call_attempt->recv_message_ready_deferred_batch_ = batch_data; + call_attempt->recv_message_error_ = GRPC_ERROR_REF(error); + if (!call_attempt->started_recv_trailing_metadata_) { + // recv_trailing_metadata not yet started by application; start it + // ourselves to get status. + call_attempt->StartInternalRecvTrailingMetadata(); + } else { + GRPC_CALL_COMBINER_STOP(calld->call_combiner_, + "recv_message_ready null"); + } + return; + } + // Received a valid message, so commit the call. + calld->RetryCommit(call_attempt); + } + // Invoke the callback to return the result to the surface. + // Manually invoking a callback function; it does not take ownership of error. + InvokeRecvMessageCallback(batch_data, error); +} + +// +// recv_trailing_metadata handling +// + +namespace { + +// Sets *status, *server_pushback_md, and *is_lb_drop based on md_batch +// and error. +void GetCallStatus(grpc_millis deadline, grpc_metadata_batch* md_batch, + grpc_error_handle error, grpc_status_code* status, + grpc_mdelem** server_pushback_md, bool* is_lb_drop) { + if (error != GRPC_ERROR_NONE) { + grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); + intptr_t value = 0; + if (grpc_error_get_int(error, GRPC_ERROR_INT_LB_POLICY_DROP, &value) && + value != 0) { + *is_lb_drop = true; + } + } else { + GPR_ASSERT(md_batch->idx.named.grpc_status != nullptr); + *status = + grpc_get_status_code_from_metadata(md_batch->idx.named.grpc_status->md); + if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) { + *server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md; + } + } + GRPC_ERROR_UNREF(error); +} + +} // namespace + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddClosureForRecvTrailingMetadataReady(grpc_error_handle error, + CallCombinerClosureList* closures) { + auto* calld = call_attempt_->calld_; + // Find pending batch. + PendingBatch* pending = calld->PendingBatchFind( + "invoking recv_trailing_metadata for", + [](grpc_transport_stream_op_batch* batch) { + return batch->recv_trailing_metadata && + batch->payload->recv_trailing_metadata + .recv_trailing_metadata_ready != nullptr; + }); + // If we generated the recv_trailing_metadata op internally via + // StartInternalRecvTrailingMetadata(), then there will be no pending batch. + if (pending == nullptr) { + GRPC_ERROR_UNREF(error); + return; + } + // Return metadata. + grpc_metadata_batch_move( + &call_attempt_->recv_trailing_metadata_, + pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata); + // Add closure. + closures->Add(pending->batch->payload->recv_trailing_metadata + .recv_trailing_metadata_ready, + error, "recv_trailing_metadata_ready for pending batch"); + // Update bookkeeping. + pending->batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + nullptr; + calld->MaybeClearPendingBatch(pending); +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddClosuresForDeferredRecvCallbacks(CallCombinerClosureList* closures) { + if (batch_.recv_trailing_metadata) { + // Add closure for deferred recv_initial_metadata_ready. + if (GPR_UNLIKELY( + call_attempt_->recv_initial_metadata_ready_deferred_batch_ != + nullptr)) { + GRPC_CLOSURE_INIT( + &call_attempt_->recv_initial_metadata_ready_, + InvokeRecvInitialMetadataCallback, + call_attempt_->recv_initial_metadata_ready_deferred_batch_, + grpc_schedule_on_exec_ctx); + closures->Add(&call_attempt_->recv_initial_metadata_ready_, + call_attempt_->recv_initial_metadata_error_, + "resuming recv_initial_metadata_ready"); + call_attempt_->recv_initial_metadata_ready_deferred_batch_ = nullptr; + } + // Add closure for deferred recv_message_ready. + if (GPR_UNLIKELY(call_attempt_->recv_message_ready_deferred_batch_ != + nullptr)) { + GRPC_CLOSURE_INIT(&call_attempt_->recv_message_ready_, + InvokeRecvMessageCallback, + call_attempt_->recv_message_ready_deferred_batch_, + grpc_schedule_on_exec_ctx); + closures->Add(&call_attempt_->recv_message_ready_, + call_attempt_->recv_message_error_, + "resuming recv_message_ready"); + call_attempt_->recv_message_ready_deferred_batch_ = nullptr; + } + } +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddClosuresToFailUnstartedPendingBatches( + grpc_error_handle error, CallCombinerClosureList* closures) { + auto* calld = call_attempt_->calld_; + for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches_); ++i) { + PendingBatch* pending = &calld->pending_batches_[i]; + if (call_attempt_->PendingBatchIsUnstarted(pending)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: failing unstarted pending batch at " + "index %" PRIuPTR, + calld->chand_, calld, i); + } + closures->Add(pending->batch->on_complete, GRPC_ERROR_REF(error), + "failing on_complete for pending batch"); + pending->batch->on_complete = nullptr; + calld->MaybeClearPendingBatch(pending); + } + } + GRPC_ERROR_UNREF(error); +} + +void RetryFilter::CallData::CallAttempt::BatchData::RunClosuresForCompletedCall( + grpc_error_handle error) { + // Construct list of closures to execute. + CallCombinerClosureList closures; + // First, add closure for recv_trailing_metadata_ready. + AddClosureForRecvTrailingMetadataReady(GRPC_ERROR_REF(error), &closures); + // If there are deferred recv_initial_metadata_ready or recv_message_ready + // callbacks, add them to closures. + AddClosuresForDeferredRecvCallbacks(&closures); + // Add closures to fail any pending batches that have not yet been started. + AddClosuresToFailUnstartedPendingBatches(GRPC_ERROR_REF(error), &closures); + // Schedule all of the closures identified above. + // Note: This will release the call combiner. + closures.RunClosures(call_attempt_->calld_->call_combiner_); + // Don't need batch_data anymore. + Unref(); + GRPC_ERROR_UNREF(error); +} + +void RetryFilter::CallData::CallAttempt::BatchData::RecvTrailingMetadataReady( + void* arg, grpc_error_handle error) { + CallAttempt::BatchData* batch_data = + static_cast(arg); + CallAttempt* call_attempt = batch_data->call_attempt_.get(); + CallData* calld = call_attempt->calld_; + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: got recv_trailing_metadata_ready, error=%s", + calld->chand_, calld, grpc_error_std_string(error).c_str()); + } + call_attempt->completed_recv_trailing_metadata_ = true; + // Get the call's status and check for server pushback metadata. + grpc_status_code status = GRPC_STATUS_OK; + grpc_mdelem* server_pushback_md = nullptr; + grpc_metadata_batch* md_batch = + batch_data->batch_.payload->recv_trailing_metadata.recv_trailing_metadata; + bool is_lb_drop = false; + GetCallStatus(calld->deadline_, md_batch, GRPC_ERROR_REF(error), &status, + &server_pushback_md, &is_lb_drop); + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log( + GPR_INFO, "chand=%p calld=%p: call finished, status=%s is_lb_drop=%d", + calld->chand_, calld, grpc_status_code_to_string(status), is_lb_drop); + } + // Check if we should retry. + if (batch_data->MaybeRetry(status, server_pushback_md, is_lb_drop)) { + // Unref batch_data for deferred recv_initial_metadata_ready or + // recv_message_ready callbacks, if any. + if (call_attempt->recv_initial_metadata_ready_deferred_batch_ != nullptr) { + GRPC_ERROR_UNREF(call_attempt->recv_initial_metadata_error_); + batch_data->Unref(); + } + if (call_attempt->recv_message_ready_deferred_batch_ != nullptr) { + GRPC_ERROR_UNREF(call_attempt->recv_message_error_); + batch_data->Unref(); + } + batch_data->Unref(); + return; + } + // Not retrying, so commit the call. + calld->RetryCommit(call_attempt); + // Run any necessary closures. + batch_data->RunClosuresForCompletedCall(GRPC_ERROR_REF(error)); +} + +// +// on_complete callback handling +// + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddClosuresForCompletedPendingBatch(grpc_error_handle error, + CallCombinerClosureList* closures) { + auto* calld = call_attempt_->calld_; + PendingBatch* pending = calld->PendingBatchFind( + "completed", [this](grpc_transport_stream_op_batch* batch) { + // Match the pending batch with the same set of send ops as the + // batch we've just completed. + return batch->on_complete != nullptr && + batch_.send_initial_metadata == batch->send_initial_metadata && + batch_.send_message == batch->send_message && + batch_.send_trailing_metadata == batch->send_trailing_metadata; + }); + // If batch_data is a replay batch, then there will be no pending + // batch to complete. + if (pending == nullptr) { + GRPC_ERROR_UNREF(error); + return; + } + // Add closure. + closures->Add(pending->batch->on_complete, error, + "on_complete for pending batch"); + pending->batch->on_complete = nullptr; + calld->MaybeClearPendingBatch(pending); +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddClosuresForReplayOrPendingSendOps(CallCombinerClosureList* closures) { + auto* calld = call_attempt_->calld_; + // We don't check send_initial_metadata here, because that op will always + // be started as soon as it is received from the surface, so it will + // never need to be started at this point. + bool have_pending_send_message_ops = + call_attempt_->started_send_message_count_ < calld->send_messages_.size(); + bool have_pending_send_trailing_metadata_op = + calld->seen_send_trailing_metadata_ && + !call_attempt_->started_send_trailing_metadata_; + if (!have_pending_send_message_ops && + !have_pending_send_trailing_metadata_op) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches_); ++i) { + PendingBatch* pending = &calld->pending_batches_[i]; + grpc_transport_stream_op_batch* batch = pending->batch; + if (batch == nullptr || pending->send_ops_cached) continue; + if (batch->send_message) have_pending_send_message_ops = true; + if (batch->send_trailing_metadata) { + have_pending_send_trailing_metadata_op = true; + } + } + } + if (have_pending_send_message_ops || have_pending_send_trailing_metadata_op) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: starting next batch for pending send op(s)", + calld->chand_, calld); + } + call_attempt_->AddRetriableBatches(closures); + } +} + +void RetryFilter::CallData::CallAttempt::BatchData::OnComplete( + void* arg, grpc_error_handle error) { + CallAttempt::BatchData* batch_data = + static_cast(arg); + CallAttempt* call_attempt = batch_data->call_attempt_.get(); + CallData* calld = call_attempt->calld_; + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: got on_complete, error=%s, batch=%s", + calld->chand_, calld, grpc_error_std_string(error).c_str(), + grpc_transport_stream_op_batch_string(&batch_data->batch_).c_str()); + } + // Update bookkeeping in call_attempt. + if (batch_data->batch_.send_initial_metadata) { + call_attempt->completed_send_initial_metadata_ = true; + } + if (batch_data->batch_.send_message) { + ++call_attempt->completed_send_message_count_; + } + if (batch_data->batch_.send_trailing_metadata) { + call_attempt->completed_send_trailing_metadata_ = true; + } + // If the call is committed, free cached data for send ops that we've just + // completed. + if (calld->retry_committed_) { + batch_data->FreeCachedSendOpDataForCompletedBatch(); + } + // Construct list of closures to execute. + CallCombinerClosureList closures; + // If a retry was already dispatched, that means we saw + // recv_trailing_metadata before this, so we do nothing here. + // Otherwise, invoke the callback to return the result to the surface. + if (!call_attempt->retry_dispatched_) { + // Add closure for the completed pending batch, if any. + batch_data->AddClosuresForCompletedPendingBatch(GRPC_ERROR_REF(error), + &closures); + // If needed, add a callback to start any replay or pending send ops on + // the LB call. + if (!call_attempt->completed_recv_trailing_metadata_) { + batch_data->AddClosuresForReplayOrPendingSendOps(&closures); + } + } + // Track number of in-flight send batches and determine if this was the + // last one. + --calld->num_in_flight_call_attempt_send_batches_; + const bool last_send_batch_complete = + calld->num_in_flight_call_attempt_send_batches_ == 0; + // Don't need batch_data anymore. + batch_data->Unref(); + // Schedule all of the closures identified above. + // Note: This yields the call combiner. + closures.RunClosures(calld->call_combiner_); + // If this was the last in-flight send batch, unref the call stack. + if (last_send_batch_complete) { + GRPC_CALL_STACK_UNREF(calld->owning_call_, "retriable_send_batches"); + } +} + +// +// retriable batch construction +// + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddRetriableSendInitialMetadataOp() { + auto* calld = call_attempt_->calld_; + // Maps the number of retries to the corresponding metadata value slice. + const grpc_slice* retry_count_strings[] = {&GRPC_MDSTR_1, &GRPC_MDSTR_2, + &GRPC_MDSTR_3, &GRPC_MDSTR_4}; + // We need to make a copy of the metadata batch for each attempt, since + // the filters in the subchannel stack may modify this batch, and we don't + // want those modifications to be passed forward to subsequent attempts. + // + // If we've already completed one or more attempts, add the + // grpc-retry-attempts header. + call_attempt_->send_initial_metadata_storage_ = + static_cast( + calld->arena_->Alloc(sizeof(grpc_linked_mdelem) * + (calld->send_initial_metadata_.list.count + + (calld->num_attempts_completed_ > 0)))); + grpc_metadata_batch_copy(&calld->send_initial_metadata_, + &call_attempt_->send_initial_metadata_, + call_attempt_->send_initial_metadata_storage_); + if (GPR_UNLIKELY(call_attempt_->send_initial_metadata_.idx.named + .grpc_previous_rpc_attempts != nullptr)) { + grpc_metadata_batch_remove(&call_attempt_->send_initial_metadata_, + GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS); + } + if (GPR_UNLIKELY(calld->num_attempts_completed_ > 0)) { + grpc_mdelem retry_md = grpc_mdelem_create( + GRPC_MDSTR_GRPC_PREVIOUS_RPC_ATTEMPTS, + *retry_count_strings[calld->num_attempts_completed_ - 1], nullptr); + grpc_error_handle error = grpc_metadata_batch_add_tail( + &call_attempt_->send_initial_metadata_, + &call_attempt_->send_initial_metadata_storage_ + [calld->send_initial_metadata_.list.count], + retry_md, GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS); + if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { + gpr_log(GPR_ERROR, "error adding retry metadata: %s", + grpc_error_std_string(error).c_str()); + GPR_ASSERT(false); + } + } + call_attempt_->started_send_initial_metadata_ = true; + batch_.send_initial_metadata = true; + batch_.payload->send_initial_metadata.send_initial_metadata = + &call_attempt_->send_initial_metadata_; + batch_.payload->send_initial_metadata.send_initial_metadata_flags = + calld->send_initial_metadata_flags_; + batch_.payload->send_initial_metadata.peer_string = calld->peer_string_; +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddRetriableSendMessageOp() { + auto* calld = call_attempt_->calld_; + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: starting calld->send_messages[%" PRIuPTR "]", + calld->chand_, calld, call_attempt_->started_send_message_count_); + } + ByteStreamCache* cache = + calld->send_messages_[call_attempt_->started_send_message_count_]; + ++call_attempt_->started_send_message_count_; + call_attempt_->send_message_.Init(cache); + batch_.send_message = true; + batch_.payload->send_message.send_message.reset( + call_attempt_->send_message_.get()); +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddRetriableSendTrailingMetadataOp() { + auto* calld = call_attempt_->calld_; + // We need to make a copy of the metadata batch for each attempt, since + // the filters in the subchannel stack may modify this batch, and we don't + // want those modifications to be passed forward to subsequent attempts. + call_attempt_->send_trailing_metadata_storage_ = + static_cast( + calld->arena_->Alloc(sizeof(grpc_linked_mdelem) * + calld->send_trailing_metadata_.list.count)); + grpc_metadata_batch_copy(&calld->send_trailing_metadata_, + &call_attempt_->send_trailing_metadata_, + call_attempt_->send_trailing_metadata_storage_); + call_attempt_->started_send_trailing_metadata_ = true; + batch_.send_trailing_metadata = true; + batch_.payload->send_trailing_metadata.send_trailing_metadata = + &call_attempt_->send_trailing_metadata_; +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddRetriableRecvInitialMetadataOp() { + call_attempt_->started_recv_initial_metadata_ = true; + batch_.recv_initial_metadata = true; + grpc_metadata_batch_init(&call_attempt_->recv_initial_metadata_); + batch_.payload->recv_initial_metadata.recv_initial_metadata = + &call_attempt_->recv_initial_metadata_; + batch_.payload->recv_initial_metadata.trailing_metadata_available = + &call_attempt_->trailing_metadata_available_; + GRPC_CLOSURE_INIT(&call_attempt_->recv_initial_metadata_ready_, + RecvInitialMetadataReady, this, grpc_schedule_on_exec_ctx); + batch_.payload->recv_initial_metadata.recv_initial_metadata_ready = + &call_attempt_->recv_initial_metadata_ready_; +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddRetriableRecvMessageOp() { + ++call_attempt_->started_recv_message_count_; + batch_.recv_message = true; + batch_.payload->recv_message.recv_message = &call_attempt_->recv_message_; + GRPC_CLOSURE_INIT(&call_attempt_->recv_message_ready_, RecvMessageReady, this, + grpc_schedule_on_exec_ctx); + batch_.payload->recv_message.recv_message_ready = + &call_attempt_->recv_message_ready_; +} + +void RetryFilter::CallData::CallAttempt::BatchData:: + AddRetriableRecvTrailingMetadataOp() { + call_attempt_->started_recv_trailing_metadata_ = true; + batch_.recv_trailing_metadata = true; + grpc_metadata_batch_init(&call_attempt_->recv_trailing_metadata_); + batch_.payload->recv_trailing_metadata.recv_trailing_metadata = + &call_attempt_->recv_trailing_metadata_; + batch_.payload->recv_trailing_metadata.collect_stats = + &call_attempt_->collect_stats_; + GRPC_CLOSURE_INIT(&call_attempt_->recv_trailing_metadata_ready_, + RecvTrailingMetadataReady, this, grpc_schedule_on_exec_ctx); + batch_.payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &call_attempt_->recv_trailing_metadata_ready_; +} + +// +// CallData vtable functions +// + +grpc_error_handle RetryFilter::CallData::Init( + grpc_call_element* elem, const grpc_call_element_args* args) { + auto* chand = static_cast(elem->channel_data); + new (elem->call_data) CallData(chand, *args); + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p: created call=%p", chand, elem->call_data); + } + return GRPC_ERROR_NONE; +} + +void RetryFilter::CallData::Destroy(grpc_call_element* elem, + const grpc_call_final_info* /*final_info*/, + grpc_closure* then_schedule_closure) { + auto* calld = static_cast(elem->call_data); + // Save our ref to the CallStackDestructionBarrier until after our + // dtor is invoked. + RefCountedPtr call_stack_destruction_barrier = + std::move(calld->call_stack_destruction_barrier_); + calld->~CallData(); + // Now set the callback in the CallStackDestructionBarrier object, + // right before we release our ref to it (implicitly upon returning). + // The callback will be invoked when the CallStackDestructionBarrier + // is destroyed. + call_stack_destruction_barrier->set_on_call_stack_destruction( + then_schedule_closure); +} + +void RetryFilter::CallData::StartTransportStreamOpBatch( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + auto* calld = static_cast(elem->call_data); + calld->StartTransportStreamOpBatch(batch); +} + +void RetryFilter::CallData::SetPollent(grpc_call_element* elem, + grpc_polling_entity* pollent) { + auto* calld = static_cast(elem->call_data); + calld->pollent_ = pollent; +} + +// +// CallData implementation +// + +const RetryMethodConfig* GetRetryPolicy( + const grpc_call_context_element* context) { + if (context == nullptr) return nullptr; + auto* svc_cfg_call_data = static_cast( + context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value); + if (svc_cfg_call_data == nullptr) return nullptr; + return static_cast( + svc_cfg_call_data->GetMethodParsedConfig( + RetryServiceConfigParser::ParserIndex())); +} + +RetryFilter::CallData::CallData(RetryFilter* chand, + const grpc_call_element_args& args) + : chand_(chand), + retry_throttle_data_(chand->retry_throttle_data_), + retry_policy_(GetRetryPolicy(args.context)), + retry_backoff_( + BackOff::Options() + .set_initial_backoff(retry_policy_ == nullptr + ? 0 + : retry_policy_->initial_backoff()) + .set_multiplier(retry_policy_ == nullptr + ? 0 + : retry_policy_->backoff_multiplier()) + .set_jitter(RETRY_BACKOFF_JITTER) + .set_max_backoff( + retry_policy_ == nullptr ? 0 : retry_policy_->max_backoff())), + path_(grpc_slice_ref_internal(args.path)), + call_start_time_(args.start_time), + deadline_(args.deadline), + arena_(args.arena), + owning_call_(args.call_stack), + call_combiner_(args.call_combiner), + call_context_(args.context), + call_stack_destruction_barrier_( + arena_->New()), + pending_send_initial_metadata_(false), + pending_send_message_(false), + pending_send_trailing_metadata_(false), + retry_committed_(false), + last_attempt_got_server_pushback_(false) {} + +RetryFilter::CallData::~CallData() { + grpc_slice_unref_internal(path_); + // Make sure there are no remaining pending batches. + for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { + GPR_ASSERT(pending_batches_[i].batch == nullptr); + } +} + +void RetryFilter::CallData::StartTransportStreamOpBatch( + grpc_transport_stream_op_batch* batch) { + // If we have an LB call, delegate to the LB call. + if (committed_call_ != nullptr) { + // Note: This will release the call combiner. + committed_call_->StartTransportStreamOpBatch(batch); + return; + } + // Handle cancellation. + if (GPR_UNLIKELY(batch->cancel_stream)) { + grpc_error_handle cancel_error = batch->payload->cancel_stream.cancel_error; + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: cancelled from surface: %s", chand_, + this, grpc_error_std_string(cancel_error).c_str()); + } + // If we have a current call attempt, commit the call, then send + // the cancellation down to that attempt. When the call fails, it + // will not be retried, because we have committed it here. + if (call_attempt_ != nullptr) { + RetryCommit(call_attempt_.get()); + // Note: This will release the call combiner. + call_attempt_->lb_call()->StartTransportStreamOpBatch(batch); + return; + } + // Fail pending batches. + PendingBatchesFail(GRPC_ERROR_REF(cancel_error)); + // Note: This will release the call combiner. + grpc_transport_stream_op_batch_finish_with_failure( + batch, GRPC_ERROR_REF(cancel_error), call_combiner_); + return; + } + // Add the batch to the pending list. + PendingBatch* pending = PendingBatchesAdd(batch); + if (call_attempt_ == nullptr) { + // If this is the first batch and retries are already committed + // (e.g., if this batch put the call above the buffer size limit), then + // immediately create an LB call and delegate the batch to it. This + // avoids the overhead of unnecessarily allocating a CallAttempt + // object or caching any of the send op data. + if (num_attempts_completed_ == 0 && retry_committed_) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: retry committed before first attempt; " + "creating LB call", + chand_, this); + } + PendingBatchClear(pending); + committed_call_ = CreateLoadBalancedCall(); + committed_call_->StartTransportStreamOpBatch(batch); + return; + } + // We do not yet have a call attempt, so create one. + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: creating call attempt", chand_, + this); + } + CreateCallAttempt(); + return; + } + // Send batches to call attempt. + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: starting batch on attempt=%p lb_call=%p", + chand_, this, call_attempt_.get(), call_attempt_->lb_call()); + } + call_attempt_->StartRetriableBatches(); +} + +RefCountedPtr +RetryFilter::CallData::CreateLoadBalancedCall() { + grpc_call_element_args args = {owning_call_, nullptr, call_context_, + path_, call_start_time_, deadline_, + arena_, call_combiner_}; + return chand_->client_channel_->CreateLoadBalancedCall( + args, pollent_, + // This callback holds a ref to the CallStackDestructionBarrier + // object until the LB call is destroyed. + call_stack_destruction_barrier_->MakeLbCallDestructionClosure(this)); +} + +void RetryFilter::CallData::CreateCallAttempt() { + call_attempt_.reset(arena_->New(this)); + call_attempt_->StartRetriableBatches(); + // TODO(roth): When implementing hedging, change this to start a timer + // for the next hedging attempt. +} + +namespace { + +void StartBatchInCallCombiner(void* arg, grpc_error_handle /*ignored*/) { + grpc_transport_stream_op_batch* batch = + static_cast(arg); + auto* lb_call = static_cast( + batch->handler_private.extra_arg); + // Note: This will release the call combiner. + lb_call->StartTransportStreamOpBatch(batch); +} + +} // namespace + +void RetryFilter::CallData::AddClosureForBatch( + grpc_transport_stream_op_batch* batch, CallCombinerClosureList* closures) { + batch->handler_private.extra_arg = call_attempt_->lb_call(); + GRPC_CLOSURE_INIT(&batch->handler_private.closure, StartBatchInCallCombiner, + batch, grpc_schedule_on_exec_ctx); + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: starting batch on LB call: %s", + chand_, this, grpc_transport_stream_op_batch_string(batch).c_str()); + } + closures->Add(&batch->handler_private.closure, GRPC_ERROR_NONE, + "start_batch_on_lb_call"); +} + +// +// send op data caching +// + +void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) { + if (pending->send_ops_cached) return; + pending->send_ops_cached = true; + grpc_transport_stream_op_batch* batch = pending->batch; + // Save a copy of metadata for send_initial_metadata ops. + if (batch->send_initial_metadata) { + seen_send_initial_metadata_ = true; + GPR_ASSERT(send_initial_metadata_storage_ == nullptr); + grpc_metadata_batch* send_initial_metadata = + batch->payload->send_initial_metadata.send_initial_metadata; + send_initial_metadata_storage_ = + static_cast(arena_->Alloc( + sizeof(grpc_linked_mdelem) * send_initial_metadata->list.count)); + grpc_metadata_batch_copy(send_initial_metadata, &send_initial_metadata_, + send_initial_metadata_storage_); + send_initial_metadata_flags_ = + batch->payload->send_initial_metadata.send_initial_metadata_flags; + peer_string_ = batch->payload->send_initial_metadata.peer_string; + } + // Set up cache for send_message ops. + if (batch->send_message) { + ByteStreamCache* cache = arena_->New( + std::move(batch->payload->send_message.send_message)); + send_messages_.push_back(cache); + } + // Save metadata batch for send_trailing_metadata ops. + if (batch->send_trailing_metadata) { + seen_send_trailing_metadata_ = true; + GPR_ASSERT(send_trailing_metadata_storage_ == nullptr); + grpc_metadata_batch* send_trailing_metadata = + batch->payload->send_trailing_metadata.send_trailing_metadata; + send_trailing_metadata_storage_ = + static_cast(arena_->Alloc( + sizeof(grpc_linked_mdelem) * send_trailing_metadata->list.count)); + grpc_metadata_batch_copy(send_trailing_metadata, &send_trailing_metadata_, + send_trailing_metadata_storage_); + } +} + +void RetryFilter::CallData::FreeCachedSendInitialMetadata() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: destroying send_initial_metadata", + chand_, this); + } + grpc_metadata_batch_destroy(&send_initial_metadata_); +} + +void RetryFilter::CallData::FreeCachedSendMessage(size_t idx) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: destroying send_messages[%" PRIuPTR "]", chand_, + this, idx); + } + send_messages_[idx]->Destroy(); +} + +void RetryFilter::CallData::FreeCachedSendTrailingMetadata() { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand_=%p calld=%p: destroying send_trailing_metadata", + chand_, this); + } + grpc_metadata_batch_destroy(&send_trailing_metadata_); +} + +void RetryFilter::CallData::FreeAllCachedSendOpData() { + if (seen_send_initial_metadata_) { + FreeCachedSendInitialMetadata(); + } + for (size_t i = 0; i < send_messages_.size(); ++i) { + FreeCachedSendMessage(i); + } + if (seen_send_trailing_metadata_) { + FreeCachedSendTrailingMetadata(); + } +} + +// +// pending_batches management +// + +size_t RetryFilter::CallData::GetBatchIndex( + grpc_transport_stream_op_batch* batch) { + if (batch->send_initial_metadata) return 0; + if (batch->send_message) return 1; + if (batch->send_trailing_metadata) return 2; + if (batch->recv_initial_metadata) return 3; + if (batch->recv_message) return 4; + if (batch->recv_trailing_metadata) return 5; + GPR_UNREACHABLE_CODE(return (size_t)-1); +} + +// This is called via the call combiner, so access to calld is synchronized. +RetryFilter::CallData::PendingBatch* RetryFilter::CallData::PendingBatchesAdd( + grpc_transport_stream_op_batch* batch) { + const size_t idx = GetBatchIndex(batch); + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand_=%p calld=%p: adding pending batch at index %" PRIuPTR, + chand_, this, idx); + } + PendingBatch* pending = &pending_batches_[idx]; + GPR_ASSERT(pending->batch == nullptr); + pending->batch = batch; + pending->send_ops_cached = false; + // Update state in calld about pending batches. + // Also check if the batch takes us over the retry buffer limit. + // Note: We don't check the size of trailing metadata here, because + // gRPC clients do not send trailing metadata. + if (batch->send_initial_metadata) { + pending_send_initial_metadata_ = true; + bytes_buffered_for_retry_ += grpc_metadata_batch_size( + batch->payload->send_initial_metadata.send_initial_metadata); + } + if (batch->send_message) { + pending_send_message_ = true; + bytes_buffered_for_retry_ += + batch->payload->send_message.send_message->length(); + } + if (batch->send_trailing_metadata) { + pending_send_trailing_metadata_ = true; + } + if (GPR_UNLIKELY(bytes_buffered_for_retry_ > + chand_->per_rpc_retry_buffer_size_)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: exceeded retry buffer size, committing", + chand_, this); + } + RetryCommit(call_attempt_.get()); + } + return pending; +} + +void RetryFilter::CallData::PendingBatchClear(PendingBatch* pending) { + if (pending->batch->send_initial_metadata) { + pending_send_initial_metadata_ = false; + } + if (pending->batch->send_message) { + pending_send_message_ = false; + } + if (pending->batch->send_trailing_metadata) { + pending_send_trailing_metadata_ = false; + } + pending->batch = nullptr; +} + +void RetryFilter::CallData::MaybeClearPendingBatch(PendingBatch* pending) { + grpc_transport_stream_op_batch* batch = pending->batch; + // We clear the pending batch if all of its callbacks have been + // scheduled and reset to nullptr. + if (batch->on_complete == nullptr && + (!batch->recv_initial_metadata || + batch->payload->recv_initial_metadata.recv_initial_metadata_ready == + nullptr) && + (!batch->recv_message || + batch->payload->recv_message.recv_message_ready == nullptr) && + (!batch->recv_trailing_metadata || + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready == + nullptr)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: clearing pending batch", chand_, + this); + } + PendingBatchClear(pending); + } +} + +// This is called via the call combiner, so access to calld is synchronized. +void RetryFilter::CallData::FailPendingBatchInCallCombiner( + void* arg, grpc_error_handle error) { + grpc_transport_stream_op_batch* batch = + static_cast(arg); + CallData* call = static_cast(batch->handler_private.extra_arg); + // Note: This will release the call combiner. + grpc_transport_stream_op_batch_finish_with_failure( + batch, GRPC_ERROR_REF(error), call->call_combiner_); +} + +// This is called via the call combiner, so access to calld is synchronized. +void RetryFilter::CallData::PendingBatchesFail(grpc_error_handle error) { + GPR_ASSERT(error != GRPC_ERROR_NONE); + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + size_t num_batches = 0; + for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { + if (pending_batches_[i].batch != nullptr) ++num_batches; + } + gpr_log(GPR_INFO, + "chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s", + chand_, this, num_batches, grpc_error_std_string(error).c_str()); + } + CallCombinerClosureList closures; + for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { + PendingBatch* pending = &pending_batches_[i]; + grpc_transport_stream_op_batch* batch = pending->batch; + if (batch != nullptr) { + batch->handler_private.extra_arg = this; + GRPC_CLOSURE_INIT(&batch->handler_private.closure, + FailPendingBatchInCallCombiner, batch, + grpc_schedule_on_exec_ctx); + closures.Add(&batch->handler_private.closure, GRPC_ERROR_REF(error), + "PendingBatchesFail"); + PendingBatchClear(pending); + } + } + closures.RunClosuresWithoutYielding(call_combiner_); + GRPC_ERROR_UNREF(error); +} + +template +RetryFilter::CallData::PendingBatch* RetryFilter::CallData::PendingBatchFind( + const char* log_message, Predicate predicate) { + for (size_t i = 0; i < GPR_ARRAY_SIZE(pending_batches_); ++i) { + PendingBatch* pending = &pending_batches_[i]; + grpc_transport_stream_op_batch* batch = pending->batch; + if (batch != nullptr && predicate(batch)) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: %s pending batch at index %" PRIuPTR, + chand_, this, log_message, i); + } + return pending; + } + } + return nullptr; +} + +// +// retry code +// + +void RetryFilter::CallData::RetryCommit(CallAttempt* call_attempt) { + if (retry_committed_) return; + retry_committed_ = true; + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: committing retries", chand_, this); + } + if (call_attempt != nullptr) { + call_attempt->FreeCachedSendOpDataAfterCommit(); + } +} + +void RetryFilter::CallData::DoRetry(grpc_millis server_pushback_ms) { + // Reset call attempt. + call_attempt_.reset(); + // Compute backoff delay. + grpc_millis next_attempt_time; + if (server_pushback_ms >= 0) { + next_attempt_time = ExecCtx::Get()->Now() + server_pushback_ms; + last_attempt_got_server_pushback_ = true; + } else { + if (num_attempts_completed_ == 1 || last_attempt_got_server_pushback_) { + last_attempt_got_server_pushback_ = false; + } + next_attempt_time = retry_backoff_.NextAttemptTime(); + } + if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: retrying failed call in %" PRId64 " ms", chand_, + this, next_attempt_time - ExecCtx::Get()->Now()); + } + // Schedule retry after computed delay. + GRPC_CLOSURE_INIT(&retry_closure_, OnRetryTimer, this, nullptr); + GRPC_CALL_STACK_REF(owning_call_, "OnRetryTimer"); + MutexLock lock(&timer_mu_); + canceller_ = new Canceller(this); + grpc_timer_init(&retry_timer_, next_attempt_time, &retry_closure_); +} + +void RetryFilter::CallData::OnRetryTimer(void* arg, grpc_error_handle error) { + auto* calld = static_cast(arg); + if (error == GRPC_ERROR_NONE) { + bool start_attempt = false; + { + MutexLock lock(&calld->timer_mu_); + if (calld->canceller_ != nullptr) { + calld->canceller_ = nullptr; + start_attempt = true; + } + } + if (start_attempt) calld->CreateCallAttempt(); + } + GRPC_CALL_STACK_UNREF(calld->owning_call_, "OnRetryTimer"); +} + +} // namespace + +const grpc_channel_filter kRetryFilterVtable = { + RetryFilter::CallData::StartTransportStreamOpBatch, + RetryFilter::StartTransportOp, + sizeof(RetryFilter::CallData), + RetryFilter::CallData::Init, + RetryFilter::CallData::SetPollent, + RetryFilter::CallData::Destroy, + sizeof(RetryFilter), + RetryFilter::Init, + RetryFilter::Destroy, + RetryFilter::GetChannelInfo, + "retry_filter", +}; + +} // namespace grpc_core diff --git a/test/core/util/eval_args_mock_endpoint.h b/src/core/ext/filters/client_channel/retry_filter.h similarity index 56% rename from test/core/util/eval_args_mock_endpoint.h rename to src/core/ext/filters/client_channel/retry_filter.h index 68b32cc891e..a96df8af1fc 100644 --- a/test/core/util/eval_args_mock_endpoint.h +++ b/src/core/ext/filters/client_channel/retry_filter.h @@ -1,4 +1,5 @@ -// Copyright 2020 gRPC authors. +// +// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,21 +12,19 @@ // 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_TEST_CORE_UTIL_EVAL_ARGS_MOCK_ENDPOINT_H -#define GRPC_TEST_CORE_UTIL_EVAL_ARGS_MOCK_ENDPOINT_H +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_FILTER_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_FILTER_H #include -#include "src/core/lib/iomgr/endpoint.h" +#include "src/core/lib/channel/channel_stack.h" namespace grpc_core { -grpc_endpoint* CreateEvalArgsMockEndpoint(const char* local_address, - const int local_port, - const char* peer_address, - const int peer_port); +extern const grpc_channel_filter kRetryFilterVtable; } // namespace grpc_core -#endif // GRPC_TEST_CORE_UTIL_EVAL_ARGS_MOCK_ENDPOINT_H +#endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_FILTER_H diff --git a/src/core/ext/filters/client_channel/retry_service_config.cc b/src/core/ext/filters/client_channel/retry_service_config.cc new file mode 100644 index 00000000000..fc066e639c4 --- /dev/null +++ b/src/core/ext/filters/client_channel/retry_service_config.cc @@ -0,0 +1,287 @@ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "src/core/ext/filters/client_channel/retry_service_config.h" + +#include +#include +#include + +#include "absl/strings/str_cat.h" +#include "absl/types/optional.h" + +#include +#include +#include + +#include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/json/json_util.h" +#include "src/core/lib/uri/uri_parser.h" + +// As per the retry design, we do not allow more than 5 retry attempts. +#define MAX_MAX_RETRY_ATTEMPTS 5 + +namespace grpc_core { +namespace internal { + +namespace { +size_t g_retry_service_config_parser_index; +} + +size_t RetryServiceConfigParser::ParserIndex() { + return g_retry_service_config_parser_index; +} + +void RetryServiceConfigParser::Register() { + g_retry_service_config_parser_index = ServiceConfigParser::RegisterParser( + absl::make_unique()); +} + +namespace { + +grpc_error_handle ParseRetryThrottling(const Json& json, + intptr_t* max_milli_tokens, + intptr_t* milli_token_ratio) { + if (json.type() != Json::Type::OBJECT) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling error:Type should be object"); + } + std::vector error_list; + // Parse maxTokens. + auto it = json.object_value().find("maxTokens"); + if (it == json.object_value().end()) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:maxTokens error:Not found")); + } else if (it->second.type() != Json::Type::NUMBER) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:maxTokens error:Type should be " + "number")); + } else { + *max_milli_tokens = + gpr_parse_nonnegative_int(it->second.string_value().c_str()) * 1000; + if (*max_milli_tokens <= 0) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:maxTokens error:should be " + "greater than zero")); + } + } + // Parse tokenRatio. + it = json.object_value().find("tokenRatio"); + if (it == json.object_value().end()) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:tokenRatio error:Not found")); + } else if (it->second.type() != Json::Type::NUMBER) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:tokenRatio error:type should be " + "number")); + } else { + // We support up to 3 decimal digits. + size_t whole_len = it->second.string_value().size(); + const char* value = it->second.string_value().c_str(); + uint32_t multiplier = 1; + uint32_t decimal_value = 0; + const char* decimal_point = strchr(value, '.'); + if (decimal_point != nullptr) { + whole_len = static_cast(decimal_point - value); + multiplier = 1000; + size_t decimal_len = strlen(decimal_point + 1); + if (decimal_len > 3) decimal_len = 3; + if (!gpr_parse_bytes_to_uint32(decimal_point + 1, decimal_len, + &decimal_value)) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:tokenRatio error:Failed " + "parsing")); + return GRPC_ERROR_CREATE_FROM_VECTOR("retryThrottling", &error_list); + } + uint32_t decimal_multiplier = 1; + for (size_t i = 0; i < (3 - decimal_len); ++i) { + decimal_multiplier *= 10; + } + decimal_value *= decimal_multiplier; + } + uint32_t whole_value; + if (!gpr_parse_bytes_to_uint32(value, whole_len, &whole_value)) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:tokenRatio error:Failed " + "parsing")); + return GRPC_ERROR_CREATE_FROM_VECTOR("retryThrottling", &error_list); + } + *milli_token_ratio = + static_cast((whole_value * multiplier) + decimal_value); + if (*milli_token_ratio <= 0) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryThrottling field:tokenRatio error:value should " + "be greater than 0")); + } + } + return GRPC_ERROR_CREATE_FROM_VECTOR("retryThrottling", &error_list); +} + +} // namespace + +std::unique_ptr +RetryServiceConfigParser::ParseGlobalParams(const grpc_channel_args* /*args*/, + const Json& json, + grpc_error_handle* error) { + GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); + auto it = json.object_value().find("retryThrottling"); + if (it == json.object_value().end()) return nullptr; + intptr_t max_milli_tokens = 0; + intptr_t milli_token_ratio = 0; + *error = + ParseRetryThrottling(it->second, &max_milli_tokens, &milli_token_ratio); + if (*error != GRPC_ERROR_NONE) return nullptr; + return absl::make_unique(max_milli_tokens, + milli_token_ratio); +} + +namespace { + +grpc_error_handle ParseRetryPolicy(const Json& json, int* max_attempts, + grpc_millis* initial_backoff, + grpc_millis* max_backoff, + float* backoff_multiplier, + StatusCodeSet* retryable_status_codes) { + if (json.type() != Json::Type::OBJECT) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryPolicy error:should be of type object"); + } + std::vector error_list; + // Parse maxAttempts. + auto it = json.object_value().find("maxAttempts"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::NUMBER) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:maxAttempts error:should be of type number")); + } else { + *max_attempts = + gpr_parse_nonnegative_int(it->second.string_value().c_str()); + if (*max_attempts <= 1) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:maxAttempts error:should be at least 2")); + } else if (*max_attempts > MAX_MAX_RETRY_ATTEMPTS) { + gpr_log(GPR_ERROR, + "service config: clamped retryPolicy.maxAttempts at %d", + MAX_MAX_RETRY_ATTEMPTS); + *max_attempts = MAX_MAX_RETRY_ATTEMPTS; + } + } + } + // Parse initialBackoff. + if (ParseJsonObjectFieldAsDuration(json.object_value(), "initialBackoff", + initial_backoff, &error_list) && + *initial_backoff == 0) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:initialBackoff error:must be greater than 0")); + } + // Parse maxBackoff. + if (ParseJsonObjectFieldAsDuration(json.object_value(), "maxBackoff", + max_backoff, &error_list) && + *max_backoff == 0) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:maxBackoff error:should be greater than 0")); + } + // Parse backoffMultiplier. + it = json.object_value().find("backoffMultiplier"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::NUMBER) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:backoffMultiplier error:should be of type number")); + } else { + if (sscanf(it->second.string_value().c_str(), "%f", backoff_multiplier) != + 1) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:backoffMultiplier error:failed to parse")); + } else if (*backoff_multiplier <= 0) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:backoffMultiplier error:should be greater than 0")); + } + } + } + // Parse retryableStatusCodes. + it = json.object_value().find("retryableStatusCodes"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::ARRAY) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryableStatusCodes error:should be of type array")); + } else { + for (const Json& element : it->second.array_value()) { + if (element.type() != Json::Type::STRING) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryableStatusCodes error:status codes should be of type " + "string")); + continue; + } + grpc_status_code status; + if (!grpc_status_code_from_string(element.string_value().c_str(), + &status)) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryableStatusCodes error:failed to parse status code")); + continue; + } + retryable_status_codes->Add(status); + } + if (retryable_status_codes->Empty()) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryableStatusCodes error:should be non-empty")); + }; + } + } + // Make sure required fields are set. + if (error_list.empty()) { + if (*max_attempts == 0 || *initial_backoff == 0 || *max_backoff == 0 || + *backoff_multiplier == 0 || retryable_status_codes->Empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:retryPolicy error:Missing required field(s)"); + } + } + return GRPC_ERROR_CREATE_FROM_VECTOR("retryPolicy", &error_list); +} + +} // namespace + +std::unique_ptr +RetryServiceConfigParser::ParsePerMethodParams( + const grpc_channel_args* /*args*/, const Json& json, + grpc_error_handle* error) { + GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); + // Parse retry policy. + auto it = json.object_value().find("retryPolicy"); + if (it == json.object_value().end()) return nullptr; + int max_attempts = 0; + grpc_millis initial_backoff = 0; + grpc_millis max_backoff = 0; + float backoff_multiplier = 0; + StatusCodeSet retryable_status_codes; + *error = ParseRetryPolicy(it->second, &max_attempts, &initial_backoff, + &max_backoff, &backoff_multiplier, + &retryable_status_codes); + if (*error != GRPC_ERROR_NONE) return nullptr; + return absl::make_unique(max_attempts, initial_backoff, + max_backoff, backoff_multiplier, + retryable_status_codes); +} + +} // namespace internal +} // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/retry_service_config.h b/src/core/ext/filters/client_channel/retry_service_config.h new file mode 100644 index 00000000000..256183f26eb --- /dev/null +++ b/src/core/ext/filters/client_channel/retry_service_config.h @@ -0,0 +1,90 @@ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_SERVICE_CONFIG_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_SERVICE_CONFIG_H + +#include + +#include + +#include "src/core/ext/filters/client_channel/retry_throttle.h" +#include "src/core/ext/filters/client_channel/service_config_parser.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis + +namespace grpc_core { +namespace internal { + +class RetryGlobalConfig : public ServiceConfigParser::ParsedConfig { + public: + RetryGlobalConfig(intptr_t max_milli_tokens, intptr_t milli_token_ratio) + : max_milli_tokens_(max_milli_tokens), + milli_token_ratio_(milli_token_ratio) {} + + intptr_t max_milli_tokens() const { return max_milli_tokens_; } + intptr_t milli_token_ratio() const { return milli_token_ratio_; } + + private: + intptr_t max_milli_tokens_ = 0; + intptr_t milli_token_ratio_ = 0; +}; + +class RetryMethodConfig : public ServiceConfigParser::ParsedConfig { + public: + RetryMethodConfig(int max_attempts, grpc_millis initial_backoff, + grpc_millis max_backoff, float backoff_multiplier, + StatusCodeSet retryable_status_codes) + : max_attempts_(max_attempts), + initial_backoff_(initial_backoff), + max_backoff_(max_backoff), + backoff_multiplier_(backoff_multiplier), + retryable_status_codes_(retryable_status_codes) {} + + int max_attempts() const { return max_attempts_; } + grpc_millis initial_backoff() const { return initial_backoff_; } + grpc_millis max_backoff() const { return max_backoff_; } + float backoff_multiplier() const { return backoff_multiplier_; } + StatusCodeSet retryable_status_codes() const { + return retryable_status_codes_; + } + + private: + int max_attempts_ = 0; + grpc_millis initial_backoff_ = 0; + grpc_millis max_backoff_ = 0; + float backoff_multiplier_ = 0; + StatusCodeSet retryable_status_codes_; +}; + +class RetryServiceConfigParser : public ServiceConfigParser::Parser { + public: + std::unique_ptr ParseGlobalParams( + const grpc_channel_args* /*args*/, const Json& json, + grpc_error_handle* error) override; + + std::unique_ptr ParsePerMethodParams( + const grpc_channel_args* /*args*/, const Json& json, + grpc_error_handle* error) override; + + static size_t ParserIndex(); + static void Register(); +}; + +} // namespace internal +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_SERVICE_CONFIG_H diff --git a/src/core/ext/filters/client_channel/server_address.cc b/src/core/ext/filters/client_channel/server_address.cc index 89d7c90f79c..e082256b97b 100644 --- a/src/core/ext/filters/client_channel/server_address.cc +++ b/src/core/ext/filters/client_channel/server_address.cc @@ -27,7 +27,7 @@ #include "absl/strings/str_cat.h" #include "absl/strings/str_join.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" namespace grpc_core { @@ -61,6 +61,9 @@ ServerAddress::ServerAddress(const ServerAddress& other) } } ServerAddress& ServerAddress::operator=(const ServerAddress& other) { + if (&other == this) { + return *this; + } address_ = other.address_; grpc_channel_args_destroy(args_); args_ = grpc_channel_args_copy(other.args_); diff --git a/src/core/ext/filters/client_channel/service_config.cc b/src/core/ext/filters/client_channel/service_config.cc index a2794f19f44..b87226c6719 100644 --- a/src/core/ext/filters/client_channel/service_config.cc +++ b/src/core/ext/filters/client_channel/service_config.cc @@ -32,7 +32,7 @@ namespace grpc_core { RefCountedPtr ServiceConfig::Create( const grpc_channel_args* args, absl::string_view json_string, - grpc_error** error) { + grpc_error_handle* error) { GPR_DEBUG_ASSERT(error != nullptr); Json json = Json::Parse(json_string, error); if (*error != GRPC_ERROR_NONE) return nullptr; @@ -42,7 +42,7 @@ RefCountedPtr ServiceConfig::Create( ServiceConfig::ServiceConfig(const grpc_channel_args* args, std::string json_string, Json json, - grpc_error** error) + grpc_error_handle* error) : json_string_(std::move(json_string)), json_(std::move(json)) { GPR_DEBUG_ASSERT(error != nullptr); if (json_.type() != Json::Type::OBJECT) { @@ -50,12 +50,12 @@ ServiceConfig::ServiceConfig(const grpc_channel_args* args, GRPC_ERROR_CREATE_FROM_STATIC_STRING("JSON value is not an object"); return; } - std::vector error_list; - grpc_error* global_error = GRPC_ERROR_NONE; + std::vector error_list; + grpc_error_handle global_error = GRPC_ERROR_NONE; parsed_global_configs_ = ServiceConfigParser::ParseGlobalParameters(args, json_, &global_error); if (global_error != GRPC_ERROR_NONE) error_list.push_back(global_error); - grpc_error* local_error = ParsePerMethodParams(args); + grpc_error_handle local_error = ParsePerMethodParams(args); if (local_error != GRPC_ERROR_NONE) error_list.push_back(local_error); if (!error_list.empty()) { *error = GRPC_ERROR_CREATE_FROM_VECTOR("Service config parsing error", @@ -69,13 +69,13 @@ ServiceConfig::~ServiceConfig() { } } -grpc_error* ServiceConfig::ParseJsonMethodConfig(const grpc_channel_args* args, - const Json& json) { - std::vector error_list; +grpc_error_handle ServiceConfig::ParseJsonMethodConfig( + const grpc_channel_args* args, const Json& json) { + std::vector error_list; // Parse method config with each registered parser. auto parsed_configs = absl::make_unique(); - grpc_error* parser_error = GRPC_ERROR_NONE; + grpc_error_handle parser_error = GRPC_ERROR_NONE; *parsed_configs = ServiceConfigParser::ParsePerMethodParameters(args, json, &parser_error); if (parser_error != GRPC_ERROR_NONE) { @@ -94,7 +94,7 @@ grpc_error* ServiceConfig::ParseJsonMethodConfig(const grpc_channel_args* args, } const Json::Array& name_array = it->second.array_value(); for (const Json& name : name_array) { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; std::string path = ParseJsonMethodName(name, &parse_error); if (parse_error != GRPC_ERROR_NONE) { error_list.push_back(parse_error); @@ -130,8 +130,9 @@ grpc_error* ServiceConfig::ParseJsonMethodConfig(const grpc_channel_args* args, return GRPC_ERROR_CREATE_FROM_VECTOR("methodConfig", &error_list); } -grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_channel_args* args) { - std::vector error_list; +grpc_error_handle ServiceConfig::ParsePerMethodParams( + const grpc_channel_args* args) { + std::vector error_list; auto it = json_.object_value().find("methodConfig"); if (it != json_.object_value().end()) { if (it->second.type() != Json::Type::ARRAY) { @@ -144,7 +145,7 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_channel_args* args) { "field:methodConfig error:not of type Object")); continue; } - grpc_error* error = ParseJsonMethodConfig(args, method_config); + grpc_error_handle error = ParseJsonMethodConfig(args, method_config); if (error != GRPC_ERROR_NONE) { error_list.push_back(error); } @@ -154,7 +155,7 @@ grpc_error* ServiceConfig::ParsePerMethodParams(const grpc_channel_args* args) { } std::string ServiceConfig::ParseJsonMethodName(const Json& json, - grpc_error** error) { + grpc_error_handle* error) { if (json.type() != Json::Type::OBJECT) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "field:name error:type is not object"); diff --git a/src/core/ext/filters/client_channel/service_config.h b/src/core/ext/filters/client_channel/service_config.h index 2dfd45d8f6c..a06ae1626e8 100644 --- a/src/core/ext/filters/client_channel/service_config.h +++ b/src/core/ext/filters/client_channel/service_config.h @@ -67,10 +67,10 @@ class ServiceConfig : public RefCounted { /// Returns null on parse error. static RefCountedPtr Create(const grpc_channel_args* args, absl::string_view json_string, - grpc_error** error); + grpc_error_handle* error); ServiceConfig(const grpc_channel_args* args, std::string json_string, - Json json, grpc_error** error); + Json json, grpc_error_handle* error); ~ServiceConfig() override; const std::string& json_string() const { return json_string_; } @@ -91,13 +91,14 @@ class ServiceConfig : public RefCounted { private: // Helper functions for parsing the method configs. - grpc_error* ParsePerMethodParams(const grpc_channel_args* args); - grpc_error* ParseJsonMethodConfig(const grpc_channel_args* args, - const Json& json); + grpc_error_handle ParsePerMethodParams(const grpc_channel_args* args); + grpc_error_handle ParseJsonMethodConfig(const grpc_channel_args* args, + const Json& json); // Returns a path string for the JSON name object specified by json. // Sets *error on error. - static std::string ParseJsonMethodName(const Json& json, grpc_error** error); + static std::string ParseJsonMethodName(const Json& json, + grpc_error_handle* error); std::string json_string_; Json json_; diff --git a/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc b/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc index 679c0f572c2..5763e17d8fb 100644 --- a/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +++ b/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc @@ -36,13 +36,14 @@ class ServiceConfigChannelArgChannelData { const char* service_config_str = grpc_channel_args_find_string( args->channel_args, GRPC_ARG_SERVICE_CONFIG); if (service_config_str != nullptr) { - grpc_error* service_config_error = GRPC_ERROR_NONE; + grpc_error_handle service_config_error = GRPC_ERROR_NONE; auto service_config = ServiceConfig::Create( args->channel_args, service_config_str, &service_config_error); if (service_config_error == GRPC_ERROR_NONE) { service_config_ = std::move(service_config); } else { - gpr_log(GPR_ERROR, "%s", grpc_error_string(service_config_error)); + gpr_log(GPR_ERROR, "%s", + grpc_error_std_string(service_config_error).c_str()); } GRPC_ERROR_UNREF(service_config_error); } @@ -73,7 +74,7 @@ class ServiceConfigChannelArgCallData { } }; -grpc_error* ServiceConfigChannelArgInitCallElem( +grpc_error_handle ServiceConfigChannelArgInitCallElem( grpc_call_element* elem, const grpc_call_element_args* args) { ServiceConfigChannelArgCallData* calld = static_cast(elem->call_data); @@ -89,7 +90,7 @@ void ServiceConfigChannelArgDestroyCallElem( calld->~ServiceConfigChannelArgCallData(); } -grpc_error* ServiceConfigChannelArgInitChannelElem( +grpc_error_handle ServiceConfigChannelArgInitChannelElem( grpc_channel_element* elem, grpc_channel_element_args* args) { ServiceConfigChannelArgChannelData* chand = static_cast(elem->channel_data); diff --git a/src/core/ext/filters/client_channel/service_config_parser.cc b/src/core/ext/filters/client_channel/service_config_parser.cc index d116f3115f9..fa8fbea68f3 100644 --- a/src/core/ext/filters/client_channel/service_config_parser.cc +++ b/src/core/ext/filters/client_channel/service_config_parser.cc @@ -47,11 +47,11 @@ size_t ServiceConfigParser::RegisterParser(std::unique_ptr parser) { ServiceConfigParser::ParsedConfigVector ServiceConfigParser::ParseGlobalParameters(const grpc_channel_args* args, const Json& json, - grpc_error** error) { + grpc_error_handle* error) { ParsedConfigVector parsed_global_configs; - std::vector error_list; + std::vector error_list; for (size_t i = 0; i < g_registered_parsers->size(); i++) { - grpc_error* parser_error = GRPC_ERROR_NONE; + grpc_error_handle parser_error = GRPC_ERROR_NONE; auto parsed_config = (*g_registered_parsers)[i]->ParseGlobalParams( args, json, &parser_error); if (parser_error != GRPC_ERROR_NONE) { @@ -68,11 +68,11 @@ ServiceConfigParser::ParseGlobalParameters(const grpc_channel_args* args, ServiceConfigParser::ParsedConfigVector ServiceConfigParser::ParsePerMethodParameters(const grpc_channel_args* args, const Json& json, - grpc_error** error) { + grpc_error_handle* error) { ParsedConfigVector parsed_method_configs; - std::vector error_list; + std::vector error_list; for (size_t i = 0; i < g_registered_parsers->size(); i++) { - grpc_error* parser_error = GRPC_ERROR_NONE; + grpc_error_handle parser_error = GRPC_ERROR_NONE; auto parsed_config = (*g_registered_parsers)[i]->ParsePerMethodParams( args, json, &parser_error); if (parser_error != GRPC_ERROR_NONE) { diff --git a/src/core/ext/filters/client_channel/service_config_parser.h b/src/core/ext/filters/client_channel/service_config_parser.h index 692a920ec35..ebd31660742 100644 --- a/src/core/ext/filters/client_channel/service_config_parser.h +++ b/src/core/ext/filters/client_channel/service_config_parser.h @@ -47,7 +47,8 @@ class ServiceConfigParser { virtual ~Parser() = default; virtual std::unique_ptr ParseGlobalParams( - const grpc_channel_args*, const Json& /* json */, grpc_error** error) { + const grpc_channel_args*, const Json& /* json */, + grpc_error_handle* error) { // Avoid unused parameter warning on debug-only parameter (void)error; GPR_DEBUG_ASSERT(error != nullptr); @@ -55,7 +56,8 @@ class ServiceConfigParser { } virtual std::unique_ptr ParsePerMethodParams( - const grpc_channel_args*, const Json& /* json */, grpc_error** error) { + const grpc_channel_args*, const Json& /* json */, + grpc_error_handle* error) { // Avoid unused parameter warning on debug-only parameter (void)error; GPR_DEBUG_ASSERT(error != nullptr); @@ -81,10 +83,11 @@ class ServiceConfigParser { static ParsedConfigVector ParseGlobalParameters(const grpc_channel_args* args, const Json& json, - grpc_error** error); + grpc_error_handle* error); static ParsedConfigVector ParsePerMethodParameters( - const grpc_channel_args* args, const Json& json, grpc_error** error); + const grpc_channel_args* args, const Json& json, + grpc_error_handle* error); }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel.cc b/src/core/ext/filters/client_channel/subchannel.cc index b50295d56fd..a3db6096b02 100644 --- a/src/core/ext/filters/client_channel/subchannel.cc +++ b/src/core/ext/filters/client_channel/subchannel.cc @@ -36,6 +36,8 @@ #include "src/core/ext/filters/client_channel/proxy_mapper_registry.h" #include "src/core/ext/filters/client_channel/service_config.h" #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/connected_channel.h" @@ -45,8 +47,6 @@ #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/iomgr/parse_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel.h" @@ -131,7 +131,7 @@ size_t ConnectedSubchannel::GetInitialCallSizeEstimate() const { // RefCountedPtr SubchannelCall::Create(Args args, - grpc_error** error) { + grpc_error_handle* error) { const size_t allocation_size = args.connected_subchannel->GetInitialCallSizeEstimate(); Arena* arena = args.arena; @@ -139,7 +139,7 @@ RefCountedPtr SubchannelCall::Create(Args args, arena->Alloc(allocation_size)) SubchannelCall(std::move(args), error)); } -SubchannelCall::SubchannelCall(Args args, grpc_error** error) +SubchannelCall::SubchannelCall(Args args, grpc_error_handle* error) : connected_subchannel_(std::move(args.connected_subchannel)), deadline_(args.deadline) { grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(this); @@ -156,8 +156,7 @@ SubchannelCall::SubchannelCall(Args args, grpc_error** error) *error = grpc_call_stack_init(connected_subchannel_->channel_stack(), 1, SubchannelCall::Destroy, this, &call_args); if (GPR_UNLIKELY(*error != GRPC_ERROR_NONE)) { - const char* error_string = grpc_error_string(*error); - gpr_log(GPR_ERROR, "error: %s", error_string); + gpr_log(GPR_ERROR, "error: %s", grpc_error_std_string(*error).c_str()); return; } grpc_call_stack_set_pollset_or_pollset_set(callstk, args.pollent); @@ -207,7 +206,7 @@ void SubchannelCall::Unref(const DebugLocation& /*location*/, GRPC_CALL_STACK_UNREF(SUBCHANNEL_CALL_TO_CALL_STACK(this), reason); } -void SubchannelCall::Destroy(void* arg, grpc_error* /*error*/) { +void SubchannelCall::Destroy(void* arg, grpc_error_handle /*error*/) { GPR_TIMER_SCOPE("subchannel_call_destroy", 0); SubchannelCall* self = static_cast(arg); // Keep some members before destroying the subchannel call. @@ -252,7 +251,7 @@ namespace { // Sets *status based on the rest of the parameters. void GetCallStatus(grpc_status_code* status, grpc_millis deadline, - grpc_metadata_batch* md_batch, grpc_error* error) { + grpc_metadata_batch* md_batch, grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); } else { @@ -268,7 +267,8 @@ void GetCallStatus(grpc_status_code* status, grpc_millis deadline, } // namespace -void SubchannelCall::RecvTrailingMetadataReady(void* arg, grpc_error* error) { +void SubchannelCall::RecvTrailingMetadataReady(void* arg, + grpc_error_handle error) { SubchannelCall* call = static_cast(arg); GPR_ASSERT(call->recv_trailing_metadata_ != nullptr); grpc_status_code status = GRPC_STATUS_OK; @@ -303,20 +303,17 @@ class Subchannel::ConnectedSubchannelStateWatcher : public AsyncConnectivityStateWatcherInterface { public: // Must be instantiated while holding c->mu. - explicit ConnectedSubchannelStateWatcher(Subchannel* c) : subchannel_(c) { - // Steal subchannel ref for connecting. - GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "state_watcher"); - GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "connecting"); - } + explicit ConnectedSubchannelStateWatcher(WeakRefCountedPtr c) + : subchannel_(std::move(c)) {} ~ConnectedSubchannelStateWatcher() override { - GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "state_watcher"); + subchannel_.reset(DEBUG_LOCATION, "state_watcher"); } private: void OnConnectivityStateChange(grpc_connectivity_state new_state, const absl::Status& status) override { - Subchannel* c = subchannel_; + Subchannel* c = subchannel_.get(); MutexLock lock(&c->mu_); switch (new_state) { case GRPC_CHANNEL_TRANSIENT_FAILURE: @@ -357,7 +354,7 @@ class Subchannel::ConnectedSubchannelStateWatcher } } - Subchannel* subchannel_; + WeakRefCountedPtr subchannel_; }; // Asynchronously notifies the \a watcher of a change in the connectvity state @@ -378,7 +375,7 @@ class Subchannel::AsyncWatcherNotifierLocked { ExecCtx::Run(DEBUG_LOCATION, GRPC_CLOSURE_INIT( &closure_, - [](void* arg, grpc_error* /*error*/) { + [](void* arg, grpc_error_handle /*error*/) { auto* self = static_cast(arg); self->watcher_->OnConnectivityStateChange(); @@ -424,19 +421,19 @@ void Subchannel::ConnectivityStateWatcherList::NotifyLocked( class Subchannel::HealthWatcherMap::HealthWatcher : public AsyncConnectivityStateWatcherInterface { public: - HealthWatcher(Subchannel* c, std::string health_check_service_name, - grpc_connectivity_state subchannel_state) - : subchannel_(c), + HealthWatcher(WeakRefCountedPtr c, + std::string health_check_service_name) + : subchannel_(std::move(c)), health_check_service_name_(std::move(health_check_service_name)), - state_(subchannel_state == GRPC_CHANNEL_READY ? GRPC_CHANNEL_CONNECTING - : subchannel_state) { - GRPC_SUBCHANNEL_WEAK_REF(subchannel_, "health_watcher"); + state_(subchannel_->state_ == GRPC_CHANNEL_READY + ? GRPC_CHANNEL_CONNECTING + : subchannel_->state_) { // If the subchannel is already connected, start health checking. - if (subchannel_state == GRPC_CHANNEL_READY) StartHealthCheckingLocked(); + if (subchannel_->state_ == GRPC_CHANNEL_READY) StartHealthCheckingLocked(); } ~HealthWatcher() override { - GRPC_SUBCHANNEL_WEAK_UNREF(subchannel_, "health_watcher"); + subchannel_.reset(DEBUG_LOCATION, "health_watcher"); } const std::string& health_check_service_name() const { @@ -449,7 +446,8 @@ class Subchannel::HealthWatcherMap::HealthWatcher grpc_connectivity_state initial_state, RefCountedPtr watcher) { if (state_ != initial_state) { - new AsyncWatcherNotifierLocked(watcher, subchannel_, state_, status_); + new AsyncWatcherNotifierLocked(watcher, subchannel_.get(), state_, + status_); } watcher_list_.AddWatcherLocked(std::move(watcher)); } @@ -461,7 +459,8 @@ class Subchannel::HealthWatcherMap::HealthWatcher bool HasWatchers() const { return !watcher_list_.empty(); } - void NotifyLocked(grpc_connectivity_state state, const absl::Status& status) { + void NotifyLocked(grpc_connectivity_state state, const absl::Status& status) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(subchannel_->mu_) { if (state == GRPC_CHANNEL_READY) { // If we had not already notified for CONNECTING state, do so now. // (We may have missed this earlier, because if the transition @@ -470,14 +469,14 @@ class Subchannel::HealthWatcherMap::HealthWatcher if (state_ != GRPC_CHANNEL_CONNECTING) { state_ = GRPC_CHANNEL_CONNECTING; status_ = status; - watcher_list_.NotifyLocked(subchannel_, state_, status); + watcher_list_.NotifyLocked(subchannel_.get(), state_, status); } // If we've become connected, start health checking. StartHealthCheckingLocked(); } else { state_ = state; status_ = status; - watcher_list_.NotifyLocked(subchannel_, state_, status); + watcher_list_.NotifyLocked(subchannel_.get(), state_, status); // We're not connected, so stop health checking. health_check_client_.reset(); } @@ -496,18 +495,19 @@ class Subchannel::HealthWatcherMap::HealthWatcher if (new_state != GRPC_CHANNEL_SHUTDOWN && health_check_client_ != nullptr) { state_ = new_state; status_ = status; - watcher_list_.NotifyLocked(subchannel_, new_state, status); + watcher_list_.NotifyLocked(subchannel_.get(), new_state, status); } } - void StartHealthCheckingLocked() { + void StartHealthCheckingLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(subchannel_->mu_) { GPR_ASSERT(health_check_client_ == nullptr); health_check_client_ = MakeOrphanable( health_check_service_name_, subchannel_->connected_subchannel_, subchannel_->pollset_set_, subchannel_->channelz_node_, Ref()); } - Subchannel* subchannel_; + WeakRefCountedPtr subchannel_; std::string health_check_service_name_; OrphanablePtr health_check_client_; grpc_connectivity_state state_; @@ -520,7 +520,8 @@ class Subchannel::HealthWatcherMap::HealthWatcher // void Subchannel::HealthWatcherMap::AddWatcherLocked( - Subchannel* subchannel, grpc_connectivity_state initial_state, + WeakRefCountedPtr subchannel, + grpc_connectivity_state initial_state, const std::string& health_check_service_name, RefCountedPtr watcher) { // If the health check service name is not already present in the map, @@ -528,8 +529,8 @@ void Subchannel::HealthWatcherMap::AddWatcherLocked( auto it = map_.find(health_check_service_name); HealthWatcher* health_watcher; if (it == map_.end()) { - auto w = MakeOrphanable( - subchannel, health_check_service_name, subchannel->state_); + auto w = MakeOrphanable(std::move(subchannel), + health_check_service_name); health_watcher = w.get(); map_.emplace(health_check_service_name, std::move(w)); } else { @@ -647,14 +648,16 @@ Subchannel::ConnectivityStateWatcherInterface::PopConnectivityStateChange() { return state_change; } -Subchannel::Subchannel(SubchannelKey* key, +Subchannel::Subchannel(SubchannelKey key, OrphanablePtr connector, const grpc_channel_args* args) - : key_(key), + : DualRefCounted( + GRPC_TRACE_FLAG_ENABLED(grpc_trace_subchannel_refcount) ? "Subchannel" + : nullptr), + key_(std::move(key)), connector_(std::move(connector)), backoff_(ParseArgsForBackoffValues(args, &min_connect_timeout_ms_)) { GRPC_STATS_INC_CLIENT_SUBCHANNELS_CREATED(); - gpr_atm_no_barrier_store(&ref_pair_, 1 << INTERNAL_REF_BITS); pollset_set_ = grpc_pollset_set_create(); grpc_resolved_address* addr = static_cast(gpr_malloc(sizeof(*addr))); @@ -704,26 +707,26 @@ Subchannel::~Subchannel() { grpc_channel_args_destroy(args_); connector_.reset(); grpc_pollset_set_destroy(pollset_set_); - delete key_; } -Subchannel* Subchannel::Create(OrphanablePtr connector, - const grpc_channel_args* args) { - SubchannelKey* key = new SubchannelKey(args); +RefCountedPtr Subchannel::Create( + OrphanablePtr connector, + const grpc_channel_args* args) { + SubchannelKey key(args); SubchannelPoolInterface* subchannel_pool = SubchannelPoolInterface::GetSubchannelPoolFromChannelArgs(args); GPR_ASSERT(subchannel_pool != nullptr); - Subchannel* c = subchannel_pool->FindSubchannel(key); + RefCountedPtr c = subchannel_pool->FindSubchannel(key); if (c != nullptr) { - delete key; return c; } - c = new Subchannel(key, std::move(connector), args); + c = MakeRefCounted(std::move(key), std::move(connector), args); // Try to register the subchannel before setting the subchannel pool. // Otherwise, in case of a registration race, unreffing c in // RegisterSubchannel() will cause c to be tried to be unregistered, while // its key maps to a different subchannel. - Subchannel* registered = subchannel_pool->RegisterSubchannel(key, c); + RefCountedPtr registered = + subchannel_pool->RegisterSubchannel(c->key_, c); if (registered == c) c->subchannel_pool_ = subchannel_pool->Ref(); return registered; } @@ -747,68 +750,6 @@ void Subchannel::ThrottleKeepaliveTime(int new_keepalive_time) { } } -Subchannel* Subchannel::Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = RefMutate((1 << INTERNAL_REF_BITS), - 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_REF")); - GPR_ASSERT((old_refs & STRONG_REF_MASK) != 0); - return this; -} - -void Subchannel::Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - // add a weak ref and subtract a strong ref (atomically) - old_refs = RefMutate( - static_cast(1) - static_cast(1 << INTERNAL_REF_BITS), - 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("STRONG_UNREF")); - if ((old_refs & STRONG_REF_MASK) == (1 << INTERNAL_REF_BITS)) { - Disconnect(); - } - GRPC_SUBCHANNEL_WEAK_UNREF(this, "strong-unref"); -} - -Subchannel* Subchannel::WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = RefMutate(1, 0 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_REF")); - GPR_ASSERT(old_refs != 0); - return this; -} - -namespace { - -void subchannel_destroy(void* arg, grpc_error* /*error*/) { - Subchannel* self = static_cast(arg); - delete self; -} - -} // namespace - -void Subchannel::WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS) { - gpr_atm old_refs; - old_refs = RefMutate(-static_cast(1), - 1 GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE("WEAK_UNREF")); - if (old_refs == 1) { - ExecCtx::Run(DEBUG_LOCATION, - GRPC_CLOSURE_CREATE(subchannel_destroy, this, - grpc_schedule_on_exec_ctx), - GRPC_ERROR_NONE); - } -} - -Subchannel* Subchannel::RefFromWeakRef() { - for (;;) { - gpr_atm old_refs = gpr_atm_acq_load(&ref_pair_); - if (old_refs >= (1 << INTERNAL_REF_BITS)) { - gpr_atm new_refs = old_refs + (1 << INTERNAL_REF_BITS); - if (gpr_atm_rel_cas(&ref_pair_, old_refs, new_refs)) { - return this; - } - } else { - return nullptr; - } - } -} - const char* Subchannel::GetTargetAddress() { const grpc_arg* addr_arg = grpc_channel_args_find(args_, GRPC_ARG_SUBCHANNEL_ADDRESS); @@ -854,7 +795,8 @@ void Subchannel::WatchConnectivityState( watcher_list_.AddWatcherLocked(std::move(watcher)); } else { health_watcher_map_.AddWatcherLocked( - this, initial_state, *health_check_service_name, std::move(watcher)); + WeakRef(DEBUG_LOCATION, "health_watcher"), initial_state, + *health_check_service_name, std::move(watcher)); } } @@ -891,6 +833,21 @@ void Subchannel::ResetBackoff() { } } +void Subchannel::Orphan() { + // The subchannel_pool is only used once here in this subchannel, so the + // access can be outside of the lock. + if (subchannel_pool_ != nullptr) { + subchannel_pool_->UnregisterSubchannel(key_, this); + subchannel_pool_.reset(); + } + MutexLock lock(&mu_); + GPR_ASSERT(!disconnected_); + disconnected_ = true; + connector_.reset(); + connected_subchannel_.reset(); + health_watcher_map_.ShutdownLocked(); +} + grpc_arg Subchannel::CreateSubchannelAddressArg( const grpc_resolved_address* addr) { return grpc_channel_arg_string_create( @@ -984,7 +941,8 @@ void Subchannel::MaybeStartConnectingLocked() { return; } connecting_ = true; - GRPC_SUBCHANNEL_WEAK_REF(this, "connecting"); + WeakRef(DEBUG_LOCATION, "connecting") + .release(); // ref held by pending connect if (!backoff_begun_) { backoff_begun_ = true; ContinueConnectingLocked(); @@ -1005,11 +963,9 @@ void Subchannel::MaybeStartConnectingLocked() { } } -void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { - Subchannel* c = static_cast(arg); - // TODO(soheilhy): Once subchannel refcounting is simplified, we can get use - // MutexLock instead of ReleasableMutexLock, here. - ReleasableMutexLock lock(&c->mu_); +void Subchannel::OnRetryAlarm(void* arg, grpc_error_handle error) { + WeakRefCountedPtr c(static_cast(arg)); + MutexLock lock(&c->mu_); c->have_retry_alarm_ = false; if (c->disconnected_) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Disconnected", @@ -1023,10 +979,9 @@ void Subchannel::OnRetryAlarm(void* arg, grpc_error* error) { if (error == GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to connect to channel, retrying"); c->ContinueConnectingLocked(); - lock.Release(); - } else { - lock.Release(); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); + // Still connecting, keep ref around. Note that this stolen ref won't + // be dropped without first acquiring c->mu_. + c.release(); } GRPC_ERROR_UNREF(error); } @@ -1043,33 +998,30 @@ void Subchannel::ContinueConnectingLocked() { connector_->Connect(args, &connecting_result_, &on_connecting_finished_); } -void Subchannel::OnConnectingFinished(void* arg, grpc_error* error) { - auto* c = static_cast(arg); +void Subchannel::OnConnectingFinished(void* arg, grpc_error_handle error) { + WeakRefCountedPtr c(static_cast(arg)); const grpc_channel_args* delete_channel_args = c->connecting_result_.channel_args; - GRPC_SUBCHANNEL_WEAK_REF(c, "on_connecting_finished"); { MutexLock lock(&c->mu_); c->connecting_ = false; if (c->connecting_result_.transport != nullptr && c->PublishTransportLocked()) { // Do nothing, transport was published. - } else if (c->disconnected_) { - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); - } else { - gpr_log(GPR_INFO, "Connect failed: %s", grpc_error_string(error)); + } else if (!c->disconnected_) { + gpr_log(GPR_INFO, "Connect failed: %s", + grpc_error_std_string(error).c_str()); c->SetConnectivityStateLocked(GRPC_CHANNEL_TRANSIENT_FAILURE, grpc_error_to_absl_status(error)); - GRPC_SUBCHANNEL_WEAK_UNREF(c, "connecting"); } } - GRPC_SUBCHANNEL_WEAK_UNREF(c, "on_connecting_finished"); grpc_channel_args_destroy(delete_channel_args); + c.reset(DEBUG_LOCATION, "connecting"); } namespace { -void ConnectionDestroy(void* arg, grpc_error* /*error*/) { +void ConnectionDestroy(void* arg, grpc_error_handle /*error*/) { grpc_channel_stack* stk = static_cast(arg); grpc_channel_stack_destroy(stk); gpr_free(stk); @@ -1089,13 +1041,13 @@ bool Subchannel::PublishTransportLocked() { return false; } grpc_channel_stack* stk; - grpc_error* error = grpc_channel_stack_builder_finish( + grpc_error_handle error = grpc_channel_stack_builder_finish( builder, 0, 1, ConnectionDestroy, nullptr, reinterpret_cast(&stk)); if (error != GRPC_ERROR_NONE) { grpc_transport_destroy(connecting_result_.transport); gpr_log(GPR_ERROR, "error initializing subchannel stack: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); return false; } @@ -1117,39 +1069,11 @@ bool Subchannel::PublishTransportLocked() { } // Start watching connected subchannel. connected_subchannel_->StartWatch( - pollset_set_, MakeOrphanable(this)); + pollset_set_, MakeOrphanable( + WeakRef(DEBUG_LOCATION, "state_watcher"))); // Report initial state. SetConnectivityStateLocked(GRPC_CHANNEL_READY, absl::Status()); return true; } -void Subchannel::Disconnect() { - // The subchannel_pool is only used once here in this subchannel, so the - // access can be outside of the lock. - if (subchannel_pool_ != nullptr) { - subchannel_pool_->UnregisterSubchannel(key_); - subchannel_pool_.reset(); - } - MutexLock lock(&mu_); - GPR_ASSERT(!disconnected_); - disconnected_ = true; - connector_.reset(); - connected_subchannel_.reset(); - health_watcher_map_.ShutdownLocked(); -} - -gpr_atm Subchannel::RefMutate( - gpr_atm delta, int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS) { - gpr_atm old_val = barrier ? gpr_atm_full_fetch_add(&ref_pair_, delta) - : gpr_atm_no_barrier_fetch_add(&ref_pair_, delta); -#ifndef NDEBUG - if (grpc_trace_subchannel_refcount.enabled()) { - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "SUBCHANNEL: %p %12s 0x%" PRIxPTR " -> 0x%" PRIxPTR " [%s]", this, - purpose, old_val, old_val + delta, reason); - } -#endif - return old_val; -} - } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel.h b/src/core/ext/filters/client_channel/subchannel.h index 952a02a5ce3..9667fe7fd72 100644 --- a/src/core/ext/filters/client_channel/subchannel.h +++ b/src/core/ext/filters/client_channel/subchannel.h @@ -30,6 +30,7 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/time_precise.h" #include "src/core/lib/gprpp/arena.h" +#include "src/core/lib/gprpp/dual_ref_counted.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" @@ -41,31 +42,6 @@ // Channel arg containing a URI indicating the address to connect to. #define GRPC_ARG_SUBCHANNEL_ADDRESS "grpc.subchannel_address" -// For debugging refcounting. -#ifndef NDEBUG -#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref(__FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) (p)->RefFromWeakRef() -#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref(__FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef(__FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref(__FILE__, __LINE__, (r)) -#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS \ - const char *file, int line, const char *reason -#define GRPC_SUBCHANNEL_REF_REASON reason -#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS \ - , GRPC_SUBCHANNEL_REF_EXTRA_ARGS, const char* purpose -#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) , file, line, reason, x -#else -#define GRPC_SUBCHANNEL_REF(p, r) (p)->Ref() -#define GRPC_SUBCHANNEL_REF_FROM_WEAK_REF(p, r) (p)->RefFromWeakRef() -#define GRPC_SUBCHANNEL_UNREF(p, r) (p)->Unref() -#define GRPC_SUBCHANNEL_WEAK_REF(p, r) (p)->WeakRef() -#define GRPC_SUBCHANNEL_WEAK_UNREF(p, r) (p)->WeakUnref() -#define GRPC_SUBCHANNEL_REF_EXTRA_ARGS -#define GRPC_SUBCHANNEL_REF_REASON "" -#define GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS -#define GRPC_SUBCHANNEL_REF_MUTATE_PURPOSE(x) -#endif - namespace grpc_core { class SubchannelCall; @@ -111,7 +87,8 @@ class SubchannelCall { grpc_call_context_element* context; CallCombiner* call_combiner; }; - static RefCountedPtr Create(Args args, grpc_error** error); + static RefCountedPtr Create(Args args, + grpc_error_handle* error); // Continues processing a transport stream op batch. void StartTransportStreamOpBatch(grpc_transport_stream_op_batch* batch); @@ -137,20 +114,20 @@ class SubchannelCall { template friend class RefCountedPtr; - SubchannelCall(Args args, grpc_error** error); + SubchannelCall(Args args, grpc_error_handle* error); // If channelz is enabled, intercepts recv_trailing so that we may check the // status and associate it to a subchannel. void MaybeInterceptRecvTrailingMetadata( grpc_transport_stream_op_batch* batch); - static void RecvTrailingMetadataReady(void* arg, grpc_error* error); + static void RecvTrailingMetadataReady(void* arg, grpc_error_handle error); // Interface of RefCounted<>. void IncrementRefCount(); void IncrementRefCount(const DebugLocation& location, const char* reason); - static void Destroy(void* arg, grpc_error* error); + static void Destroy(void* arg, grpc_error_handle error); RefCountedPtr connected_subchannel_; grpc_closure* after_call_stack_destroy_ = nullptr; @@ -168,7 +145,7 @@ class SubchannelCall { // different from the SubchannelInterface that is exposed to LB policy // implementations. The client channel provides an adaptor class // (SubchannelWrapper) that "converts" between the two. -class Subchannel { +class Subchannel : public DualRefCounted { public: class ConnectivityStateWatcherInterface : public RefCounted { @@ -204,37 +181,29 @@ class Subchannel { ConnectivityStateChange PopConnectivityStateChange(); private: + Mutex mu_; // protects the queue // Keeps track of the updates that the watcher instance must be notified of. // TODO(yashkt): This is currently needed to send the state updates in the // right order when asynchronously notifying. This will no longer be // necessary when we have access to EventManager. - std::deque connectivity_state_queue_; - Mutex mu_; // protects the queue + std::deque connectivity_state_queue_ + ABSL_GUARDED_BY(&mu_); }; + // Creates a subchannel given \a connector and \a args. + static RefCountedPtr Create( + OrphanablePtr connector, + const grpc_channel_args* args); + // The ctor and dtor are not intended to use directly. - Subchannel(SubchannelKey* key, OrphanablePtr connector, + Subchannel(SubchannelKey key, OrphanablePtr connector, const grpc_channel_args* args); - ~Subchannel(); - - // Creates a subchannel given \a connector and \a args. - static Subchannel* Create(OrphanablePtr connector, - const grpc_channel_args* args); + ~Subchannel() override; // Throttles keepalive time to \a new_keepalive_time iff \a new_keepalive_time // is larger than the subchannel's current keepalive time. The updated value // will have an affect when the subchannel creates a new ConnectedSubchannel. - void ThrottleKeepaliveTime(int new_keepalive_time); - - // Strong and weak refcounting. - Subchannel* Ref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - void Unref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - Subchannel* WeakRef(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - void WeakUnref(GRPC_SUBCHANNEL_REF_EXTRA_ARGS); - // Attempts to return a strong ref when only the weak refcount is guaranteed - // non-zero. If the strong refcount is zero, does not alter the refcount and - // returns null. - Subchannel* RefFromWeakRef(); + void ThrottleKeepaliveTime(int new_keepalive_time) ABSL_LOCKS_EXCLUDED(mu_); // Gets the string representing the subchannel address. // Caller doesn't take ownership. @@ -251,7 +220,8 @@ class Subchannel { // If the return value is GRPC_CHANNEL_READY, also sets *connected_subchannel. grpc_connectivity_state CheckConnectivityState( const absl::optional& health_check_service_name, - RefCountedPtr* connected_subchannel); + RefCountedPtr* connected_subchannel) + ABSL_LOCKS_EXCLUDED(mu_); // Starts watching the subchannel's connectivity state. // The first callback to the watcher will be delivered when the @@ -264,23 +234,27 @@ class Subchannel { void WatchConnectivityState( grpc_connectivity_state initial_state, const absl::optional& health_check_service_name, - RefCountedPtr watcher); + RefCountedPtr watcher) + ABSL_LOCKS_EXCLUDED(mu_); // Cancels a connectivity state watch. // If the watcher has already been destroyed, this is a no-op. void CancelConnectivityStateWatch( const absl::optional& health_check_service_name, - ConnectivityStateWatcherInterface* watcher); + ConnectivityStateWatcherInterface* watcher) ABSL_LOCKS_EXCLUDED(mu_); // Attempt to connect to the backend. Has no effect if already connected. - void AttemptToConnect(); + void AttemptToConnect() ABSL_LOCKS_EXCLUDED(mu_); // Resets the connection backoff of the subchannel. // TODO(roth): Move connection backoff out of subchannels and up into LB // policy code (probably by adding a SubchannelGroup between // SubchannelList and SubchannelData), at which point this method can // go away. - void ResetBackoff(); + void ResetBackoff() ABSL_LOCKS_EXCLUDED(mu_); + + // Tears down any existing connection, and arranges for destruction + void Orphan() override ABSL_LOCKS_EXCLUDED(mu_); // Returns a new channel arg encoding the subchannel address as a URI // string. Caller is responsible for freeing the string. @@ -333,18 +307,20 @@ class Subchannel { class HealthWatcherMap { public: void AddWatcherLocked( - Subchannel* subchannel, grpc_connectivity_state initial_state, + WeakRefCountedPtr subchannel, + grpc_connectivity_state initial_state, const std::string& health_check_service_name, RefCountedPtr watcher); void RemoveWatcherLocked(const std::string& health_check_service_name, ConnectivityStateWatcherInterface* watcher); // Notifies the watcher when the subchannel's state changes. - void NotifyLocked(grpc_connectivity_state state, - const absl::Status& status); + void NotifyLocked(grpc_connectivity_state state, const absl::Status& status) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&Subchannel::mu_); grpc_connectivity_state CheckConnectivityStateLocked( - Subchannel* subchannel, const std::string& health_check_service_name); + Subchannel* subchannel, const std::string& health_check_service_name) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&Subchannel::mu_); void ShutdownLocked(); @@ -360,72 +336,65 @@ class Subchannel { // Sets the subchannel's connectivity state to \a state. void SetConnectivityStateLocked(grpc_connectivity_state state, - const absl::Status& status); + const absl::Status& status) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); // Methods for connection. - void MaybeStartConnectingLocked(); - static void OnRetryAlarm(void* arg, grpc_error* error); - void ContinueConnectingLocked(); - static void OnConnectingFinished(void* arg, grpc_error* error); - bool PublishTransportLocked(); - void Disconnect(); - - gpr_atm RefMutate(gpr_atm delta, - int barrier GRPC_SUBCHANNEL_REF_MUTATE_EXTRA_ARGS); + void MaybeStartConnectingLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + static void OnRetryAlarm(void* arg, grpc_error_handle error) + ABSL_LOCKS_EXCLUDED(mu_); + void ContinueConnectingLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + static void OnConnectingFinished(void* arg, grpc_error_handle error) + ABSL_LOCKS_EXCLUDED(mu_); + bool PublishTransportLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); // The subchannel pool this subchannel is in. RefCountedPtr subchannel_pool_; // TODO(juanlishen): Consider using args_ as key_ directly. // Subchannel key that identifies this subchannel in the subchannel pool. - SubchannelKey* key_; + const SubchannelKey key_; // Channel args. grpc_channel_args* args_; // pollset_set tracking who's interested in a connection being setup. grpc_pollset_set* pollset_set_; - // Protects the other members. - Mutex mu_; - // Refcount - // - lower INTERNAL_REF_BITS bits are for internal references: - // these do not keep the subchannel open. - // - upper remaining bits are for public references: these do - // keep the subchannel open - gpr_atm ref_pair_; - - // Connection states. + // Channelz tracking. + RefCountedPtr channelz_node_; + + // Connection state. OrphanablePtr connector_; - // Set during connection. SubchannelConnector::Result connecting_result_; grpc_closure on_connecting_finished_; + + // Protects the other members. + Mutex mu_; + // Active connection, or null. - RefCountedPtr connected_subchannel_; - bool connecting_ = false; - bool disconnected_ = false; + RefCountedPtr connected_subchannel_ ABSL_GUARDED_BY(mu_); + bool connecting_ ABSL_GUARDED_BY(mu_) = false; + bool disconnected_ ABSL_GUARDED_BY(mu_) = false; // Connectivity state tracking. - grpc_connectivity_state state_ = GRPC_CHANNEL_IDLE; - absl::Status status_; + grpc_connectivity_state state_ ABSL_GUARDED_BY(mu_) = GRPC_CHANNEL_IDLE; + absl::Status status_ ABSL_GUARDED_BY(mu_); // The list of watchers without a health check service name. - ConnectivityStateWatcherList watcher_list_; + ConnectivityStateWatcherList watcher_list_ ABSL_GUARDED_BY(mu_); // The map of watchers with health check service names. - HealthWatcherMap health_watcher_map_; + HealthWatcherMap health_watcher_map_ ABSL_GUARDED_BY(mu_); // Backoff state. - BackOff backoff_; - grpc_millis next_attempt_deadline_; - grpc_millis min_connect_timeout_ms_; - bool backoff_begun_ = false; + BackOff backoff_ ABSL_GUARDED_BY(mu_); + grpc_millis next_attempt_deadline_ ABSL_GUARDED_BY(mu_); + grpc_millis min_connect_timeout_ms_ ABSL_GUARDED_BY(mu_); + bool backoff_begun_ ABSL_GUARDED_BY(mu_) = false; // Retry alarm. - grpc_timer retry_alarm_; - grpc_closure on_retry_alarm_; - bool have_retry_alarm_ = false; + grpc_timer retry_alarm_ ABSL_GUARDED_BY(mu_); + grpc_closure on_retry_alarm_ ABSL_GUARDED_BY(mu_); + bool have_retry_alarm_ ABSL_GUARDED_BY(mu_) = false; // reset_backoff() was called while alarm was pending. - bool retry_immediately_ = false; + bool retry_immediately_ ABSL_GUARDED_BY(mu_) = false; // Keepalive time period (-1 for unset) - int keepalive_time_ = -1; - - // Channelz tracking. - RefCountedPtr channelz_node_; + int keepalive_time_ ABSL_GUARDED_BY(mu_) = -1; }; } // namespace grpc_core diff --git a/src/core/ext/filters/client_channel/subchannel_pool_interface.cc b/src/core/ext/filters/client_channel/subchannel_pool_interface.cc index bb35f228b70..308541c5309 100644 --- a/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +++ b/src/core/ext/filters/client_channel/subchannel_pool_interface.cc @@ -44,13 +44,27 @@ SubchannelKey::SubchannelKey(const SubchannelKey& other) { } SubchannelKey& SubchannelKey::operator=(const SubchannelKey& other) { + if (&other == this) { + return *this; + } grpc_channel_args_destroy(const_cast(args_)); Init(other.args_, grpc_channel_args_copy); return *this; } -int SubchannelKey::Cmp(const SubchannelKey& other) const { - return grpc_channel_args_compare(args_, other.args_); +SubchannelKey::SubchannelKey(SubchannelKey&& other) noexcept { + args_ = other.args_; + other.args_ = nullptr; +} + +SubchannelKey& SubchannelKey::operator=(SubchannelKey&& other) noexcept { + args_ = other.args_; + other.args_ = nullptr; + return *this; +} + +bool SubchannelKey::operator<(const SubchannelKey& other) const { + return grpc_channel_args_compare(args_, other.args_) < 0; } void SubchannelKey::Init( diff --git a/src/core/ext/filters/client_channel/subchannel_pool_interface.h b/src/core/ext/filters/client_channel/subchannel_pool_interface.h index f320ab69c26..8a8a0cb6934 100644 --- a/src/core/ext/filters/client_channel/subchannel_pool_interface.h +++ b/src/core/ext/filters/client_channel/subchannel_pool_interface.h @@ -41,11 +41,11 @@ class SubchannelKey { // Copyable. SubchannelKey(const SubchannelKey& other); SubchannelKey& operator=(const SubchannelKey& other); - // Not movable. - SubchannelKey(SubchannelKey&&) = delete; - SubchannelKey& operator=(SubchannelKey&&) = delete; + // Movable + SubchannelKey(SubchannelKey&&) noexcept; + SubchannelKey& operator=(SubchannelKey&&) noexcept; - int Cmp(const SubchannelKey& other) const; + bool operator<(const SubchannelKey& other) const; private: // Initializes the subchannel key with the given \a args and the function to @@ -72,15 +72,17 @@ class SubchannelPoolInterface : public RefCounted { // Registers a subchannel against a key. Returns the subchannel registered // with \a key, which may be different from \a constructed because we reuse // (instead of update) any existing subchannel already registered with \a key. - virtual Subchannel* RegisterSubchannel(SubchannelKey* key, - Subchannel* constructed) = 0; + virtual RefCountedPtr RegisterSubchannel( + const SubchannelKey& key, RefCountedPtr constructed) = 0; // Removes the registered subchannel found by \a key. - virtual void UnregisterSubchannel(SubchannelKey* key) = 0; + virtual void UnregisterSubchannel(const SubchannelKey& key, + Subchannel* subchannel) = 0; // Finds the subchannel registered for the given subchannel key. Returns NULL // if no such channel exists. Thread-safe. - virtual Subchannel* FindSubchannel(SubchannelKey* key) = 0; + virtual RefCountedPtr FindSubchannel( + const SubchannelKey& key) = 0; // Creates a channel arg from \a subchannel pool. static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool); diff --git a/src/core/ext/filters/client_idle/client_idle_filter.cc b/src/core/ext/filters/client_idle/client_idle_filter.cc index e39dda4dd90..01abaab7807 100644 --- a/src/core/ext/filters/client_idle/client_idle_filter.cc +++ b/src/core/ext/filters/client_idle/client_idle_filter.cc @@ -126,8 +126,8 @@ grpc_millis GetClientIdleTimeout(const grpc_channel_args* args) { class ChannelData { public: - static grpc_error* Init(grpc_channel_element* elem, - grpc_channel_element_args* args); + static grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args); static void Destroy(grpc_channel_element* elem); static void StartTransportOp(grpc_channel_element* elem, @@ -139,11 +139,12 @@ class ChannelData { private: ChannelData(grpc_channel_element* elem, grpc_channel_element_args* args, - grpc_error** error); + grpc_error_handle* error); ~ChannelData() = default; - static void IdleTimerCallback(void* arg, grpc_error* error); - static void IdleTransportOpCompleteCallback(void* arg, grpc_error* error); + static void IdleTimerCallback(void* arg, grpc_error_handle error); + static void IdleTransportOpCompleteCallback(void* arg, + grpc_error_handle error); void StartIdleTimer(); @@ -170,9 +171,9 @@ class ChannelData { grpc_closure idle_transport_op_complete_callback_; }; -grpc_error* ChannelData::Init(grpc_channel_element* elem, - grpc_channel_element_args* args) { - grpc_error* error = GRPC_ERROR_NONE; +grpc_error_handle ChannelData::Init(grpc_channel_element* elem, + grpc_channel_element_args* args) { + grpc_error_handle error = GRPC_ERROR_NONE; new (elem->channel_data) ChannelData(elem, args, &error); return error; } @@ -283,7 +284,7 @@ void ChannelData::DecreaseCallCount() { ChannelData::ChannelData(grpc_channel_element* elem, grpc_channel_element_args* args, - grpc_error** /*error*/) + grpc_error_handle* /*error*/) : elem_(elem), channel_stack_(args->channel_stack), client_idle_timeout_(GetClientIdleTimeout(args->channel_args)) { @@ -303,7 +304,7 @@ ChannelData::ChannelData(grpc_channel_element* elem, grpc_schedule_on_exec_ctx); } -void ChannelData::IdleTimerCallback(void* arg, grpc_error* error) { +void ChannelData::IdleTimerCallback(void* arg, grpc_error_handle error) { GRPC_IDLE_FILTER_LOG("timer alarms"); ChannelData* chand = static_cast(arg); if (error != GRPC_ERROR_NONE) { @@ -352,7 +353,7 @@ void ChannelData::IdleTimerCallback(void* arg, grpc_error* error) { } void ChannelData::IdleTransportOpCompleteCallback(void* arg, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { ChannelData* chand = static_cast(arg); GRPC_CHANNEL_STACK_UNREF(chand->channel_stack_, "idle transport op"); } @@ -381,15 +382,15 @@ void ChannelData::EnterIdle() { class CallData { public: - static grpc_error* Init(grpc_call_element* elem, - const grpc_call_element_args* args); + static grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args); static void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* then_schedule_closure); }; -grpc_error* CallData::Init(grpc_call_element* elem, - const grpc_call_element_args* /*args*/) { +grpc_error_handle CallData::Init(grpc_call_element* elem, + const grpc_call_element_args* /*args*/) { ChannelData* chand = static_cast(elem->channel_data); chand->IncreaseCallCount(); return GRPC_ERROR_NONE; diff --git a/src/core/ext/filters/deadline/deadline_filter.cc b/src/core/ext/filters/deadline/deadline_filter.cc index 837e337b64b..8944f5d9d15 100644 --- a/src/core/ext/filters/deadline/deadline_filter.cc +++ b/src/core/ext/filters/deadline/deadline_filter.cc @@ -51,7 +51,7 @@ class TimerState { private: // The on_complete callback used when sending a cancel_error batch down the // filter stack. Yields the call combiner when the batch returns. - static void YieldCallCombiner(void* arg, grpc_error* /*ignored*/) { + static void YieldCallCombiner(void* arg, grpc_error_handle /*ignored*/) { TimerState* self = static_cast(arg); grpc_deadline_state* deadline_state = static_cast(self->elem_->call_data); @@ -62,7 +62,7 @@ class TimerState { // This is called via the call combiner, so access to deadline_state is // synchronized. - static void SendCancelOpInCallCombiner(void* arg, grpc_error* error) { + static void SendCancelOpInCallCombiner(void* arg, grpc_error_handle error) { TimerState* self = static_cast(arg); grpc_transport_stream_op_batch* batch = grpc_make_transport_stream_op( GRPC_CLOSURE_INIT(&self->closure_, YieldCallCombiner, self, nullptr)); @@ -72,7 +72,7 @@ class TimerState { } // Timer callback. - static void TimerCallback(void* arg, grpc_error* error) { + static void TimerCallback(void* arg, grpc_error_handle error) { TimerState* self = static_cast(arg); grpc_deadline_state* deadline_state = static_cast(self->elem_->call_data); @@ -135,7 +135,7 @@ static void cancel_timer_if_needed(grpc_deadline_state* deadline_state) { } // Callback run when we receive trailing metadata. -static void recv_trailing_metadata_ready(void* arg, grpc_error* error) { +static void recv_trailing_metadata_ready(void* arg, grpc_error_handle error) { grpc_deadline_state* deadline_state = static_cast(arg); cancel_timer_if_needed(deadline_state); // Invoke the original callback. @@ -168,7 +168,7 @@ struct start_timer_after_init_state { grpc_millis deadline; grpc_closure closure; }; -static void start_timer_after_init(void* arg, grpc_error* error) { +static void start_timer_after_init(void* arg, grpc_error_handle error) { struct start_timer_after_init_state* state = static_cast(arg); grpc_deadline_state* deadline_state = @@ -241,8 +241,8 @@ void grpc_deadline_state_client_start_transport_stream_op_batch( // // Constructor for channel_data. Used for both client and server filters. -static grpc_error* deadline_init_channel_elem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* args) { +static grpc_error_handle deadline_init_channel_elem( + grpc_channel_element* /*elem*/, grpc_channel_element_args* args) { GPR_ASSERT(!args->is_last); return GRPC_ERROR_NONE; } @@ -268,8 +268,8 @@ typedef struct server_call_data { } server_call_data; // Constructor for call_data. Used for both client and server filters. -static grpc_error* deadline_init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { +static grpc_error_handle deadline_init_call_elem( + grpc_call_element* elem, const grpc_call_element_args* args) { new (elem->call_data) grpc_deadline_state(elem, *args, args->deadline); return GRPC_ERROR_NONE; } @@ -292,7 +292,7 @@ static void deadline_client_start_transport_stream_op_batch( } // Callback for receiving initial metadata on the server. -static void recv_initial_metadata_ready(void* arg, grpc_error* error) { +static void recv_initial_metadata_ready(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); server_call_data* calld = static_cast(elem->call_data); start_timer_if_needed(elem, calld->recv_initial_metadata->deadline); diff --git a/src/core/ext/filters/fault_injection/fault_injection_filter.cc b/src/core/ext/filters/fault_injection/fault_injection_filter.cc new file mode 100644 index 00000000000..5f8d7794414 --- /dev/null +++ b/src/core/ext/filters/fault_injection/fault_injection_filter.cc @@ -0,0 +1,501 @@ +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "src/core/ext/filters/fault_injection/fault_injection_filter.h" + +#include "absl/strings/numbers.h" + +#include +#include + +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/ext/filters/client_channel/service_config_call_data.h" +#include "src/core/ext/filters/fault_injection/service_config_parser.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gprpp/atomic.h" +#include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/iomgr/closure.h" +#include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/transport/status_conversion.h" + +namespace grpc_core { + +TraceFlag grpc_fault_injection_filter_trace(false, "fault_injection_filter"); + +namespace { + +Atomic g_active_faults{0}; +static_assert( + std::is_trivially_destructible>::value, + "the active fault counter needs to have a trivially destructible type"); + +inline int GetLinkedMetadatumValueInt(grpc_linked_mdelem* md) { + int res; + if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) { + return res; + } else { + return -1; + } +} + +inline uint32_t GetLinkedMetadatumValueUnsignedInt(grpc_linked_mdelem* md) { + uint32_t res; + if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) { + return res; + } else { + return -1; + } +} + +inline int64_t GetLinkedMetadatumValueInt64(grpc_linked_mdelem* md) { + int64_t res; + if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) { + return res; + } else { + return -1; + } +} + +inline bool UnderFraction(const uint32_t numerator, + const uint32_t denominator) { + if (numerator <= 0) return false; + if (numerator >= denominator) return true; + // Generate a random number in [0, denominator). + const uint32_t random_number = rand() % denominator; + return random_number < numerator; +} + +class ChannelData { + public: + static grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args); + static void Destroy(grpc_channel_element* elem); + + int index() const { return index_; } + + private: + ChannelData(grpc_channel_element* elem, grpc_channel_element_args* args); + ~ChannelData() = default; + + // The relative index of instances of the same filter. + int index_; +}; + +class CallData { + public: + static grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args); + + static void Destroy(grpc_call_element* elem, + const grpc_call_final_info* /*final_info*/, + grpc_closure* /*then_schedule_closure*/); + + static void StartTransportStreamOpBatch( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch); + + private: + class ResumeBatchCanceller; + + CallData(grpc_call_element* elem, const grpc_call_element_args* args); + ~CallData(); + + void DecideWhetherToInjectFaults(grpc_metadata_batch* initial_metadata); + + // Checks if current active faults exceed the allowed max faults. + bool HaveActiveFaultsQuota(bool increment); + + // Returns true if this RPC needs to be delayed. If so, this call will be + // counted as an active fault. + bool MaybeDelay(); + + // Returns the aborted RPC status if this RPC needs to be aborted. If so, + // this call will be counted as an active fault. Otherwise, it returns + // GRPC_ERROR_NONE. + // If this call is already been delay injected, skip the active faults + // quota check. + grpc_error_handle MaybeAbort(); + + // Delays the stream operations batch. + void DelayBatch(grpc_call_element* elem, + grpc_transport_stream_op_batch* batch); + + // Cancels the delay timer. + void CancelDelayTimer() { grpc_timer_cancel(&delay_timer_); } + + // Finishes the fault injection, should only be called once. + void FaultInjectionFinished() { + g_active_faults.FetchSub(1, MemoryOrder::RELAXED); + } + + // This is a callback that will be invoked after the delay timer is up. + static void ResumeBatch(void* arg, grpc_error_handle error); + + // This is a callback invoked upon completion of recv_trailing_metadata. + // Injects the abort_error_ to the recv_trailing_metadata batch if needed. + static void HijackedRecvTrailingMetadataReady(void* arg, grpc_error_handle); + + // Used to track the policy structs that needs to be destroyed in dtor. + bool fi_policy_owned_ = false; + const FaultInjectionMethodParsedConfig::FaultInjectionPolicy* fi_policy_; + grpc_call_stack* owning_call_; + Arena* arena_; + CallCombiner* call_combiner_; + + // Indicates whether we are doing a delay and/or an abort for this call. + bool delay_request_ = false; + bool abort_request_ = false; + + // Delay states + grpc_timer delay_timer_ ABSL_GUARDED_BY(delay_mu_); + ResumeBatchCanceller* resume_batch_canceller_ ABSL_GUARDED_BY(delay_mu_); + grpc_transport_stream_op_batch* delayed_batch_ ABSL_GUARDED_BY(delay_mu_); + // Abort states + grpc_error_handle abort_error_ = GRPC_ERROR_NONE; + grpc_closure recv_trailing_metadata_ready_; + grpc_closure* original_recv_trailing_metadata_ready_; + // Protects the asynchronous delay, resume, and cancellation. + Mutex delay_mu_; +}; + +// ChannelData + +grpc_error_handle ChannelData::Init(grpc_channel_element* elem, + grpc_channel_element_args* args) { + GPR_ASSERT(elem->filter == &FaultInjectionFilterVtable); + new (elem->channel_data) ChannelData(elem, args); + return GRPC_ERROR_NONE; +} + +void ChannelData::Destroy(grpc_channel_element* elem) { + auto* chand = static_cast(elem->channel_data); + chand->~ChannelData(); +} + +ChannelData::ChannelData(grpc_channel_element* elem, + grpc_channel_element_args* args) + : index_(grpc_channel_stack_filter_instance_number(args->channel_stack, + elem)) {} + +// CallData::ResumeBatchCanceller + +class CallData::ResumeBatchCanceller { + public: + explicit ResumeBatchCanceller(grpc_call_element* elem) : elem_(elem) { + auto* calld = static_cast(elem->call_data); + GRPC_CALL_STACK_REF(calld->owning_call_, "ResumeBatchCanceller"); + GRPC_CLOSURE_INIT(&closure_, &Cancel, this, grpc_schedule_on_exec_ctx); + calld->call_combiner_->SetNotifyOnCancel(&closure_); + } + + private: + static void Cancel(void* arg, grpc_error_handle error) { + auto* self = static_cast(arg); + auto* chand = static_cast(self->elem_->channel_data); + auto* calld = static_cast(self->elem_->call_data); + { + MutexLock lock(&calld->delay_mu_); + if (GRPC_TRACE_FLAG_ENABLED(grpc_fault_injection_filter_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: cancelling schdueled pick: " + "error=%s self=%p calld->resume_batch_canceller_=%p", + chand, calld, grpc_error_std_string(error).c_str(), self, + calld->resume_batch_canceller_); + } + if (error != GRPC_ERROR_NONE && calld->resume_batch_canceller_ == self) { + // Cancel the delayed pick. + calld->CancelDelayTimer(); + calld->FaultInjectionFinished(); + // Fail pending batches on the call. + grpc_transport_stream_op_batch_finish_with_failure( + calld->delayed_batch_, GRPC_ERROR_REF(error), + calld->call_combiner_); + } + } + GRPC_CALL_STACK_UNREF(calld->owning_call_, "ResumeBatchCanceller"); + delete self; + } + + grpc_call_element* elem_; + grpc_closure closure_; +}; + +// CallData + +grpc_error_handle CallData::Init(grpc_call_element* elem, + const grpc_call_element_args* args) { + auto* calld = new (elem->call_data) CallData(elem, args); + if (calld->fi_policy_ == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "failed to find fault injection policy"); + } + return GRPC_ERROR_NONE; +} + +void CallData::Destroy(grpc_call_element* elem, + const grpc_call_final_info* /*final_info*/, + grpc_closure* /*then_schedule_closure*/) { + auto* calld = static_cast(elem->call_data); + calld->~CallData(); +} + +void CallData::StartTransportStreamOpBatch( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { + auto* calld = static_cast(elem->call_data); + // There should only be one send_initial_metdata op, and fault injection also + // only need to be enforced once. + if (batch->send_initial_metadata) { + calld->DecideWhetherToInjectFaults( + batch->payload->send_initial_metadata.send_initial_metadata); + if (GRPC_TRACE_FLAG_ENABLED(grpc_fault_injection_filter_trace)) { + gpr_log(GPR_INFO, + "chand=%p calld=%p: Fault injection triggered delay=%d abort=%d", + elem->channel_data, calld, calld->delay_request_, + calld->abort_request_); + } + if (calld->MaybeDelay()) { + // Delay the batch, and pass down the batch in the scheduled closure. + calld->DelayBatch(elem, batch); + return; + } + grpc_error_handle abort_error = calld->MaybeAbort(); + if (abort_error != GRPC_ERROR_NONE) { + calld->abort_error_ = abort_error; + grpc_transport_stream_op_batch_finish_with_failure( + batch, GRPC_ERROR_REF(calld->abort_error_), calld->call_combiner_); + return; + } + } else { + if (batch->recv_trailing_metadata) { + // Intercept recv_trailing_metadata callback so that we can inject the + // failure when aborting streaming calls, because their + // recv_trailing_metatdata op may not be on the same batch as the + // send_initial_metadata op. + calld->original_recv_trailing_metadata_ready_ = + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready; + batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready = + &calld->recv_trailing_metadata_ready_; + } + if (calld->abort_error_ != GRPC_ERROR_NONE) { + // If we already decided to abort, then immediately fail this batch. + grpc_transport_stream_op_batch_finish_with_failure( + batch, GRPC_ERROR_REF(calld->abort_error_), calld->call_combiner_); + return; + } + } + // Chain to the next filter. + grpc_call_next_op(elem, batch); +} + +CallData::CallData(grpc_call_element* elem, const grpc_call_element_args* args) + : owning_call_(args->call_stack), + arena_(args->arena), + call_combiner_(args->call_combiner) { + auto* chand = static_cast(elem->channel_data); + // Fetch the fault injection policy from the service config, based on the + // relative index for which policy should this CallData use. + auto* service_config_call_data = static_cast( + args->context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value); + auto* method_params = static_cast( + service_config_call_data->GetMethodParsedConfig( + FaultInjectionServiceConfigParser::ParserIndex())); + if (method_params != nullptr) { + fi_policy_ = method_params->fault_injection_policy(chand->index()); + } + GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_, + HijackedRecvTrailingMetadataReady, elem, + grpc_schedule_on_exec_ctx); +} + +CallData::~CallData() { + if (fi_policy_owned_) { + fi_policy_->~FaultInjectionPolicy(); + } + GRPC_ERROR_UNREF(abort_error_); +} + +void CallData::DecideWhetherToInjectFaults( + grpc_metadata_batch* initial_metadata) { + FaultInjectionMethodParsedConfig::FaultInjectionPolicy* copied_policy = + nullptr; + // Update the policy with values in initial metadata. + if (!fi_policy_->abort_code_header.empty() || + !fi_policy_->abort_percentage_header.empty() || + !fi_policy_->delay_header.empty() || + !fi_policy_->delay_percentage_header.empty()) { + // Defer the actual copy until the first matched header. + auto maybe_copy_policy_func = [this, &copied_policy]() { + if (copied_policy == nullptr) { + copied_policy = + arena_->New( + *fi_policy_); + } + }; + for (grpc_linked_mdelem* md = initial_metadata->list.head; md != nullptr; + md = md->next) { + absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md)); + // Only perform string comparison if: + // 1. Needs to check this header; + // 2. The value is not been filled before. + if (!fi_policy_->abort_code_header.empty() && + (copied_policy == nullptr || + copied_policy->abort_code == GRPC_STATUS_OK) && + key == fi_policy_->abort_code_header) { + maybe_copy_policy_func(); + grpc_status_code_from_int(GetLinkedMetadatumValueInt(md), + &copied_policy->abort_code); + } + if (!fi_policy_->abort_percentage_header.empty() && + key == fi_policy_->abort_percentage_header) { + maybe_copy_policy_func(); + copied_policy->abort_percentage_numerator = + GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md), + fi_policy_->abort_percentage_numerator); + } + if (!fi_policy_->delay_header.empty() && + (copied_policy == nullptr || copied_policy->delay == 0) && + key == fi_policy_->delay_header) { + maybe_copy_policy_func(); + copied_policy->delay = static_cast( + GPR_MAX(GetLinkedMetadatumValueInt64(md), 0)); + } + if (!fi_policy_->delay_percentage_header.empty() && + key == fi_policy_->delay_percentage_header) { + maybe_copy_policy_func(); + copied_policy->delay_percentage_numerator = + GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md), + fi_policy_->delay_percentage_numerator); + } + } + if (copied_policy != nullptr) fi_policy_ = copied_policy; + } + // Roll the dice + delay_request_ = fi_policy_->delay != 0 && + UnderFraction(fi_policy_->delay_percentage_numerator, + fi_policy_->delay_percentage_denominator); + abort_request_ = fi_policy_->abort_code != GRPC_STATUS_OK && + UnderFraction(fi_policy_->abort_percentage_numerator, + fi_policy_->abort_percentage_denominator); + if (!delay_request_ && !abort_request_) { + if (copied_policy != nullptr) copied_policy->~FaultInjectionPolicy(); + // No fault injection for this call + } else { + fi_policy_owned_ = copied_policy != nullptr; + } +} + +bool CallData::HaveActiveFaultsQuota(bool increment) { + if (g_active_faults.Load(MemoryOrder::ACQUIRE) >= fi_policy_->max_faults) { + return false; + } + if (increment) g_active_faults.FetchAdd(1, MemoryOrder::RELAXED); + return true; +} + +bool CallData::MaybeDelay() { + if (delay_request_) { + return HaveActiveFaultsQuota(true); + } + return false; +} + +grpc_error_handle CallData::MaybeAbort() { + if (abort_request_ && (delay_request_ || HaveActiveFaultsQuota(false))) { + return grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_COPIED_STRING(fi_policy_->abort_message.c_str()), + GRPC_ERROR_INT_GRPC_STATUS, fi_policy_->abort_code); + } + return GRPC_ERROR_NONE; +} + +void CallData::DelayBatch(grpc_call_element* elem, + grpc_transport_stream_op_batch* batch) { + MutexLock lock(&delay_mu_); + delayed_batch_ = batch; + resume_batch_canceller_ = new ResumeBatchCanceller(elem); + grpc_millis resume_time = ExecCtx::Get()->Now() + fi_policy_->delay; + GRPC_CLOSURE_INIT(&batch->handler_private.closure, ResumeBatch, elem, + grpc_schedule_on_exec_ctx); + grpc_timer_init(&delay_timer_, resume_time, &batch->handler_private.closure); +} + +void CallData::ResumeBatch(void* arg, grpc_error_handle error) { + grpc_call_element* elem = static_cast(arg); + auto* calld = static_cast(elem->call_data); + MutexLock lock(&calld->delay_mu_); + // Cancelled or canceller has already run + if (error == GRPC_ERROR_CANCELLED || + calld->resume_batch_canceller_ == nullptr) { + return; + } + if (GRPC_TRACE_FLAG_ENABLED(grpc_fault_injection_filter_trace)) { + gpr_log(GPR_INFO, "chand=%p calld=%p: Resuming delayed stream op batch %p", + elem->channel_data, calld, calld->delayed_batch_); + } + // Lame the canceller + calld->resume_batch_canceller_ = nullptr; + // Finish fault injection. + calld->FaultInjectionFinished(); + // Abort if needed. + error = calld->MaybeAbort(); + if (error != GRPC_ERROR_NONE) { + grpc_transport_stream_op_batch_finish_with_failure( + calld->delayed_batch_, error, calld->call_combiner_); + return; + } + // Chain to the next filter. + grpc_call_next_op(elem, calld->delayed_batch_); +} + +void CallData::HijackedRecvTrailingMetadataReady(void* arg, + grpc_error_handle error) { + grpc_call_element* elem = static_cast(arg); + auto* calld = static_cast(elem->call_data); + if (calld->abort_error_ != GRPC_ERROR_NONE) { + error = grpc_error_add_child(GRPC_ERROR_REF(error), + GRPC_ERROR_REF(calld->abort_error_)); + } else { + error = GRPC_ERROR_REF(error); + } + Closure::Run(DEBUG_LOCATION, calld->original_recv_trailing_metadata_ready_, + error); +} + +} // namespace + +extern const grpc_channel_filter FaultInjectionFilterVtable = { + CallData::StartTransportStreamOpBatch, + grpc_channel_next_op, + sizeof(CallData), + CallData::Init, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + CallData::Destroy, + sizeof(ChannelData), + ChannelData::Init, + ChannelData::Destroy, + grpc_channel_next_get_info, + "fault_injection_filter", +}; + +void FaultInjectionFilterInit(void) { + grpc_core::FaultInjectionServiceConfigParser::Register(); +} + +void FaultInjectionFilterShutdown(void) {} + +} // namespace grpc_core diff --git a/src/core/ext/filters/fault_injection/fault_injection_filter.h b/src/core/ext/filters/fault_injection/fault_injection_filter.h new file mode 100644 index 00000000000..fbc1eb0cf9e --- /dev/null +++ b/src/core/ext/filters/fault_injection/fault_injection_filter.h @@ -0,0 +1,39 @@ +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_FAULT_INJECTION_FILTER_H +#define GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_FAULT_INJECTION_FILTER_H + +#include + +#include "src/core/ext/filters/fault_injection/service_config_parser.h" +#include "src/core/lib/channel/channel_stack.h" + +// Channel arg key for enabling parsing fault injection via method config. +#define GRPC_ARG_PARSE_FAULT_INJECTION_METHOD_CONFIG \ + "grpc.parse_fault_injection_method_config" + +namespace grpc_core { + +// This channel filter is intended to be used by the dynamic filters, instead +// of the ordinary channel stack. The fault injection filter fetches fault +// injection policy from the method config of service config returned by the +// resolver, and enforces the fault injection policy. +extern const grpc_channel_filter FaultInjectionFilterVtable; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_FAULT_INJECTION_FILTER_H diff --git a/src/core/ext/filters/fault_injection/service_config_parser.cc b/src/core/ext/filters/fault_injection/service_config_parser.cc new file mode 100644 index 00000000000..e8c23e1903f --- /dev/null +++ b/src/core/ext/filters/fault_injection/service_config_parser.cc @@ -0,0 +1,189 @@ +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "src/core/ext/filters/fault_injection/service_config_parser.h" + +#include + +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/ext/filters/fault_injection/fault_injection_filter.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/json/json_util.h" + +namespace grpc_core { + +namespace { + +size_t g_fault_injection_parser_index; + +std::vector +ParseFaultInjectionPolicy(const Json::Array& policies_json_array, + std::vector* error_list) { + std::vector policies; + for (size_t i = 0; i < policies_json_array.size(); i++) { + FaultInjectionMethodParsedConfig::FaultInjectionPolicy + fault_injection_policy; + std::vector sub_error_list; + if (policies_json_array[i].type() != Json::Type::OBJECT) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("faultInjectionPolicy index ", i, + " is not a JSON object") + .c_str())); + continue; + } + const Json::Object& json_object = policies_json_array[i].object_value(); + // Parse abort_code + std::string abort_code_string; + if (ParseJsonObjectField(json_object, "abortCode", &abort_code_string, + &sub_error_list, false)) { + if (!grpc_status_code_from_string(abort_code_string.c_str(), + &(fault_injection_policy.abort_code))) { + sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:abortCode error:failed to parse status code")); + } + } + // Parse abort_message + if (!ParseJsonObjectField(json_object, "abortMessage", + &fault_injection_policy.abort_message, + &sub_error_list, false)) { + fault_injection_policy.abort_message = "Fault injected"; + } + // Parse abort_code_header + ParseJsonObjectField(json_object, "abortCodeHeader", + &fault_injection_policy.abort_code_header, + &sub_error_list, false); + // Parse abort_percentage_header + ParseJsonObjectField(json_object, "abortPercentageHeader", + &fault_injection_policy.abort_percentage_header, + &sub_error_list, false); + // Parse abort_percentage_numerator + ParseJsonObjectField(json_object, "abortPercentageNumerator", + &fault_injection_policy.abort_percentage_numerator, + &sub_error_list, false); + // Parse abort_percentage_denominator + if (ParseJsonObjectField( + json_object, "abortPercentageDenominator", + &fault_injection_policy.abort_percentage_denominator, + &sub_error_list, false)) { + if (fault_injection_policy.abort_percentage_denominator != 100 && + fault_injection_policy.abort_percentage_denominator != 10000 && + fault_injection_policy.abort_percentage_denominator != 1000000) { + sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:abortPercentageDenominator error:Denominator can only be " + "one of " + "100, 10000, 1000000")); + } + } + // Parse delay + ParseJsonObjectFieldAsDuration(json_object, "delay", + &fault_injection_policy.delay, + &sub_error_list, false); + // Parse delay_header + ParseJsonObjectField(json_object, "delayHeader", + &fault_injection_policy.delay_header, &sub_error_list, + false); + // Parse delay_percentage_header + ParseJsonObjectField(json_object, "delayPercentageHeader", + &fault_injection_policy.delay_percentage_header, + &sub_error_list, false); + // Parse delay_percentage_numerator + ParseJsonObjectField(json_object, "delayPercentageNumerator", + &fault_injection_policy.delay_percentage_numerator, + &sub_error_list, false); + // Parse delay_percentage_denominator + if (ParseJsonObjectField( + json_object, "delayPercentageDenominator", + &fault_injection_policy.delay_percentage_denominator, + &sub_error_list, false)) { + if (fault_injection_policy.delay_percentage_denominator != 100 && + fault_injection_policy.delay_percentage_denominator != 10000 && + fault_injection_policy.delay_percentage_denominator != 1000000) { + sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:delayPercentageDenominator error:Denominator can only be " + "one of " + "100, 10000, 1000000")); + } + } + // Parse max_faults + if (ParseJsonObjectField(json_object, "maxFaults", + &fault_injection_policy.max_faults, + &sub_error_list, false)) { + if (fault_injection_policy.max_faults < 0) { + sub_error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "field:maxFaults error:should be zero or positive")); + } + } + if (!sub_error_list.empty()) { + // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error + // string is not static in this case. + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("failed to parse faultInjectionPolicy index ", i) + .c_str()); + for (size_t i = 0; i < sub_error_list.size(); ++i) { + error = grpc_error_add_child(error, sub_error_list[i]); + } + error_list->push_back(error); + } + policies.push_back(std::move(fault_injection_policy)); + } + return policies; +} + +} // namespace + +std::unique_ptr +FaultInjectionServiceConfigParser::ParsePerMethodParams( + const grpc_channel_args* args, const Json& json, grpc_error_handle* error) { + GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); + // Only parse fault injection policy if the following channel arg is present. + if (!grpc_channel_args_find_bool( + args, GRPC_ARG_PARSE_FAULT_INJECTION_METHOD_CONFIG, false)) { + return nullptr; + } + // Parse fault injection policy from given Json + std::vector + fault_injection_policies; + std::vector error_list; + const Json::Array* policies_json_array; + if (ParseJsonObjectField(json.object_value(), "faultInjectionPolicy", + &policies_json_array, &error_list)) { + fault_injection_policies = + ParseFaultInjectionPolicy(*policies_json_array, &error_list); + } + *error = GRPC_ERROR_CREATE_FROM_VECTOR("Fault injection parser", &error_list); + if (*error != GRPC_ERROR_NONE || fault_injection_policies.empty()) { + return nullptr; + } + return absl::make_unique( + std::move(fault_injection_policies)); +} + +void FaultInjectionServiceConfigParser::Register() { + g_fault_injection_parser_index = ServiceConfigParser::RegisterParser( + absl::make_unique()); +} + +size_t FaultInjectionServiceConfigParser::ParserIndex() { + return g_fault_injection_parser_index; +} + +} // namespace grpc_core diff --git a/src/core/ext/filters/fault_injection/service_config_parser.h b/src/core/ext/filters/fault_injection/service_config_parser.h new file mode 100644 index 00000000000..a885539c8c6 --- /dev/null +++ b/src/core/ext/filters/fault_injection/service_config_parser.h @@ -0,0 +1,85 @@ +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_SERVICE_CONFIG_PARSER_H +#define GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_SERVICE_CONFIG_PARSER_H + +#include + +#include + +#include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/lib/iomgr/exec_ctx.h" + +namespace grpc_core { + +class FaultInjectionMethodParsedConfig + : public ServiceConfigParser::ParsedConfig { + public: + struct FaultInjectionPolicy { + grpc_status_code abort_code = GRPC_STATUS_OK; + std::string abort_message; + std::string abort_code_header; + std::string abort_percentage_header; + uint32_t abort_percentage_numerator = 0; + uint32_t abort_percentage_denominator = 100; + + grpc_millis delay = 0; + std::string delay_header; + std::string delay_percentage_header; + uint32_t delay_percentage_numerator = 0; + uint32_t delay_percentage_denominator = 100; + + // By default, the max allowed active faults are unlimited. + uint32_t max_faults = std::numeric_limits::max(); + }; + + explicit FaultInjectionMethodParsedConfig( + std::vector fault_injection_policies) + : fault_injection_policies_(std::move(fault_injection_policies)) {} + + // Returns the fault injection policy at certain index. + // There might be multiple fault injection policies functioning at the same + // time. The order between the policies are stable, and an index is used to + // keep track of their relative positions. The FaultInjectionFilter uses this + // method to access the parsed fault injection policy in service config, + // whether it came from xDS resolver or directly from service config + const FaultInjectionPolicy* fault_injection_policy(int index) const { + if (static_cast(index) >= fault_injection_policies_.size()) { + return nullptr; + } + return &fault_injection_policies_[index]; + } + + private: + std::vector fault_injection_policies_; +}; + +class FaultInjectionServiceConfigParser : public ServiceConfigParser::Parser { + public: + // Parses the per-method service config for fault injection filter. + std::unique_ptr ParsePerMethodParams( + const grpc_channel_args* args, const Json& json, + grpc_error_handle* error) override; + // Returns the parser index for FaultInjectionServiceConfigParser. + static size_t ParserIndex(); + // Registers FaultInjectionServiceConfigParser to ServiceConfigParser. + static void Register(); +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_FILTERS_FAULT_INJECTION_SERVICE_CONFIG_PARSER_H diff --git a/src/core/ext/filters/http/client/http_client_filter.cc b/src/core/ext/filters/http/client/http_client_filter.cc index 3a4825f83d2..ef737f0e5ed 100644 --- a/src/core/ext/filters/http/client/http_client_filter.cc +++ b/src/core/ext/filters/http/client/http_client_filter.cc @@ -48,10 +48,12 @@ /* default maximum size of payload eligible for GET request */ static constexpr size_t kMaxPayloadSizeForGet = 2048; -static void recv_initial_metadata_ready(void* user_data, grpc_error* error); -static void recv_trailing_metadata_ready(void* user_data, grpc_error* error); -static void on_send_message_next_done(void* arg, grpc_error* error); -static void send_message_on_complete(void* arg, grpc_error* error); +static void recv_initial_metadata_ready(void* user_data, + grpc_error_handle error); +static void recv_trailing_metadata_ready(void* user_data, + grpc_error_handle error); +static void on_send_message_next_done(void* arg, grpc_error_handle error); +static void send_message_on_complete(void* arg, grpc_error_handle error); namespace { struct call_data { @@ -81,14 +83,14 @@ struct call_data { grpc_linked_mdelem user_agent; // State for handling recv_initial_metadata ops. grpc_metadata_batch* recv_initial_metadata; - grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE; + grpc_error_handle recv_initial_metadata_error = GRPC_ERROR_NONE; grpc_closure* original_recv_initial_metadata_ready = nullptr; grpc_closure recv_initial_metadata_ready; // State for handling recv_trailing_metadata ops. grpc_metadata_batch* recv_trailing_metadata; grpc_closure* original_recv_trailing_metadata_ready; grpc_closure recv_trailing_metadata_ready; - grpc_error* recv_trailing_metadata_error = GRPC_ERROR_NONE; + grpc_error_handle recv_trailing_metadata_error = GRPC_ERROR_NONE; bool seen_recv_trailing_metadata_ready = false; // State for handling send_message ops. grpc_transport_stream_op_batch* send_message_batch; @@ -108,7 +110,8 @@ struct channel_data { }; } // namespace -static grpc_error* client_filter_incoming_metadata(grpc_metadata_batch* b) { +static grpc_error_handle client_filter_incoming_metadata( + grpc_metadata_batch* b) { if (b->idx.named.status != nullptr) { /* If both gRPC status and HTTP status are provided in the response, we * should prefer the gRPC status code, as mentioned in @@ -123,7 +126,7 @@ static grpc_error* client_filter_incoming_metadata(grpc_metadata_batch* b) { GPR_DUMP_ASCII); std::string msg = absl::StrCat("Received http2 header with status: ", val); - grpc_error* e = grpc_error_set_str( + grpc_error_handle e = grpc_error_set_str( grpc_error_set_int( grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -182,7 +185,8 @@ static grpc_error* client_filter_incoming_metadata(grpc_metadata_batch* b) { return GRPC_ERROR_NONE; } -static void recv_initial_metadata_ready(void* user_data, grpc_error* error) { +static void recv_initial_metadata_ready(void* user_data, + grpc_error_handle error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); if (error == GRPC_ERROR_NONE) { @@ -201,7 +205,8 @@ static void recv_initial_metadata_ready(void* user_data, grpc_error* error) { grpc_core::Closure::Run(DEBUG_LOCATION, closure, error); } -static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { +static void recv_trailing_metadata_ready(void* user_data, + grpc_error_handle error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); if (calld->original_recv_initial_metadata_ready != nullptr) { @@ -223,7 +228,7 @@ static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { calld->original_recv_trailing_metadata_ready, error); } -static void send_message_on_complete(void* arg, grpc_error* error) { +static void send_message_on_complete(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); calld->send_message_cache.Destroy(); @@ -234,9 +239,10 @@ static void send_message_on_complete(void* arg, grpc_error* error) { // Pulls a slice from the send_message byte stream, updating // calld->send_message_bytes_read. -static grpc_error* pull_slice_from_send_message(call_data* calld) { +static grpc_error_handle pull_slice_from_send_message(call_data* calld) { grpc_slice incoming_slice; - grpc_error* error = calld->send_message_caching_stream->Pull(&incoming_slice); + grpc_error_handle error = + calld->send_message_caching_stream->Pull(&incoming_slice); if (error == GRPC_ERROR_NONE) { calld->send_message_bytes_read += GRPC_SLICE_LENGTH(incoming_slice); grpc_slice_unref_internal(incoming_slice); @@ -249,10 +255,11 @@ static grpc_error* pull_slice_from_send_message(call_data* calld) { // calld->send_message_caching_stream->length(), then we have completed // reading from the byte stream; otherwise, an async read has been dispatched // and on_send_message_next_done() will be invoked when it is complete. -static grpc_error* read_all_available_send_message_data(call_data* calld) { +static grpc_error_handle read_all_available_send_message_data( + call_data* calld) { while (calld->send_message_caching_stream->Next( SIZE_MAX, &calld->on_send_message_next_done)) { - grpc_error* error = pull_slice_from_send_message(calld); + grpc_error_handle error = pull_slice_from_send_message(calld); if (error != GRPC_ERROR_NONE) return error; if (calld->send_message_bytes_read == calld->send_message_caching_stream->length()) { @@ -263,7 +270,7 @@ static grpc_error* read_all_available_send_message_data(call_data* calld) { } // Async callback for ByteStream::Next(). -static void on_send_message_next_done(void* arg, grpc_error* error) { +static void on_send_message_next_done(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { @@ -301,8 +308,8 @@ static char* slice_buffer_to_string(grpc_slice_buffer* slice_buffer) { // Modifies the path entry in the batch's send_initial_metadata to // append the base64-encoded query for a GET request. -static grpc_error* update_path_for_get(grpc_call_element* elem, - grpc_transport_stream_op_batch* batch) { +static grpc_error_handle update_path_for_get( + grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast(elem->call_data); grpc_slice path_slice = GRPC_MDVALUE(batch->payload->send_initial_metadata.send_initial_metadata @@ -376,7 +383,7 @@ static void http_client_start_transport_stream_op_batch( &calld->recv_trailing_metadata_ready; } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; bool batch_will_be_handled_asynchronously = false; if (batch->send_initial_metadata) { // Decide which HTTP VERB to use. We use GET if the request is marked @@ -475,7 +482,7 @@ done: } /* Constructor for call_data */ -static grpc_error* http_client_init_call_elem( +static grpc_error_handle http_client_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* args) { new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; @@ -561,7 +568,7 @@ static grpc_core::ManagedMemorySlice user_agent_from_args( } /* Constructor for channel_data */ -static grpc_error* http_client_init_channel_elem( +static grpc_error_handle http_client_init_channel_elem( grpc_channel_element* elem, grpc_channel_element_args* args) { channel_data* chand = static_cast(elem->channel_data); GPR_ASSERT(!args->is_last); diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc index 9511d2591a3..f44ef853b4b 100644 --- a/src/core/ext/filters/http/client_authority_filter.cc +++ b/src/core/ext/filters/http/client_authority_filter.cc @@ -57,7 +57,7 @@ void client_authority_start_transport_stream_op_batch( if (batch->send_initial_metadata && batch->payload->send_initial_metadata.send_initial_metadata->idx.named .authority == nullptr) { - grpc_error* error = grpc_metadata_batch_add_head( + grpc_error_handle error = grpc_metadata_batch_add_head( batch->payload->send_initial_metadata.send_initial_metadata, &calld->authority_storage, GRPC_MDELEM_REF(chand->default_authority_mdelem), GRPC_BATCH_AUTHORITY); @@ -72,7 +72,7 @@ void client_authority_start_transport_stream_op_batch( } /* Constructor for call_data */ -grpc_error* client_authority_init_call_elem( +grpc_error_handle client_authority_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* args) { call_data* calld = static_cast(elem->call_data); calld->call_combiner = args->call_combiner; @@ -85,7 +85,7 @@ void client_authority_destroy_call_elem( grpc_closure* /*ignored*/) {} /* Constructor for channel_data */ -grpc_error* client_authority_init_channel_elem( +grpc_error_handle client_authority_init_channel_elem( grpc_channel_element* elem, grpc_channel_element_args* args) { channel_data* chand = static_cast(elem->channel_data); const grpc_arg* default_authority_arg = diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.cc b/src/core/ext/filters/http/message_compress/message_compress_filter.cc index 09c914fab07..0fc85b1ea21 100644 --- a/src/core/ext/filters/http/message_compress/message_compress_filter.cc +++ b/src/core/ext/filters/http/message_compress/message_compress_filter.cc @@ -131,25 +131,25 @@ class CallData { bool SkipMessageCompression(); void InitializeState(grpc_call_element* elem); - grpc_error* ProcessSendInitialMetadata(grpc_call_element* elem, - grpc_metadata_batch* initial_metadata); + grpc_error_handle ProcessSendInitialMetadata( + grpc_call_element* elem, grpc_metadata_batch* initial_metadata); // Methods for processing a send_message batch - static void StartSendMessageBatch(void* elem_arg, grpc_error* unused); - static void OnSendMessageNextDone(void* elem_arg, grpc_error* error); - grpc_error* PullSliceFromSendMessage(); + static void StartSendMessageBatch(void* elem_arg, grpc_error_handle unused); + static void OnSendMessageNextDone(void* elem_arg, grpc_error_handle error); + grpc_error_handle PullSliceFromSendMessage(); void ContinueReadingSendMessage(grpc_call_element* elem); void FinishSendMessage(grpc_call_element* elem); void SendMessageBatchContinue(grpc_call_element* elem); static void FailSendMessageBatchInCallCombiner(void* calld_arg, - grpc_error* error); + grpc_error_handle error); - static void SendMessageOnComplete(void* calld_arg, grpc_error* error); + static void SendMessageOnComplete(void* calld_arg, grpc_error_handle error); grpc_core::CallCombiner* call_combiner_; grpc_message_compression_algorithm message_compression_algorithm_ = GRPC_MESSAGE_COMPRESS_NONE; - grpc_error* cancel_error_ = GRPC_ERROR_NONE; + grpc_error_handle cancel_error_ = GRPC_ERROR_NONE; grpc_transport_stream_op_batch* send_message_batch_ = nullptr; bool seen_initial_metadata_ = false; /* Set to true, if the fields below are initialized. */ @@ -232,7 +232,7 @@ void CallData::InitializeState(grpc_call_element* elem) { grpc_schedule_on_exec_ctx); } -grpc_error* CallData::ProcessSendInitialMetadata( +grpc_error_handle CallData::ProcessSendInitialMetadata( grpc_call_element* elem, grpc_metadata_batch* initial_metadata) { ChannelData* channeld = static_cast(elem->channel_data); // Find the compression algorithm. @@ -246,7 +246,7 @@ grpc_error* CallData::ProcessSendInitialMetadata( grpc_compression_algorithm_to_stream_compression_algorithm( compression_algorithm); // Hint compression algorithm. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (message_compression_algorithm_ != GRPC_MESSAGE_COMPRESS_NONE) { InitializeState(elem); error = grpc_metadata_batch_add_tail( @@ -281,7 +281,7 @@ grpc_error* CallData::ProcessSendInitialMetadata( return error; } -void CallData::SendMessageOnComplete(void* calld_arg, grpc_error* error) { +void CallData::SendMessageOnComplete(void* calld_arg, grpc_error_handle error) { CallData* calld = static_cast(calld_arg); grpc_slice_buffer_reset_and_unref_internal(&calld->slices_); grpc_core::Closure::Run(DEBUG_LOCATION, @@ -348,7 +348,7 @@ void CallData::FinishSendMessage(grpc_call_element* elem) { } void CallData::FailSendMessageBatchInCallCombiner(void* calld_arg, - grpc_error* error) { + grpc_error_handle error) { CallData* calld = static_cast(calld_arg); if (calld->send_message_batch_ != nullptr) { grpc_transport_stream_op_batch_finish_with_failure( @@ -359,9 +359,9 @@ void CallData::FailSendMessageBatchInCallCombiner(void* calld_arg, } // Pulls a slice from the send_message byte stream and adds it to slices_. -grpc_error* CallData::PullSliceFromSendMessage() { +grpc_error_handle CallData::PullSliceFromSendMessage() { grpc_slice incoming_slice; - grpc_error* error = + grpc_error_handle error = send_message_batch_->payload->send_message.send_message->Pull( &incoming_slice); if (error == GRPC_ERROR_NONE) { @@ -382,7 +382,7 @@ void CallData::ContinueReadingSendMessage(grpc_call_element* elem) { } while (send_message_batch_->payload->send_message.send_message->Next( ~static_cast(0), &on_send_message_next_done_)) { - grpc_error* error = PullSliceFromSendMessage(); + grpc_error_handle error = PullSliceFromSendMessage(); if (error != GRPC_ERROR_NONE) { // Closure callback; does not take ownership of error. FailSendMessageBatchInCallCombiner(this, error); @@ -398,7 +398,7 @@ void CallData::ContinueReadingSendMessage(grpc_call_element* elem) { } // Async callback for ByteStream::Next(). -void CallData::OnSendMessageNextDone(void* elem_arg, grpc_error* error) { +void CallData::OnSendMessageNextDone(void* elem_arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(elem_arg); CallData* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { @@ -421,7 +421,8 @@ void CallData::OnSendMessageNextDone(void* elem_arg, grpc_error* error) { } } -void CallData::StartSendMessageBatch(void* elem_arg, grpc_error* /*unused*/) { +void CallData::StartSendMessageBatch(void* elem_arg, + grpc_error_handle /*unused*/) { grpc_call_element* elem = static_cast(elem_arg); CallData* calld = static_cast(elem->call_data); if (calld->SkipMessageCompression()) { @@ -458,7 +459,7 @@ void CallData::CompressStartTransportStreamOpBatch( // Handle send_initial_metadata. if (batch->send_initial_metadata) { GPR_ASSERT(!seen_initial_metadata_); - grpc_error* error = ProcessSendInitialMetadata( + grpc_error_handle error = ProcessSendInitialMetadata( elem, batch->payload->send_initial_metadata.send_initial_metadata); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(batch, error, @@ -503,8 +504,8 @@ void CompressStartTransportStreamOpBatch( } /* Constructor for call_data */ -grpc_error* CompressInitCallElem(grpc_call_element* elem, - const grpc_call_element_args* args) { +grpc_error_handle CompressInitCallElem(grpc_call_element* elem, + const grpc_call_element_args* args) { new (elem->call_data) CallData(elem, *args); return GRPC_ERROR_NONE; } @@ -518,8 +519,8 @@ void CompressDestroyCallElem(grpc_call_element* elem, } /* Constructor for ChannelData */ -grpc_error* CompressInitChannelElem(grpc_channel_element* elem, - grpc_channel_element_args* args) { +grpc_error_handle CompressInitChannelElem(grpc_channel_element* elem, + grpc_channel_element_args* args) { new (elem->channel_data) ChannelData(args); return GRPC_ERROR_NONE; } diff --git a/src/core/ext/filters/http/message_compress/message_decompress_filter.cc b/src/core/ext/filters/http/message_compress/message_decompress_filter.cc index 4ab8a5638c5..426dd9039d7 100644 --- a/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +++ b/src/core/ext/filters/http/message_compress/message_decompress_filter.cc @@ -89,24 +89,24 @@ class CallData { grpc_call_element* elem, grpc_transport_stream_op_batch* batch); private: - static void OnRecvInitialMetadataReady(void* arg, grpc_error* error); + static void OnRecvInitialMetadataReady(void* arg, grpc_error_handle error); // Methods for processing a receive message event void MaybeResumeOnRecvMessageReady(); - static void OnRecvMessageReady(void* arg, grpc_error* error); - static void OnRecvMessageNextDone(void* arg, grpc_error* error); - grpc_error* PullSliceFromRecvMessage(); + static void OnRecvMessageReady(void* arg, grpc_error_handle error); + static void OnRecvMessageNextDone(void* arg, grpc_error_handle error); + grpc_error_handle PullSliceFromRecvMessage(); void ContinueReadingRecvMessage(); void FinishRecvMessage(); - void ContinueRecvMessageReadyCallback(grpc_error* error); + void ContinueRecvMessageReadyCallback(grpc_error_handle error); // Methods for processing a recv_trailing_metadata event void MaybeResumeOnRecvTrailingMetadataReady(); - static void OnRecvTrailingMetadataReady(void* arg, grpc_error* error); + static void OnRecvTrailingMetadataReady(void* arg, grpc_error_handle error); CallCombiner* call_combiner_; // Overall error for the call - grpc_error* error_ = GRPC_ERROR_NONE; + grpc_error_handle error_ = GRPC_ERROR_NONE; // Fields for handling recv_initial_metadata_ready callback grpc_closure on_recv_initial_metadata_ready_; grpc_closure* original_recv_initial_metadata_ready_ = nullptr; @@ -130,7 +130,7 @@ class CallData { bool seen_recv_trailing_metadata_ready_ = false; grpc_closure on_recv_trailing_metadata_ready_; grpc_closure* original_recv_trailing_metadata_ready_ = nullptr; - grpc_error* on_recv_trailing_metadata_ready_error_ = GRPC_ERROR_NONE; + grpc_error_handle on_recv_trailing_metadata_ready_error_ = GRPC_ERROR_NONE; }; grpc_message_compression_algorithm DecodeMessageCompressionAlgorithm( @@ -149,7 +149,7 @@ grpc_message_compression_algorithm DecodeMessageCompressionAlgorithm( return algorithm; } -void CallData::OnRecvInitialMetadataReady(void* arg, grpc_error* error) { +void CallData::OnRecvInitialMetadataReady(void* arg, grpc_error_handle error) { CallData* calld = static_cast(arg); if (error == GRPC_ERROR_NONE) { grpc_linked_mdelem* grpc_encoding = @@ -174,7 +174,7 @@ void CallData::MaybeResumeOnRecvMessageReady() { } } -void CallData::OnRecvMessageReady(void* arg, grpc_error* error) { +void CallData::OnRecvMessageReady(void* arg, grpc_error_handle error) { CallData* calld = static_cast(arg); if (error == GRPC_ERROR_NONE) { if (calld->original_recv_initial_metadata_ready_ != nullptr) { @@ -218,7 +218,7 @@ void CallData::ContinueReadingRecvMessage() { while ((*recv_message_) ->Next((*recv_message_)->length() - recv_slices_.length, &on_recv_message_next_done_)) { - grpc_error* error = PullSliceFromRecvMessage(); + grpc_error_handle error = PullSliceFromRecvMessage(); if (error != GRPC_ERROR_NONE) { return ContinueRecvMessageReadyCallback(error); } @@ -229,16 +229,16 @@ void CallData::ContinueReadingRecvMessage() { } } -grpc_error* CallData::PullSliceFromRecvMessage() { +grpc_error_handle CallData::PullSliceFromRecvMessage() { grpc_slice incoming_slice; - grpc_error* error = (*recv_message_)->Pull(&incoming_slice); + grpc_error_handle error = (*recv_message_)->Pull(&incoming_slice); if (error == GRPC_ERROR_NONE) { grpc_slice_buffer_add(&recv_slices_, incoming_slice); } return error; } -void CallData::OnRecvMessageNextDone(void* arg, grpc_error* error) { +void CallData::OnRecvMessageNextDone(void* arg, grpc_error_handle error) { CallData* calld = static_cast(arg); if (error != GRPC_ERROR_NONE) { return calld->ContinueRecvMessageReadyCallback(GRPC_ERROR_REF(error)); @@ -283,7 +283,7 @@ void CallData::FinishRecvMessage() { ContinueRecvMessageReadyCallback(GRPC_ERROR_REF(error_)); } -void CallData::ContinueRecvMessageReadyCallback(grpc_error* error) { +void CallData::ContinueRecvMessageReadyCallback(grpc_error_handle error) { MaybeResumeOnRecvTrailingMetadataReady(); // The surface will clean up the receiving stream if there is an error. grpc_closure* closure = original_recv_message_ready_; @@ -294,14 +294,14 @@ void CallData::ContinueRecvMessageReadyCallback(grpc_error* error) { void CallData::MaybeResumeOnRecvTrailingMetadataReady() { if (seen_recv_trailing_metadata_ready_) { seen_recv_trailing_metadata_ready_ = false; - grpc_error* error = on_recv_trailing_metadata_ready_error_; + grpc_error_handle error = on_recv_trailing_metadata_ready_error_; on_recv_trailing_metadata_ready_error_ = GRPC_ERROR_NONE; GRPC_CALL_COMBINER_START(call_combiner_, &on_recv_trailing_metadata_ready_, error, "Continuing OnRecvTrailingMetadataReady"); } } -void CallData::OnRecvTrailingMetadataReady(void* arg, grpc_error* error) { +void CallData::OnRecvTrailingMetadataReady(void* arg, grpc_error_handle error) { CallData* calld = static_cast(arg); if (calld->original_recv_initial_metadata_ready_ != nullptr || calld->original_recv_message_ready_ != nullptr) { @@ -356,8 +356,8 @@ void DecompressStartTransportStreamOpBatch( calld->DecompressStartTransportStreamOpBatch(elem, batch); } -grpc_error* DecompressInitCallElem(grpc_call_element* elem, - const grpc_call_element_args* args) { +grpc_error_handle DecompressInitCallElem(grpc_call_element* elem, + const grpc_call_element_args* args) { ChannelData* chand = static_cast(elem->channel_data); new (elem->call_data) CallData(*args, chand); return GRPC_ERROR_NONE; @@ -370,8 +370,8 @@ void DecompressDestroyCallElem(grpc_call_element* elem, calld->~CallData(); } -grpc_error* DecompressInitChannelElem(grpc_channel_element* elem, - grpc_channel_element_args* args) { +grpc_error_handle DecompressInitChannelElem(grpc_channel_element* elem, + grpc_channel_element_args* args) { ChannelData* chand = static_cast(elem->channel_data); new (chand) ChannelData(args); return GRPC_ERROR_NONE; diff --git a/src/core/ext/filters/http/server/http_server_filter.cc b/src/core/ext/filters/http/server/http_server_filter.cc index e4ece548b55..226ba020b4f 100644 --- a/src/core/ext/filters/http/server/http_server_filter.cc +++ b/src/core/ext/filters/http/server/http_server_filter.cc @@ -35,9 +35,11 @@ #define EXPECTED_CONTENT_TYPE "application/grpc" #define EXPECTED_CONTENT_TYPE_LENGTH (sizeof(EXPECTED_CONTENT_TYPE) - 1) -static void hs_recv_initial_metadata_ready(void* user_data, grpc_error* err); -static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err); -static void hs_recv_message_ready(void* user_data, grpc_error* err); +static void hs_recv_initial_metadata_ready(void* user_data, + grpc_error_handle err); +static void hs_recv_trailing_metadata_ready(void* user_data, + grpc_error_handle err); +static void hs_recv_message_ready(void* user_data, grpc_error_handle err); namespace { @@ -74,7 +76,7 @@ struct call_data { // State for intercepting recv_initial_metadata. grpc_closure recv_initial_metadata_ready; - grpc_error* recv_initial_metadata_ready_error = GRPC_ERROR_NONE; + grpc_error_handle recv_initial_metadata_ready_error = GRPC_ERROR_NONE; grpc_closure* original_recv_initial_metadata_ready; grpc_metadata_batch* recv_initial_metadata = nullptr; uint32_t* recv_initial_metadata_flags; @@ -89,7 +91,7 @@ struct call_data { // State for intercepting recv_trailing_metadata grpc_closure recv_trailing_metadata_ready; grpc_closure* original_recv_trailing_metadata_ready; - grpc_error* recv_trailing_metadata_ready_error; + grpc_error_handle recv_trailing_metadata_ready_error; bool seen_recv_trailing_metadata_ready = false; }; @@ -99,7 +101,7 @@ struct channel_data { } // namespace -static grpc_error* hs_filter_outgoing_metadata(grpc_metadata_batch* b) { +static grpc_error_handle hs_filter_outgoing_metadata(grpc_metadata_batch* b) { if (b->idx.named.grpc_message != nullptr) { grpc_slice pct_encoded_msg = grpc_percent_encode_slice( GRPC_MDVALUE(b->idx.named.grpc_message->md), @@ -114,8 +116,8 @@ static grpc_error* hs_filter_outgoing_metadata(grpc_metadata_batch* b) { return GRPC_ERROR_NONE; } -static void hs_add_error(const char* error_name, grpc_error** cumulative, - grpc_error* new_err) { +static void hs_add_error(const char* error_name, grpc_error_handle* cumulative, + grpc_error_handle new_err) { if (new_err == GRPC_ERROR_NONE) return; if (*cumulative == GRPC_ERROR_NONE) { *cumulative = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_name); @@ -149,10 +151,10 @@ static bool md_strict_equal(grpc_mdelem a, grpc_mdelem b_static) { } } -static grpc_error* hs_filter_incoming_metadata(grpc_call_element* elem, - grpc_metadata_batch* b) { +static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, + grpc_metadata_batch* b) { call_data* calld = static_cast(elem->call_data); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; static const char* error_name = "Failed processing incoming headers"; if (b->idx.named.method != nullptr) { @@ -330,7 +332,8 @@ static grpc_error* hs_filter_incoming_metadata(grpc_call_element* elem, return error; } -static void hs_recv_initial_metadata_ready(void* user_data, grpc_error* err) { +static void hs_recv_initial_metadata_ready(void* user_data, + grpc_error_handle err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); calld->seen_recv_initial_metadata_ready = true; @@ -367,7 +370,7 @@ static void hs_recv_initial_metadata_ready(void* user_data, grpc_error* err) { calld->original_recv_initial_metadata_ready, err); } -static void hs_recv_message_ready(void* user_data, grpc_error* err) { +static void hs_recv_message_ready(void* user_data, grpc_error_handle err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); calld->seen_recv_message_ready = true; @@ -392,7 +395,8 @@ static void hs_recv_message_ready(void* user_data, grpc_error* err) { } } -static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err) { +static void hs_recv_trailing_metadata_ready(void* user_data, + grpc_error_handle err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); if (!calld->seen_recv_initial_metadata_ready) { @@ -410,13 +414,13 @@ static void hs_recv_trailing_metadata_ready(void* user_data, grpc_error* err) { calld->original_recv_trailing_metadata_ready, err); } -static grpc_error* hs_mutate_op(grpc_call_element* elem, - grpc_transport_stream_op_batch* op) { +static grpc_error_handle hs_mutate_op(grpc_call_element* elem, + grpc_transport_stream_op_batch* op) { /* grab pointers to our data from the call element */ call_data* calld = static_cast(elem->call_data); if (op->send_initial_metadata) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; static const char* error_name = "Failed sending initial metadata"; hs_add_error( error_name, &error, @@ -463,7 +467,7 @@ static grpc_error* hs_mutate_op(grpc_call_element* elem, } if (op->send_trailing_metadata) { - grpc_error* error = hs_filter_outgoing_metadata( + grpc_error_handle error = hs_filter_outgoing_metadata( op->payload->send_trailing_metadata.send_trailing_metadata); if (error != GRPC_ERROR_NONE) return error; } @@ -475,7 +479,7 @@ static void hs_start_transport_stream_op_batch( grpc_call_element* elem, grpc_transport_stream_op_batch* op) { GPR_TIMER_SCOPE("hs_start_transport_stream_op_batch", 0); call_data* calld = static_cast(elem->call_data); - grpc_error* error = hs_mutate_op(elem, op); + grpc_error_handle error = hs_mutate_op(elem, op); if (error != GRPC_ERROR_NONE) { grpc_transport_stream_op_batch_finish_with_failure(op, error, calld->call_combiner); @@ -485,8 +489,8 @@ static void hs_start_transport_stream_op_batch( } /* Constructor for call_data */ -static grpc_error* hs_init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { +static grpc_error_handle hs_init_call_elem(grpc_call_element* elem, + const grpc_call_element_args* args) { new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; } @@ -500,8 +504,8 @@ static void hs_destroy_call_elem(grpc_call_element* elem, } /* Constructor for channel_data */ -static grpc_error* hs_init_channel_elem(grpc_channel_element* elem, - grpc_channel_element_args* args) { +static grpc_error_handle hs_init_channel_elem(grpc_channel_element* elem, + grpc_channel_element_args* args) { channel_data* chand = static_cast(elem->channel_data); GPR_ASSERT(!args->is_last); chand->surface_user_agent = grpc_channel_arg_get_bool( diff --git a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc index 6c7b42a89b9..46af805f3fa 100644 --- a/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc +++ b/src/core/ext/filters/load_reporting/server_load_reporting_filter.cc @@ -32,9 +32,9 @@ #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" #include "src/core/ext/filters/load_reporting/registered_opencensus_objects.h" #include "src/core/ext/filters/load_reporting/server_load_reporting_filter.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/context.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils.h" @@ -50,7 +50,7 @@ constexpr char kEncodedIpv6AddressLengthString[] = "32"; constexpr char kEmptyAddressLengthString[] = "00"; constexpr size_t kLengthPrefixSize = 2; -grpc_error* ServerLoadReportingChannelData::Init( +grpc_error_handle ServerLoadReportingChannelData::Init( grpc_channel_element* /* elem */, grpc_channel_element_args* args) { GPR_ASSERT(!args->is_last); // Find and record the peer_identity. @@ -232,8 +232,8 @@ grpc_filtered_mdelem ServerLoadReportingCallData::RecvInitialMetadataFilter( return GRPC_FILTERED_MDELEM(md); } -void ServerLoadReportingCallData::RecvInitialMetadataReady(void* arg, - grpc_error* err) { +void ServerLoadReportingCallData::RecvInitialMetadataReady( + void* arg, grpc_error_handle err) { grpc_call_element* elem = reinterpret_cast(arg); ServerLoadReportingCallData* calld = reinterpret_cast(elem->call_data); @@ -264,7 +264,7 @@ void ServerLoadReportingCallData::RecvInitialMetadataReady(void* arg, GRPC_ERROR_REF(err)); } -grpc_error* ServerLoadReportingCallData::Init( +grpc_error_handle ServerLoadReportingCallData::Init( grpc_call_element* elem, const grpc_call_element_args* /*args*/) { service_method_ = grpc_empty_slice(); GRPC_CLOSURE_INIT(&recv_initial_metadata_ready_, RecvInitialMetadataReady, diff --git a/src/core/ext/filters/load_reporting/server_load_reporting_filter.h b/src/core/ext/filters/load_reporting/server_load_reporting_filter.h index 3bfdc989059..47390fa0219 100644 --- a/src/core/ext/filters/load_reporting/server_load_reporting_filter.h +++ b/src/core/ext/filters/load_reporting/server_load_reporting_filter.h @@ -30,8 +30,8 @@ namespace grpc { class ServerLoadReportingChannelData : public ChannelData { public: - grpc_error* Init(grpc_channel_element* elem, - grpc_channel_element_args* args) override; + grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args) override; // Getters. const char* peer_identity() { return peer_identity_; } @@ -45,8 +45,8 @@ class ServerLoadReportingChannelData : public ChannelData { class ServerLoadReportingCallData : public CallData { public: - grpc_error* Init(grpc_call_element* elem, - const grpc_call_element_args* args) override; + grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args) override; void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* then_call_closure) override; @@ -68,7 +68,7 @@ class ServerLoadReportingCallData : public CallData { static const char* GetStatusTagForStatus(grpc_status_code status); // Records the call start. - static void RecvInitialMetadataReady(void* arg, grpc_error* err); + static void RecvInitialMetadataReady(void* arg, grpc_error_handle err); // From the initial metadata, extracts the service_method_, target_host_, and // client_ip_and_lr_token_. diff --git a/src/core/ext/filters/max_age/max_age_filter.cc b/src/core/ext/filters/max_age/max_age_filter.cc index ee89272fcf3..97a4dc28c90 100644 --- a/src/core/ext/filters/max_age/max_age_filter.cc +++ b/src/core/ext/filters/max_age/max_age_filter.cc @@ -206,7 +206,8 @@ static void decrease_call_count(channel_data* chand) { } } -static void start_max_idle_timer_after_init(void* arg, grpc_error* /*error*/) { +static void start_max_idle_timer_after_init(void* arg, + grpc_error_handle /*error*/) { channel_data* chand = static_cast(arg); /* Decrease call_count. If there are no active calls at this time, max_idle_timer will start here. If the number of active calls is not 0, @@ -258,7 +259,8 @@ class ConnectivityWatcher : public AsyncConnectivityStateWatcherInterface { } // namespace grpc_core -static void start_max_age_timer_after_init(void* arg, grpc_error* /*error*/) { +static void start_max_age_timer_after_init(void* arg, + grpc_error_handle /*error*/) { channel_data* chand = static_cast(arg); { grpc_core::MutexLock lock(&chand->max_age_timer_mu); @@ -277,8 +279,8 @@ static void start_max_age_timer_after_init(void* arg, grpc_error* /*error*/) { "max_age start_max_age_timer_after_init"); } -static void start_max_age_grace_timer_after_goaway_op(void* arg, - grpc_error* /*error*/) { +static void start_max_age_grace_timer_after_goaway_op( + void* arg, grpc_error_handle /*error*/) { channel_data* chand = static_cast(arg); { grpc_core::MutexLock lock(&chand->max_age_timer_mu); @@ -307,7 +309,7 @@ static void close_max_idle_channel(channel_data* chand) { elem->filter->start_transport_op(elem, op); } -static void max_idle_timer_cb(void* arg, grpc_error* error) { +static void max_idle_timer_cb(void* arg, grpc_error_handle error) { channel_data* chand = static_cast(arg); if (error == GRPC_ERROR_NONE) { bool try_again = true; @@ -351,7 +353,7 @@ static void max_idle_timer_cb(void* arg, grpc_error* error) { GRPC_CHANNEL_STACK_UNREF(chand->channel_stack, "max_age max_idle_timer"); } -static void close_max_age_channel(void* arg, grpc_error* error) { +static void close_max_age_channel(void* arg, grpc_error_handle error) { channel_data* chand = static_cast(arg); { grpc_core::MutexLock lock(&chand->max_age_timer_mu); @@ -374,7 +376,7 @@ static void close_max_age_channel(void* arg, grpc_error* error) { GRPC_CHANNEL_STACK_UNREF(chand->channel_stack, "max_age max_age_timer"); } -static void force_close_max_age_channel(void* arg, grpc_error* error) { +static void force_close_max_age_channel(void* arg, grpc_error_handle error) { channel_data* chand = static_cast(arg); { grpc_core::MutexLock lock(&chand->max_age_timer_mu); @@ -412,7 +414,7 @@ add_random_max_connection_age_jitter_and_convert_to_grpc_millis(int value) { } /* Constructor for call_data. */ -static grpc_error* max_age_init_call_elem( +static grpc_error_handle max_age_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* /*args*/) { channel_data* chand = static_cast(elem->channel_data); increase_call_count(chand); @@ -428,8 +430,8 @@ static void max_age_destroy_call_elem( } /* Constructor for channel_data. */ -static grpc_error* max_age_init_channel_elem(grpc_channel_element* elem, - grpc_channel_element_args* args) { +static grpc_error_handle max_age_init_channel_elem( + grpc_channel_element* elem, grpc_channel_element_args* args) { channel_data* chand = static_cast(elem->channel_data); new (chand) channel_data(); chand->channel_stack = args->channel_stack; diff --git a/src/core/ext/filters/message_size/message_size_filter.cc b/src/core/ext/filters/message_size/message_size_filter.cc index 10a58d98066..3c921e28ecd 100644 --- a/src/core/ext/filters/message_size/message_size_filter.cc +++ b/src/core/ext/filters/message_size/message_size_filter.cc @@ -37,8 +37,9 @@ #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel_init.h" -static void recv_message_ready(void* user_data, grpc_error* error); -static void recv_trailing_metadata_ready(void* user_data, grpc_error* error); +static void recv_message_ready(void* user_data, grpc_error_handle error); +static void recv_trailing_metadata_ready(void* user_data, + grpc_error_handle error); namespace grpc_core { @@ -67,9 +68,10 @@ const MessageSizeParsedConfig* MessageSizeParsedConfig::GetFromCallContext( std::unique_ptr MessageSizeParser::ParsePerMethodParams(const grpc_channel_args* /*args*/, - const Json& json, grpc_error** error) { + const Json& json, + grpc_error_handle* error) { GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); - std::vector error_list; + std::vector error_list; // Max request size. int max_request_message_bytes = -1; auto it = json.object_value().find("maxRequestMessageBytes"); @@ -179,7 +181,7 @@ struct call_data { grpc_closure recv_message_ready; grpc_closure recv_trailing_metadata_ready; // The error caused by a message that is too large, or GRPC_ERROR_NONE - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; // Used by recv_message_ready. grpc_core::OrphanablePtr* recv_message = nullptr; // Original recv_message_ready callback, invoked after our own. @@ -187,20 +189,20 @@ struct call_data { // Original recv_trailing_metadata callback, invoked after our own. grpc_closure* original_recv_trailing_metadata_ready; bool seen_recv_trailing_metadata = false; - grpc_error* recv_trailing_metadata_error; + grpc_error_handle recv_trailing_metadata_error; }; } // namespace // Callback invoked when we receive a message. Here we check the max // receive message size. -static void recv_message_ready(void* user_data, grpc_error* error) { +static void recv_message_ready(void* user_data, grpc_error_handle error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); if (*calld->recv_message != nullptr && calld->limits.max_recv_size >= 0 && (*calld->recv_message)->length() > static_cast(calld->limits.max_recv_size)) { - grpc_error* new_error = grpc_error_set_int( + grpc_error_handle new_error = grpc_error_set_int( GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat("Received message larger than max (%u vs. %d)", (*calld->recv_message)->length(), @@ -233,7 +235,8 @@ static void recv_message_ready(void* user_data, grpc_error* error) { // Callback invoked on completion of recv_trailing_metadata // Notifies the recv_trailing_metadata batch of any message size failures -static void recv_trailing_metadata_ready(void* user_data, grpc_error* error) { +static void recv_trailing_metadata_ready(void* user_data, + grpc_error_handle error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); if (calld->next_recv_message_ready != nullptr) { @@ -291,7 +294,7 @@ static void message_size_start_transport_stream_op_batch( } // Constructor for call_data. -static grpc_error* message_size_init_call_elem( +static grpc_error_handle message_size_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* args) { channel_data* chand = static_cast(elem->channel_data); new (elem->call_data) call_data(elem, *chand, *args); @@ -315,7 +318,7 @@ grpc_core::MessageSizeParsedConfig::message_size_limits get_message_size_limits( } // Constructor for channel_data. -static grpc_error* message_size_init_channel_elem( +static grpc_error_handle message_size_init_channel_elem( grpc_channel_element* elem, grpc_channel_element_args* args) { GPR_ASSERT(!args->is_last); channel_data* chand = static_cast(elem->channel_data); diff --git a/src/core/ext/filters/message_size/message_size_filter.h b/src/core/ext/filters/message_size/message_size_filter.h index 0583a789267..6629803e4e1 100644 --- a/src/core/ext/filters/message_size/message_size_filter.h +++ b/src/core/ext/filters/message_size/message_size_filter.h @@ -51,7 +51,7 @@ class MessageSizeParser : public ServiceConfigParser::Parser { public: std::unique_ptr ParsePerMethodParams( const grpc_channel_args* /*args*/, const Json& json, - grpc_error** error) override; + grpc_error_handle* error) override; static void Register(); diff --git a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc index 7f9a4fcaf82..b2e8f3fd98f 100644 --- a/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc +++ b/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc @@ -54,7 +54,8 @@ static bool get_user_agent_mdelem(const grpc_metadata_batch* batch, } // Callback invoked when we receive an initial metadata. -static void recv_initial_metadata_ready(void* user_data, grpc_error* error) { +static void recv_initial_metadata_ready(void* user_data, + grpc_error_handle error) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); @@ -105,7 +106,7 @@ static void cronet_compression_start_transport_stream_op_batch( } // Constructor for call_data. -static grpc_error* cronet_compression_init_call_elem( +static grpc_error_handle cronet_compression_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* /*args*/) { call_data* calld = static_cast(elem->call_data); calld->next_recv_initial_metadata_ready = nullptr; @@ -122,7 +123,7 @@ static void cronet_compression_destroy_call_elem( grpc_closure* /*ignored*/) {} // Constructor for channel_data. -static grpc_error* cronet_compression_init_channel_elem( +static grpc_error_handle cronet_compression_init_channel_elem( grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -192,7 +193,7 @@ static bool register_workaround_cronet_compression( if (a == nullptr) { return true; } - if (grpc_channel_arg_get_bool(a, false) == false) { + if (!grpc_channel_arg_get_bool(a, false)) { return true; } return grpc_channel_stack_builder_prepend_filter( diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.cc b/src/core/ext/transport/chttp2/client/chttp2_connector.cc index 6ab3531121a..8b3d5d75d9c 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.cc +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.cc @@ -75,7 +75,7 @@ void Chttp2Connector::Connect(const Args& args, Result* result, args.channel_args, &addr, args.deadline); } -void Chttp2Connector::Shutdown(grpc_error* error) { +void Chttp2Connector::Shutdown(grpc_error_handle error) { MutexLock lock(&mu_); shutdown_ = true; if (handshake_mgr_ != nullptr) { @@ -89,7 +89,7 @@ void Chttp2Connector::Shutdown(grpc_error* error) { GRPC_ERROR_UNREF(error); } -void Chttp2Connector::Connected(void* arg, grpc_error* error) { +void Chttp2Connector::Connected(void* arg, grpc_error_handle error) { Chttp2Connector* self = static_cast(arg); bool unref = false; { @@ -131,14 +131,14 @@ void Chttp2Connector::StartHandshakeLocked() { namespace { void NullThenSchedClosure(const DebugLocation& location, grpc_closure** closure, - grpc_error* error) { + grpc_error_handle error) { grpc_closure* c = *closure; *closure = nullptr; ExecCtx::Run(location, c, error); } } // namespace -void Chttp2Connector::OnHandshakeDone(void* arg, grpc_error* error) { +void Chttp2Connector::OnHandshakeDone(void* arg, grpc_error_handle error) { auto* args = static_cast(arg); Chttp2Connector* self = static_cast(args->user_data); { @@ -178,7 +178,7 @@ void Chttp2Connector::OnHandshakeDone(void* arg, grpc_error* error) { self->Ref().release(); // Ref held by OnTimeout() grpc_chttp2_transport_start_reading(self->result_->transport, args->read_buffer, - &self->on_receive_settings_); + &self->on_receive_settings_, nullptr); GRPC_CLOSURE_INIT(&self->on_timeout_, OnTimeout, self, grpc_schedule_on_exec_ctx); grpc_timer_init(&self->timer_, self->args_.deadline, &self->on_timeout_); @@ -194,7 +194,7 @@ void Chttp2Connector::OnHandshakeDone(void* arg, grpc_error* error) { self->Unref(); } -void Chttp2Connector::OnReceiveSettings(void* arg, grpc_error* error) { +void Chttp2Connector::OnReceiveSettings(void* arg, grpc_error_handle error) { Chttp2Connector* self = static_cast(arg); { MutexLock lock(&self->mu_); @@ -220,7 +220,7 @@ void Chttp2Connector::OnReceiveSettings(void* arg, grpc_error* error) { self->Unref(); } -void Chttp2Connector::OnTimeout(void* arg, grpc_error* /*error*/) { +void Chttp2Connector::OnTimeout(void* arg, grpc_error_handle /*error*/) { Chttp2Connector* self = static_cast(arg); { MutexLock lock(&self->mu_); @@ -245,7 +245,7 @@ void Chttp2Connector::OnTimeout(void* arg, grpc_error* /*error*/) { self->Unref(); } -void Chttp2Connector::MaybeNotify(grpc_error* error) { +void Chttp2Connector::MaybeNotify(grpc_error_handle error) { if (notify_error_.has_value()) { GRPC_ERROR_UNREF(error); NullThenSchedClosure(DEBUG_LOCATION, ¬ify_, notify_error_.value()); diff --git a/src/core/ext/transport/chttp2/client/chttp2_connector.h b/src/core/ext/transport/chttp2/client/chttp2_connector.h index 7624b7f8f7e..59db078f3b7 100644 --- a/src/core/ext/transport/chttp2/client/chttp2_connector.h +++ b/src/core/ext/transport/chttp2/client/chttp2_connector.h @@ -33,14 +33,14 @@ class Chttp2Connector : public SubchannelConnector { ~Chttp2Connector() override; void Connect(const Args& args, Result* result, grpc_closure* notify) override; - void Shutdown(grpc_error* error) override; + void Shutdown(grpc_error_handle error) override; private: - static void Connected(void* arg, grpc_error* error); + static void Connected(void* arg, grpc_error_handle error); void StartHandshakeLocked(); - static void OnHandshakeDone(void* arg, grpc_error* error); - static void OnReceiveSettings(void* arg, grpc_error* error); - static void OnTimeout(void* arg, grpc_error* error); + static void OnHandshakeDone(void* arg, grpc_error_handle error); + static void OnReceiveSettings(void* arg, grpc_error_handle error); + static void OnTimeout(void* arg, grpc_error_handle error); // We cannot invoke notify_ until both OnTimeout() and OnReceiveSettings() // have been called since that is an indicator to the upper layer that we are @@ -51,7 +51,7 @@ class Chttp2Connector : public SubchannelConnector { // invoked, we call MaybeNotify() again to actually invoke the notify_ // callback. Note that this only happens if the handshake is done and the // connector is waiting on the SETTINGS frame. - void MaybeNotify(grpc_error* error); + void MaybeNotify(grpc_error_handle error); Mutex mu_; Args args_; @@ -66,7 +66,7 @@ class Chttp2Connector : public SubchannelConnector { grpc_closure on_receive_settings_; grpc_timer timer_; grpc_closure on_timeout_; - absl::optional notify_error_; + absl::optional notify_error_; RefCountedPtr handshake_mgr_; }; diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc index a325533b60c..58f274264a7 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc @@ -37,10 +37,11 @@ namespace grpc_core { class Chttp2InsecureClientChannelFactory : public ClientChannelFactory { public: - Subchannel* CreateSubchannel(const grpc_channel_args* args) override { + RefCountedPtr CreateSubchannel( + const grpc_channel_args* args) override { grpc_channel_args* new_args = grpc_default_authority_add_if_not_present(args); - Subchannel* s = + RefCountedPtr s = Subchannel::Create(MakeOrphanable(), new_args); grpc_channel_args_destroy(new_args); return s; @@ -50,7 +51,7 @@ class Chttp2InsecureClientChannelFactory : public ClientChannelFactory { namespace { grpc_channel* CreateChannel(const char* target, const grpc_channel_args* args, - grpc_error** error) { + grpc_error_handle* error) { if (target == nullptr) { gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); if (error != nullptr) { @@ -105,7 +106,7 @@ grpc_channel* grpc_insecure_channel_create(const char* target, const char* arg_to_remove = arg.key; grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove( args, &arg_to_remove, 1, &arg, 1); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; // Create channel. grpc_channel* channel = grpc_core::CreateChannel(target, new_args, &error); // Clean up. diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc b/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc index 27e64fb8f3e..4700093e310 100644 --- a/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +++ b/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc @@ -56,13 +56,13 @@ grpc_channel* grpc_insecure_channel_create_from_fd( grpc_transport* transport = grpc_create_chttp2_transport(final_args, client, true); GPR_ASSERT(transport); - grpc_error* error = nullptr; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_channel* channel = grpc_channel_create(target, final_args, GRPC_CLIENT_DIRECT_CHANNEL, transport, nullptr, &error); grpc_channel_args_destroy(final_args); if (channel != nullptr) { - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); grpc_core::ExecCtx::Get()->Flush(); } else { intptr_t integer; diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc index 7edf6aa34ed..5b00098d7b4 100644 --- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc @@ -28,9 +28,9 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/transport/chttp2/client/chttp2_connector.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/security_connector/security_connector.h" #include "src/core/lib/slice/slice_internal.h" @@ -43,14 +43,15 @@ namespace grpc_core { class Chttp2SecureClientChannelFactory : public ClientChannelFactory { public: - Subchannel* CreateSubchannel(const grpc_channel_args* args) override { + RefCountedPtr CreateSubchannel( + const grpc_channel_args* args) override { grpc_channel_args* new_args = GetSecureNamingChannelArgs(args); if (new_args == nullptr) { gpr_log(GPR_ERROR, "Failed to create channel args during subchannel creation."); return nullptr; } - Subchannel* s = + RefCountedPtr s = Subchannel::Create(MakeOrphanable(), new_args); grpc_channel_args_destroy(new_args); return s; @@ -128,7 +129,7 @@ class Chttp2SecureClientChannelFactory : public ClientChannelFactory { namespace { grpc_channel* CreateChannel(const char* target, const grpc_channel_args* args, - grpc_error** error) { + grpc_error_handle* error) { if (target == nullptr) { gpr_log(GPR_ERROR, "cannot create channel with NULL target name"); if (error != nullptr) { @@ -180,7 +181,7 @@ grpc_channel* grpc_secure_channel_create(grpc_channel_credentials* creds, 4, ((void*)creds, target, (void*)args, (void*)reserved)); GPR_ASSERT(reserved == nullptr); grpc_channel* channel = nullptr; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (creds != nullptr) { // Add channel args containing the client channel factory and channel // credentials. diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.cc b/src/core/ext/transport/chttp2/server/chttp2_server.cc index e930407f3f1..911af03b29b 100644 --- a/src/core/ext/transport/chttp2/server/chttp2_server.cc +++ b/src/core/ext/transport/chttp2/server/chttp2_server.cc @@ -38,6 +38,7 @@ #include "src/core/ext/filters/http/server/http_server_filter.h" #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/ext/transport/chttp2/transport/internal.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" @@ -46,7 +47,6 @@ #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/resource_quota.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/slice/slice_internal.h" @@ -61,14 +61,14 @@ const char kUnixAbstractUriPrefix[] = "unix-abstract:"; class Chttp2ServerListener : public Server::ListenerInterface { public: - static grpc_error* Create(Server* server, grpc_resolved_address* addr, - grpc_channel_args* args, - Chttp2ServerArgsModifier args_modifier, - int* port_num); + static grpc_error_handle Create(Server* server, grpc_resolved_address* addr, + grpc_channel_args* args, + Chttp2ServerArgsModifier args_modifier, + int* port_num); - static grpc_error* CreateWithAcceptor(Server* server, const char* name, - grpc_channel_args* args, - Chttp2ServerArgsModifier args_modifier); + static grpc_error_handle CreateWithAcceptor( + Server* server, const char* name, grpc_channel_args* args, + Chttp2ServerArgsModifier args_modifier); // Do not instantiate directly. Use one of the factory methods above. Chttp2ServerListener(Server* server, grpc_channel_args* args, @@ -90,98 +90,209 @@ class Chttp2ServerListener : public Server::ListenerInterface { class ConfigFetcherWatcher : public grpc_server_config_fetcher::WatcherInterface { public: - explicit ConfigFetcherWatcher(Chttp2ServerListener* listener) - : listener_(listener) {} - - void UpdateConfig(grpc_channel_args* args) override { - { - MutexLock lock(&listener_->mu_); - grpc_channel_args_destroy(listener_->args_); - grpc_error* error = GRPC_ERROR_NONE; - args = listener_->args_modifier_(args, &error); - if (error != GRPC_ERROR_NONE) { - // TODO(yashykt): Set state to close down connections immediately - // after accepting. - GPR_ASSERT(0); - } - listener_->args_ = args; - if (!listener_->shutdown_) return; // Already started listening. - } - int port_temp; - grpc_error* error = grpc_tcp_server_add_port( - listener_->tcp_server_, &listener_->resolved_address_, &port_temp); - if (error != GRPC_ERROR_NONE) { - GRPC_ERROR_UNREF(error); - gpr_log(GPR_ERROR, "Error adding port to server: %s", - grpc_error_string(error)); - // TODO(yashykt): We wouldn't need to assert here if we bound to the - // port earlier during AddPort. - GPR_ASSERT(0); - } - listener_->StartListening(); - } + explicit ConfigFetcherWatcher(RefCountedPtr listener) + : listener_(std::move(listener)) {} + + void UpdateConnectionManager( + RefCountedPtr + connection_manager) override; + + void StopServing() override; private: - Chttp2ServerListener* listener_; + RefCountedPtr listener_; }; - class ConnectionState : public RefCounted { + class ActiveConnection : public InternallyRefCounted { public: - ConnectionState(Chttp2ServerListener* listener, - grpc_pollset* accepting_pollset, - grpc_tcp_server_acceptor* acceptor, - RefCountedPtr handshake_mgr, - grpc_channel_args* args, grpc_endpoint* endpoint); + class HandshakingState : public InternallyRefCounted { + public: + HandshakingState(RefCountedPtr connection_ref, + grpc_pollset* accepting_pollset, + grpc_tcp_server_acceptor* acceptor, + grpc_channel_args* args); + + ~HandshakingState() override; + + void Orphan() override; - ~ConnectionState() override; + void Start(grpc_endpoint* endpoint, grpc_channel_args* args); + + // Needed to be able to grab an external ref in ActiveConnection::Start() + using InternallyRefCounted::Ref; + + private: + static void OnTimeout(void* arg, grpc_error_handle error); + static void OnReceiveSettings(void* arg, grpc_error_handle /* error */); + static void OnHandshakeDone(void* arg, grpc_error_handle error); + RefCountedPtr const connection_; + grpc_pollset* const accepting_pollset_; + grpc_tcp_server_acceptor* const acceptor_; + RefCountedPtr handshake_mgr_ + ABSL_GUARDED_BY(&connection_->mu_); + // State for enforcing handshake timeout on receiving HTTP/2 settings. + grpc_millis const deadline_; + grpc_timer timer_ ABSL_GUARDED_BY(&connection_->mu_); + grpc_closure on_timeout_ ABSL_GUARDED_BY(&connection_->mu_); + grpc_closure on_receive_settings_ ABSL_GUARDED_BY(&connection_->mu_); + grpc_pollset_set* const interested_parties_; + }; + + ActiveConnection(grpc_pollset* accepting_pollset, + grpc_tcp_server_acceptor* acceptor, + grpc_channel_args* args); + ~ActiveConnection() override; + + void Orphan() override; + + void SendGoAway(); + + void Start(RefCountedPtr listener, + grpc_endpoint* endpoint, grpc_channel_args* args); + + // Needed to be able to grab an external ref in + // Chttp2ServerListener::OnAccept() + using InternallyRefCounted::Ref; private: - static void OnTimeout(void* arg, grpc_error* error); - static void OnReceiveSettings(void* arg, grpc_error* error); - static void OnHandshakeDone(void* arg, grpc_error* error); - - Chttp2ServerListener* const listener_; - grpc_pollset* const accepting_pollset_; - grpc_tcp_server_acceptor* const acceptor_; - RefCountedPtr handshake_mgr_; - // State for enforcing handshake timeout on receiving HTTP/2 settings. - grpc_chttp2_transport* transport_ = nullptr; - grpc_millis deadline_; - grpc_timer timer_; - grpc_closure on_timeout_; - grpc_closure on_receive_settings_; - grpc_pollset_set* const interested_parties_; + static void OnClose(void* arg, grpc_error_handle error); + + RefCountedPtr listener_; + Mutex mu_ ABSL_ACQUIRED_AFTER(&listener_->mu_); + // Set by HandshakingState before the handshaking begins and reset when + // handshaking is done. + OrphanablePtr handshaking_state_ ABSL_GUARDED_BY(&mu_); + // Set by HandshakingState when handshaking is done and a valid transport is + // created. + grpc_chttp2_transport* transport_ ABSL_GUARDED_BY(&mu_) = nullptr; + grpc_closure on_close_; + bool shutdown_ ABSL_GUARDED_BY(&mu_) = false; }; + // To allow access to RefCounted<> like interface. + friend class RefCountedPtr; + + // Should only be called once so as to start the TCP server. void StartListening(); static void OnAccept(void* arg, grpc_endpoint* tcp, grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor); - RefCountedPtr CreateHandshakeManager(); - - static void TcpServerShutdownComplete(void* arg, grpc_error* error); + static void TcpServerShutdownComplete(void* arg, grpc_error_handle error); static void DestroyListener(Server* /*server*/, void* arg, grpc_closure* destroy_done); + // The interface required by RefCountedPtr<> has been manually implemented + // here to take a ref on tcp_server_ instead. Note that, the handshaker needs + // tcp_server_ to exist for the lifetime of the handshake since it's needed by + // acceptor. Sharing refs between the listener and tcp_server_ is just an + // optimization to avoid taking additional refs on the listener, since + // TcpServerShutdownComplete already holds a ref to the listener. + void IncrementRefCount() { grpc_tcp_server_ref(tcp_server_); } + void IncrementRefCount(const DebugLocation& /* location */, + const char* /* reason */) { + IncrementRefCount(); + } + + RefCountedPtr Ref() GRPC_MUST_USE_RESULT { + IncrementRefCount(); + return RefCountedPtr(this); + } + RefCountedPtr Ref(const DebugLocation& /* location */, + const char* /* reason */) + GRPC_MUST_USE_RESULT { + return Ref(); + } + + void Unref() { grpc_tcp_server_unref(tcp_server_); } + void Unref(const DebugLocation& /* location */, const char* /* reason */) { + Unref(); + } + Server* const server_; grpc_tcp_server* tcp_server_; grpc_resolved_address resolved_address_; - Chttp2ServerArgsModifier args_modifier_; - Mutex mu_; - grpc_channel_args* args_; // guarded by mu_ + Chttp2ServerArgsModifier const args_modifier_; ConfigFetcherWatcher* config_fetcher_watcher_ = nullptr; - bool shutdown_ = true; - grpc_closure tcp_server_shutdown_complete_; - grpc_closure* on_destroy_done_ = nullptr; - HandshakeManager* pending_handshake_mgrs_ = nullptr; + Mutex channel_args_mu_; + grpc_channel_args* args_ ABSL_GUARDED_BY(channel_args_mu_); + RefCountedPtr + connection_manager_ ABSL_GUARDED_BY(channel_args_mu_); + Mutex mu_; + // Signals whether grpc_tcp_server_start() has been called. + bool started_ ABSL_GUARDED_BY(mu_) = false; + // Signals whether grpc_tcp_server_start() has completed. + CondVar started_cv_ ABSL_GUARDED_BY(mu_); + // Signals whether new requests/connections are to be accepted. + bool is_serving_ ABSL_GUARDED_BY(mu_) = false; + // Signals whether the application has triggered shutdown. + bool shutdown_ ABSL_GUARDED_BY(mu_) = false; + std::map> connections_ + ABSL_GUARDED_BY(mu_); + grpc_closure tcp_server_shutdown_complete_ ABSL_GUARDED_BY(mu_); + grpc_closure* on_destroy_done_ ABSL_GUARDED_BY(mu_) = nullptr; RefCountedPtr channelz_listen_socket_; }; // -// Chttp2ServerListener::ConnectionState +// Chttp2ServerListener::ConfigFetcherWatcher +// + +void Chttp2ServerListener::ConfigFetcherWatcher::UpdateConnectionManager( + RefCountedPtr + connection_manager) { + RefCountedPtr + connection_manager_to_destroy; + { + MutexLock lock(&listener_->channel_args_mu_); + connection_manager_to_destroy = listener_->connection_manager_; + listener_->connection_manager_ = std::move(connection_manager); + } + { + MutexLock lock(&listener_->mu_); + if (listener_->shutdown_) { + return; + } + listener_->is_serving_ = true; + if (listener_->started_) return; + } + int port_temp; + grpc_error_handle error = grpc_tcp_server_add_port( + listener_->tcp_server_, &listener_->resolved_address_, &port_temp); + if (error != GRPC_ERROR_NONE) { + GRPC_ERROR_UNREF(error); + gpr_log(GPR_ERROR, "Error adding port to server: %s", + grpc_error_std_string(error).c_str()); + // TODO(yashykt): We wouldn't need to assert here if we bound to the + // port earlier during AddPort. + GPR_ASSERT(0); + } + listener_->StartListening(); + { + MutexLock lock(&listener_->mu_); + listener_->started_ = true; + listener_->started_cv_.SignalAll(); + } +} + +void Chttp2ServerListener::ConfigFetcherWatcher::StopServing() { + std::map> connections; + { + MutexLock lock(&listener_->mu_); + listener_->is_serving_ = false; + connections = std::move(listener_->connections_); + } + // Send GOAWAYs on the transports so that they disconnected when existing RPCs + // finish. + for (auto& connection : connections) { + connection.first->SendGoAway(); + } +} + +// +// Chttp2ServerListener::ActiveConnection::HandshakingState // grpc_millis GetConnectionDeadline(const grpc_channel_args* args) { @@ -191,73 +302,96 @@ grpc_millis GetConnectionDeadline(const grpc_channel_args* args) { return ExecCtx::Get()->Now() + timeout_ms; } -Chttp2ServerListener::ConnectionState::ConnectionState( - Chttp2ServerListener* listener, grpc_pollset* accepting_pollset, - grpc_tcp_server_acceptor* acceptor, - RefCountedPtr handshake_mgr, grpc_channel_args* args, - grpc_endpoint* endpoint) - : listener_(listener), +Chttp2ServerListener::ActiveConnection::HandshakingState::HandshakingState( + RefCountedPtr connection_ref, + grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor, + grpc_channel_args* args) + : connection_(std::move(connection_ref)), accepting_pollset_(accepting_pollset), acceptor_(acceptor), - handshake_mgr_(std::move(handshake_mgr)), + handshake_mgr_(MakeRefCounted()), deadline_(GetConnectionDeadline(args)), interested_parties_(grpc_pollset_set_create()) { grpc_pollset_set_add_pollset(interested_parties_, accepting_pollset_); HandshakerRegistry::AddHandshakers(HANDSHAKER_SERVER, args, interested_parties_, handshake_mgr_.get()); - handshake_mgr_->DoHandshake(endpoint, args, deadline_, acceptor_, - OnHandshakeDone, this); } -Chttp2ServerListener::ConnectionState::~ConnectionState() { - if (transport_ != nullptr) { - GRPC_CHTTP2_UNREF_TRANSPORT(transport_, "receive settings timeout"); - } +Chttp2ServerListener::ActiveConnection::HandshakingState::~HandshakingState() { grpc_pollset_set_del_pollset(interested_parties_, accepting_pollset_); grpc_pollset_set_destroy(interested_parties_); } -void Chttp2ServerListener::ConnectionState::OnTimeout(void* arg, - grpc_error* error) { - ConnectionState* self = static_cast(arg); +void Chttp2ServerListener::ActiveConnection::HandshakingState::Orphan() { + { + MutexLock lock(&connection_->mu_); + if (handshake_mgr_ != nullptr) { + handshake_mgr_->Shutdown( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Listener stopped serving.")); + } + } + Unref(); +} + +void Chttp2ServerListener::ActiveConnection::HandshakingState::Start( + grpc_endpoint* endpoint, grpc_channel_args* args) { + Ref().release(); // Held by OnHandshakeDone + RefCountedPtr handshake_mgr; + { + MutexLock lock(&connection_->mu_); + if (handshake_mgr_ == nullptr) return; + handshake_mgr = handshake_mgr_; + } + handshake_mgr->DoHandshake(endpoint, args, deadline_, acceptor_, + OnHandshakeDone, this); +} + +void Chttp2ServerListener::ActiveConnection::HandshakingState::OnTimeout( + void* arg, grpc_error_handle error) { + HandshakingState* self = static_cast(arg); // Note that we may be called with GRPC_ERROR_NONE when the timer fires // or with an error indicating that the timer system is being shut down. if (error != GRPC_ERROR_CANCELLED) { grpc_transport_op* op = grpc_make_transport_op(nullptr); op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Did not receive HTTP/2 settings before handshake timeout"); - grpc_transport_perform_op(&self->transport_->base, op); + grpc_chttp2_transport* transport = nullptr; + { + MutexLock lock(&self->connection_->mu_); + transport = self->connection_->transport_; + } + grpc_transport_perform_op(&transport->base, op); } self->Unref(); } -void Chttp2ServerListener::ConnectionState::OnReceiveSettings( - void* arg, grpc_error* error) { - ConnectionState* self = static_cast(arg); - if (error == GRPC_ERROR_NONE) { - grpc_timer_cancel(&self->timer_); - } +void Chttp2ServerListener::ActiveConnection::HandshakingState:: + OnReceiveSettings(void* arg, grpc_error_handle /* error */) { + HandshakingState* self = static_cast(arg); + grpc_timer_cancel(&self->timer_); self->Unref(); } -void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg, - grpc_error* error) { +void Chttp2ServerListener::ActiveConnection::HandshakingState::OnHandshakeDone( + void* arg, grpc_error_handle error) { auto* args = static_cast(arg); - ConnectionState* self = static_cast(args->user_data); + HandshakingState* self = static_cast(args->user_data); + OrphanablePtr handshaking_state_ref; + RefCountedPtr handshake_mgr; + bool cleanup_connection = false; + bool free_resource_quota = false; + grpc_resource_user* resource_user = + self->connection_->listener_->server_->default_resource_user(); { - MutexLock lock(&self->listener_->mu_); - grpc_resource_user* resource_user = - self->listener_->server_->default_resource_user(); - if (error != GRPC_ERROR_NONE || self->listener_->shutdown_) { - const char* error_str = grpc_error_string(error); - gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str); - if (resource_user != nullptr) { - grpc_resource_user_free(resource_user, - GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); - } + MutexLock connection_lock(&self->connection_->mu_); + if (error != GRPC_ERROR_NONE || self->connection_->shutdown_) { + std::string error_str = grpc_error_std_string(error); + gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str.c_str()); + cleanup_connection = true; + free_resource_quota = true; if (error == GRPC_ERROR_NONE && args->endpoint != nullptr) { - // We were shut down after handshaking completed successfully, so - // destroy the endpoint here. + // We were shut down or stopped serving after handshaking completed + // successfully, so destroy the endpoint here. // TODO(ctiller): It is currently necessary to shutdown endpoints // before destroying them, even if we know that there are no // pending read/write callbacks. This should be fixed, at which @@ -275,9 +409,11 @@ void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg, if (args->endpoint != nullptr) { grpc_transport* transport = grpc_create_chttp2_transport( args->args, args->endpoint, false, resource_user); - grpc_error* channel_init_err = self->listener_->server_->SetupTransport( - transport, self->accepting_pollset_, args->args, - grpc_chttp2_transport_get_socket_node(transport), resource_user); + grpc_error_handle channel_init_err = + self->connection_->listener_->server_->SetupTransport( + transport, self->accepting_pollset_, args->args, + grpc_chttp2_transport_get_socket_node(transport), + resource_user); if (channel_init_err == GRPC_ERROR_NONE) { // Use notify_on_receive_settings callback to enforce the // handshake deadline. @@ -287,48 +423,153 @@ void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg, // static_cast<> to a derived class. // TODO(roth): Change to static_cast<> when we C++-ify the // transport API. - self->transport_ = + self->connection_->transport_ = reinterpret_cast(transport); + GRPC_CHTTP2_REF_TRANSPORT(self->connection_->transport_, + "ActiveConnection"); // Held by connection_ self->Ref().release(); // Held by OnReceiveSettings(). GRPC_CLOSURE_INIT(&self->on_receive_settings_, OnReceiveSettings, self, grpc_schedule_on_exec_ctx); + // If the listener has been configured with a config fetcher, we need + // to watch on the transport being closed so that we can an updated + // list of active connections. + grpc_closure* on_close = nullptr; + if (self->connection_->listener_->config_fetcher_watcher_ != + nullptr) { + // Refs helds by OnClose() + self->connection_->Ref().release(); + on_close = &self->connection_->on_close_; + } else { + // Remove the connection from the connections_ map since OnClose() + // will not be invoked when a config fetcher is set. + cleanup_connection = true; + } grpc_chttp2_transport_start_reading(transport, args->read_buffer, - &self->on_receive_settings_); + &self->on_receive_settings_, + on_close); grpc_channel_args_destroy(args->args); self->Ref().release(); // Held by OnTimeout(). - GRPC_CHTTP2_REF_TRANSPORT( - reinterpret_cast(transport), - "receive settings timeout"); GRPC_CLOSURE_INIT(&self->on_timeout_, OnTimeout, self, grpc_schedule_on_exec_ctx); grpc_timer_init(&self->timer_, self->deadline_, &self->on_timeout_); } else { // Failed to create channel from transport. Clean up. gpr_log(GPR_ERROR, "Failed to create channel: %s", - grpc_error_string(channel_init_err)); + grpc_error_std_string(channel_init_err).c_str()); GRPC_ERROR_UNREF(channel_init_err); grpc_transport_destroy(transport); grpc_slice_buffer_destroy_internal(args->read_buffer); gpr_free(args->read_buffer); - if (resource_user != nullptr) { - grpc_resource_user_free(resource_user, - GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); - } + cleanup_connection = true; + free_resource_quota = true; grpc_channel_args_destroy(args->args); } } else { - if (resource_user != nullptr) { - grpc_resource_user_free(resource_user, - GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); - } + cleanup_connection = true; + free_resource_quota = true; } } - self->handshake_mgr_->RemoveFromPendingMgrList( - &self->listener_->pending_handshake_mgrs_); + // Since the handshake manager is done, the connection no longer needs to + // shutdown the handshake when the listener needs to stop serving. + // Avoid calling the destructor of HandshakeManager and HandshakingState + // from within the critical region. + handshake_mgr = std::move(self->handshake_mgr_); + handshaking_state_ref = std::move(self->connection_->handshaking_state_); } - self->handshake_mgr_.reset(); gpr_free(self->acceptor_); - grpc_tcp_server_unref(self->listener_->tcp_server_); + OrphanablePtr connection; + if (free_resource_quota && resource_user != nullptr) { + grpc_resource_user_free(resource_user, GRPC_RESOURCE_QUOTA_CHANNEL_SIZE); + } + if (cleanup_connection) { + MutexLock listener_lock(&self->connection_->listener_->mu_); + auto it = self->connection_->listener_->connections_.find( + self->connection_.get()); + if (it != self->connection_->listener_->connections_.end()) { + connection = std::move(it->second); + self->connection_->listener_->connections_.erase(it); + } + } + self->Unref(); +} + +// +// Chttp2ServerListener::ActiveConnection +// + +Chttp2ServerListener::ActiveConnection::ActiveConnection( + grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor, + grpc_channel_args* args) + : handshaking_state_(MakeOrphanable( + Ref(), accepting_pollset, acceptor, args)) { + GRPC_CLOSURE_INIT(&on_close_, ActiveConnection::OnClose, this, + grpc_schedule_on_exec_ctx); +} + +Chttp2ServerListener::ActiveConnection::~ActiveConnection() { + if (transport_ != nullptr) { + GRPC_CHTTP2_UNREF_TRANSPORT(transport_, "ActiveConnection"); + } +} + +void Chttp2ServerListener::ActiveConnection::Orphan() { + OrphanablePtr handshaking_state; + { + MutexLock lock(&mu_); + shutdown_ = true; + // Reset handshaking_state_ since we have been orphaned by the listener + // signaling that the listener has stopped serving. + handshaking_state = std::move(handshaking_state_); + } + Unref(); +} + +void Chttp2ServerListener::ActiveConnection::SendGoAway() { + grpc_chttp2_transport* transport = nullptr; + { + MutexLock lock(&mu_); + transport = transport_; + } + if (transport != nullptr) { + grpc_transport_op* op = grpc_make_transport_op(nullptr); + op->goaway_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Server is stopping to serve requests."); + grpc_transport_perform_op(&transport->base, op); + } +} + +void Chttp2ServerListener::ActiveConnection::Start( + RefCountedPtr listener, grpc_endpoint* endpoint, + grpc_channel_args* args) { + RefCountedPtr handshaking_state_ref; + listener_ = std::move(listener); + { + MutexLock lock(&mu_); + if (shutdown_) return; + // Hold a ref to HandshakingState to allow starting the handshake outside + // the critical region. + handshaking_state_ref = handshaking_state_->Ref(); + } + handshaking_state_ref->Start(endpoint, args); +} + +void Chttp2ServerListener::ActiveConnection::OnClose( + void* arg, grpc_error_handle /* error */) { + ActiveConnection* self = static_cast(arg); + OrphanablePtr connection; + { + MutexLock listener_lock(&self->listener_->mu_); + MutexLock connection_lock(&self->mu_); + // The node was already deleted from the connections_ list if the connection + // is shutdown. + if (!self->shutdown_) { + auto it = self->listener_->connections_.find(self); + if (it != self->listener_->connections_.end()) { + connection = std::move(it->second); + self->listener_->connections_.erase(it); + } + } + } self->Unref(); } @@ -336,15 +577,13 @@ void Chttp2ServerListener::ConnectionState::OnHandshakeDone(void* arg, // Chttp2ServerListener // -grpc_error* Chttp2ServerListener::Create(Server* server, - grpc_resolved_address* addr, - grpc_channel_args* args, - Chttp2ServerArgsModifier args_modifier, - int* port_num) { +grpc_error_handle Chttp2ServerListener::Create( + Server* server, grpc_resolved_address* addr, grpc_channel_args* args, + Chttp2ServerArgsModifier args_modifier, int* port_num) { Chttp2ServerListener* listener = nullptr; // The bulk of this method is inside of a lambda to make cleanup // easier without using goto. - grpc_error* error = [&]() { + grpc_error_handle error = [&]() { // Create Chttp2ServerListener. listener = new Chttp2ServerListener(server, args, args_modifier); error = grpc_tcp_server_create(&listener->tcp_server_shutdown_complete_, @@ -361,7 +600,7 @@ grpc_error* Chttp2ServerListener::Create(Server* server, // Create channelz node. if (grpc_channel_args_find_bool(args, GRPC_ARG_ENABLE_CHANNELZ, GRPC_ENABLE_CHANNELZ_DEFAULT)) { - std::string string_address = grpc_sockaddr_to_string(addr, false); + std::string string_address = grpc_sockaddr_to_uri(addr); listener->channelz_listen_socket_ = MakeRefCounted( string_address.c_str(), @@ -386,12 +625,12 @@ grpc_error* Chttp2ServerListener::Create(Server* server, return error; } -grpc_error* Chttp2ServerListener::CreateWithAcceptor( +grpc_error_handle Chttp2ServerListener::CreateWithAcceptor( Server* server, const char* name, grpc_channel_args* args, Chttp2ServerArgsModifier args_modifier) { Chttp2ServerListener* listener = new Chttp2ServerListener(server, args, args_modifier); - grpc_error* error = grpc_tcp_server_create( + grpc_error_handle error = grpc_tcp_server_create( &listener->tcp_server_shutdown_complete_, args, &listener->tcp_server_); if (error != GRPC_ERROR_NONE) { delete listener; @@ -414,6 +653,13 @@ Chttp2ServerListener::Chttp2ServerListener( } Chttp2ServerListener::~Chttp2ServerListener() { + // Flush queued work before destroying handshaker factory, since that + // may do a synchronous unref. + ExecCtx::Get()->Flush(); + if (on_destroy_done_ != nullptr) { + ExecCtx::Run(DEBUG_LOCATION, on_destroy_done_, GRPC_ERROR_NONE); + ExecCtx::Get()->Flush(); + } grpc_channel_args_destroy(args_); } @@ -422,24 +668,27 @@ void Chttp2ServerListener::Start( Server* /*server*/, const std::vector* /* pollsets */) { if (server_->config_fetcher() != nullptr) { grpc_channel_args* args = nullptr; - auto watcher = absl::make_unique(this); + auto watcher = absl::make_unique(Ref()); + config_fetcher_watcher_ = watcher.get(); { - MutexLock lock(&mu_); - config_fetcher_watcher_ = watcher.get(); + MutexLock lock(&channel_args_mu_); args = grpc_channel_args_copy(args_); } server_->config_fetcher()->StartWatch( grpc_sockaddr_to_string(&resolved_address_, false), args, std::move(watcher)); } else { + { + MutexLock lock(&mu_); + started_ = true; + is_serving_ = true; + } StartListening(); } } void Chttp2ServerListener::StartListening() { grpc_tcp_server_start(tcp_server_, &server_->pollsets(), OnAccept, this); - MutexLock lock(&mu_); - shutdown_ = false; } void Chttp2ServerListener::SetOnDestroyDone(grpc_closure* on_destroy_done) { @@ -447,67 +696,94 @@ void Chttp2ServerListener::SetOnDestroyDone(grpc_closure* on_destroy_done) { on_destroy_done_ = on_destroy_done; } -RefCountedPtr Chttp2ServerListener::CreateHandshakeManager() { - MutexLock lock(&mu_); - if (shutdown_) return nullptr; - grpc_resource_user* resource_user = server_->default_resource_user(); - if (resource_user != nullptr && - !grpc_resource_user_safe_alloc(resource_user, - GRPC_RESOURCE_QUOTA_CHANNEL_SIZE)) { - gpr_log(GPR_ERROR, - "Memory quota exhausted, rejecting connection, no handshaking."); - return nullptr; - } - auto handshake_mgr = MakeRefCounted(); - handshake_mgr->AddToPendingMgrList(&pending_handshake_mgrs_); - grpc_tcp_server_ref(tcp_server_); // Ref held by ConnectionState. - return handshake_mgr; -} - void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp, grpc_pollset* accepting_pollset, grpc_tcp_server_acceptor* acceptor) { Chttp2ServerListener* self = static_cast(arg); - RefCountedPtr handshake_mgr = - self->CreateHandshakeManager(); - if (handshake_mgr == nullptr) { - grpc_endpoint_shutdown(tcp, GRPC_ERROR_NONE); + grpc_channel_args* args = nullptr; + RefCountedPtr + connection_manager; + { + MutexLock lock(&self->channel_args_mu_); + args = grpc_channel_args_copy(self->args_); + connection_manager = self->connection_manager_; + } + auto endpoint_cleanup = [&](grpc_error_handle error) { + grpc_endpoint_shutdown(tcp, error); grpc_endpoint_destroy(tcp); gpr_free(acceptor); - return; + }; + if (self->server_->config_fetcher() != nullptr) { + if (connection_manager == nullptr) { + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No ConnectionManager configured. Closing connection."); + endpoint_cleanup(error); + grpc_channel_args_destroy(args); + return; + } + // TODO(yashykt): Maybe combine the following two arg modifiers into a + // single one. + absl::StatusOr args_result = + connection_manager->UpdateChannelArgsForConnection(args, tcp); + if (!args_result.ok()) { + gpr_log(GPR_DEBUG, "Closing connection: %s", + args_result.status().ToString().c_str()); + endpoint_cleanup(GRPC_ERROR_CREATE_FROM_COPIED_STRING( + args_result.status().ToString().c_str())); + return; + } + grpc_error_handle error = GRPC_ERROR_NONE; + args = self->args_modifier_(*args_result, &error); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_DEBUG, "Closing connection: %s", + grpc_error_std_string(error).c_str()); + endpoint_cleanup(error); + grpc_channel_args_destroy(args); + return; + } } - grpc_channel_args* args = nullptr; + auto connection = + MakeOrphanable(accepting_pollset, acceptor, args); + // Hold a ref to connection to allow starting handshake outside the + // critical region + RefCountedPtr connection_ref = connection->Ref(); + RefCountedPtr listener_ref; { MutexLock lock(&self->mu_); - args = grpc_channel_args_copy(self->args_); + // Shutdown the the connection if listener's stopped serving. + if (!self->shutdown_ && self->is_serving_) { + grpc_resource_user* resource_user = + self->server_->default_resource_user(); + if (resource_user != nullptr && + !grpc_resource_user_safe_alloc(resource_user, + GRPC_RESOURCE_QUOTA_CHANNEL_SIZE)) { + gpr_log( + GPR_ERROR, + "Memory quota exhausted, rejecting connection, no handshaking."); + } else { + // This ref needs to be taken in the critical region after having made + // sure that the listener has not been Orphaned, so as to avoid + // heap-use-after-free issues where `Ref()` is invoked when the ref of + // tcp_server_ has already reached 0. (Ref() implementation of + // Chttp2ServerListener is grpc_tcp_server_ref().) + listener_ref = self->Ref(); + self->connections_.emplace(connection.get(), std::move(connection)); + } + } + } + if (connection != nullptr) { + endpoint_cleanup(GRPC_ERROR_NONE); + } else { + connection_ref->Start(std::move(listener_ref), tcp, args); } - // Deletes itself when done. - new ConnectionState(self, accepting_pollset, acceptor, - std::move(handshake_mgr), args, tcp); grpc_channel_args_destroy(args); } void Chttp2ServerListener::TcpServerShutdownComplete(void* arg, - grpc_error* error) { + grpc_error_handle error) { Chttp2ServerListener* self = static_cast(arg); - /* ensure all threads have unlocked */ - grpc_closure* destroy_done = nullptr; - { - MutexLock lock(&self->mu_); - destroy_done = self->on_destroy_done_; - GPR_ASSERT(self->shutdown_); - if (self->pending_handshake_mgrs_ != nullptr) { - self->pending_handshake_mgrs_->ShutdownAllPending(GRPC_ERROR_REF(error)); - } - self->channelz_listen_socket_.reset(); - } - // Flush queued work before destroying handshaker factory, since that - // may do a synchronous unref. - ExecCtx::Get()->Flush(); - if (destroy_done != nullptr) { - ExecCtx::Run(DEBUG_LOCATION, destroy_done, GRPC_ERROR_REF(error)); - ExecCtx::Get()->Flush(); - } + self->channelz_listen_socket_.reset(); + GRPC_ERROR_UNREF(error); delete self; } @@ -519,10 +795,20 @@ void Chttp2ServerListener::Orphan() { if (config_fetcher_watcher_ != nullptr) { server_->config_fetcher()->CancelWatch(config_fetcher_watcher_); } + std::map> connections; grpc_tcp_server* tcp_server; { MutexLock lock(&mu_); shutdown_ = true; + is_serving_ = false; + // Orphan the connections so that they can start cleaning up. + connections = std::move(connections_); + // If the listener is currently set to be serving but has not been started + // yet, it means that `grpc_tcp_server_start` is in progress. Wait for the + // operation to finish to avoid causing races. + while (is_serving_ && !started_) { + started_cv_.Wait(&mu_); + } tcp_server = tcp_server_; } grpc_tcp_server_shutdown_listeners(tcp_server); @@ -535,19 +821,19 @@ void Chttp2ServerListener::Orphan() { // Chttp2ServerAddPort() // -grpc_error* Chttp2ServerAddPort(Server* server, const char* addr, - grpc_channel_args* args, - Chttp2ServerArgsModifier args_modifier, - int* port_num) { +grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr, + grpc_channel_args* args, + Chttp2ServerArgsModifier args_modifier, + int* port_num) { if (strncmp(addr, "external:", 9) == 0) { return grpc_core::Chttp2ServerListener::CreateWithAcceptor( server, addr, args, args_modifier); } *port_num = -1; grpc_resolved_addresses* resolved = nullptr; - std::vector error_list; + std::vector error_list; // Using lambda to avoid use of goto. - grpc_error* error = [&]() { + grpc_error_handle error = [&]() { if (absl::StartsWith(addr, kUnixUriPrefix)) { error = grpc_resolve_unix_domain_address( addr + sizeof(kUnixUriPrefix) - 1, &resolved); @@ -592,13 +878,13 @@ grpc_error* Chttp2ServerAddPort(Server* server, const char* addr, resolved->naddrs - error_list.size(), resolved->naddrs); error = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING( msg.c_str(), error_list.data(), error_list.size()); - gpr_log(GPR_INFO, "WARNING: %s", grpc_error_string(error)); + gpr_log(GPR_INFO, "WARNING: %s", grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); // we managed to bind some addresses: continue without error } return GRPC_ERROR_NONE; }(); // lambda end - for (grpc_error* error : error_list) { + for (grpc_error_handle error : error_list) { GRPC_ERROR_UNREF(error); } grpc_channel_args_destroy(args); diff --git a/src/core/ext/transport/chttp2/server/chttp2_server.h b/src/core/ext/transport/chttp2/server/chttp2_server.h index 10322e9af34..e4e6b7cc978 100644 --- a/src/core/ext/transport/chttp2/server/chttp2_server.h +++ b/src/core/ext/transport/chttp2/server/chttp2_server.h @@ -34,11 +34,11 @@ namespace grpc_core { // added to the server. Takes ownership of the args. Caller takes ownership of // returned args. On failure, the error parameter will be set. using Chttp2ServerArgsModifier = - std::function; + std::function; /// Adds a port to \a server. Sets \a port_num to the port number. /// Takes ownership of \a args. -grpc_error* Chttp2ServerAddPort( +grpc_error_handle Chttp2ServerAddPort( Server* server, const char* addr, grpc_channel_args* args, Chttp2ServerArgsModifier connection_args_modifier, int* port_num); diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc index 3a3d6f371e5..e00bc927cf1 100644 --- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc +++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2.cc @@ -30,7 +30,7 @@ namespace { grpc_channel_args* ModifyArgsForConnection(grpc_channel_args* args, - grpc_error** /*error*/) { + grpc_error_handle* /*error*/) { return args; } @@ -41,13 +41,12 @@ int grpc_server_add_insecure_http2_port(grpc_server* server, const char* addr) { int port_num = 0; GRPC_API_TRACE("grpc_server_add_insecure_http2_port(server=%p, addr=%s)", 2, (server, addr)); - grpc_error* err = grpc_core::Chttp2ServerAddPort( + grpc_error_handle err = grpc_core::Chttp2ServerAddPort( server->core_server.get(), addr, grpc_channel_args_copy(server->core_server->channel_args()), ModifyArgsForConnection, &port_num); if (err != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "%s", msg); + gpr_log(GPR_ERROR, "%s", grpc_error_std_string(err).c_str()); GRPC_ERROR_UNREF(err); } diff --git a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc index e27c90795fd..fd57939f21b 100644 --- a/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +++ b/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc @@ -51,16 +51,16 @@ void grpc_server_add_insecure_channel_from_fd(grpc_server* server, grpc_transport* transport = grpc_create_chttp2_transport( server_args, server_endpoint, false /* is_client */); - grpc_error* error = + grpc_error_handle error = core_server->SetupTransport(transport, nullptr, server_args, nullptr); if (error == GRPC_ERROR_NONE) { for (grpc_pollset* pollset : core_server->pollsets()) { grpc_endpoint_add_to_pollset(server_endpoint, pollset); } - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } else { gpr_log(GPR_ERROR, "Failed to create channel: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); grpc_transport_destroy(transport); } diff --git a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc index 563c3034902..f0a0eed9193 100644 --- a/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc +++ b/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc @@ -40,7 +40,7 @@ namespace { grpc_channel_args* ModifyArgsForConnection(grpc_channel_args* args, - grpc_error** error) { + grpc_error_handle* error) { grpc_server_credentials* server_credentials = grpc_find_server_credentials_in_args(args); if (server_credentials == nullptr) { @@ -69,7 +69,7 @@ grpc_channel_args* ModifyArgsForConnection(grpc_channel_args* args, int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr, grpc_server_credentials* creds) { grpc_core::ExecCtx exec_ctx; - grpc_error* err = GRPC_ERROR_NONE; + grpc_error_handle err = GRPC_ERROR_NONE; grpc_core::RefCountedPtr sc; int port_num = 0; grpc_channel_args* args = nullptr; @@ -121,8 +121,7 @@ int grpc_server_add_secure_http2_port(grpc_server* server, const char* addr, done: sc.reset(DEBUG_LOCATION, "server"); if (err != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "%s", msg); + gpr_log(GPR_ERROR, "%s", grpc_error_std_string(err).c_str()); GRPC_ERROR_UNREF(err); } diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 35c0512cada..1ff64756c92 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -100,23 +100,23 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount(false, "chttp2_refcount"); // forward declarations of various callbacks that we'll build closures around -static void write_action_begin_locked(void* t, grpc_error* error); -static void write_action(void* t, grpc_error* error); -static void write_action_end(void* t, grpc_error* error); -static void write_action_end_locked(void* t, grpc_error* error); +static void write_action_begin_locked(void* t, grpc_error_handle error); +static void write_action(void* t, grpc_error_handle error); +static void write_action_end(void* t, grpc_error_handle error); +static void write_action_end_locked(void* t, grpc_error_handle error); -static void read_action(void* t, grpc_error* error); -static void read_action_locked(void* t, grpc_error* error); +static void read_action(void* t, grpc_error_handle error); +static void read_action_locked(void* t, grpc_error_handle error); static void continue_read_action_locked(grpc_chttp2_transport* t); -static void complete_fetch(void* gs, grpc_error* error); -static void complete_fetch_locked(void* gs, grpc_error* error); +static void complete_fetch(void* gs, grpc_error_handle error); +static void complete_fetch_locked(void* gs, grpc_error_handle error); // Set a transport level setting, and push it to our peer static void queue_setting_update(grpc_chttp2_transport* t, grpc_chttp2_setting_id id, uint32_t value); static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_error* error); + grpc_error_handle error); // Start new streams that have been created if we can static void maybe_start_some_streams(grpc_chttp2_transport* t); @@ -126,45 +126,68 @@ static void connectivity_state_set(grpc_chttp2_transport* t, const absl::Status& status, const char* reason); -static void benign_reclaimer(void* arg, grpc_error* error); -static void destructive_reclaimer(void* arg, grpc_error* error); -static void benign_reclaimer_locked(void* arg, grpc_error* error); -static void destructive_reclaimer_locked(void* arg, grpc_error* error); +static void benign_reclaimer(void* arg, grpc_error_handle error); +static void destructive_reclaimer(void* arg, grpc_error_handle error); +static void benign_reclaimer_locked(void* arg, grpc_error_handle error); +static void destructive_reclaimer_locked(void* arg, grpc_error_handle error); static void post_benign_reclaimer(grpc_chttp2_transport* t); static void post_destructive_reclaimer(grpc_chttp2_transport* t); -static void close_transport_locked(grpc_chttp2_transport* t, grpc_error* error); -static void end_all_the_calls(grpc_chttp2_transport* t, grpc_error* error); - -static void start_bdp_ping(void* tp, grpc_error* error); -static void finish_bdp_ping(void* tp, grpc_error* error); -static void start_bdp_ping_locked(void* tp, grpc_error* error); -static void finish_bdp_ping_locked(void* tp, grpc_error* error); -static void next_bdp_ping_timer_expired(void* tp, grpc_error* error); -static void next_bdp_ping_timer_expired_locked(void* tp, grpc_error* error); - -static void cancel_pings(grpc_chttp2_transport* t, grpc_error* error); +static void close_transport_locked(grpc_chttp2_transport* t, + grpc_error_handle error); +static void end_all_the_calls(grpc_chttp2_transport* t, + grpc_error_handle error); + +static void start_bdp_ping(void* tp, grpc_error_handle error); +static void finish_bdp_ping(void* tp, grpc_error_handle error); +static void start_bdp_ping_locked(void* tp, grpc_error_handle error); +static void finish_bdp_ping_locked(void* tp, grpc_error_handle error); +static void next_bdp_ping_timer_expired(void* tp, grpc_error_handle error); +static void next_bdp_ping_timer_expired_locked(void* tp, + grpc_error_handle error); + +static void cancel_pings(grpc_chttp2_transport* t, grpc_error_handle error); static void send_ping_locked(grpc_chttp2_transport* t, grpc_closure* on_initiate, grpc_closure* on_ack); -static void retry_initiate_ping_locked(void* tp, grpc_error* error); +static void retry_initiate_ping_locked(void* tp, grpc_error_handle error); // keepalive-relevant functions -static void init_keepalive_ping(void* arg, grpc_error* error); -static void init_keepalive_ping_locked(void* arg, grpc_error* error); -static void start_keepalive_ping(void* arg, grpc_error* error); -static void finish_keepalive_ping(void* arg, grpc_error* error); -static void start_keepalive_ping_locked(void* arg, grpc_error* error); -static void finish_keepalive_ping_locked(void* arg, grpc_error* error); -static void keepalive_watchdog_fired(void* arg, grpc_error* error); -static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error); +static void init_keepalive_ping(void* arg, grpc_error_handle error); +static void init_keepalive_ping_locked(void* arg, grpc_error_handle error); +static void start_keepalive_ping(void* arg, grpc_error_handle error); +static void finish_keepalive_ping(void* arg, grpc_error_handle error); +static void start_keepalive_ping_locked(void* arg, grpc_error_handle error); +static void finish_keepalive_ping_locked(void* arg, grpc_error_handle error); +static void keepalive_watchdog_fired(void* arg, grpc_error_handle error); +static void keepalive_watchdog_fired_locked(void* arg, grpc_error_handle error); -static void reset_byte_stream(void* arg, grpc_error* error); +static void reset_byte_stream(void* arg, grpc_error_handle error); // Flow control default enabled. Can be disabled by setting // GRPC_EXPERIMENTAL_DISABLE_FLOW_CONTROL bool g_flow_control_enabled = true; +namespace grpc_core { + +namespace { +TestOnlyGlobalHttp2TransportInitCallback test_only_init_callback = nullptr; +TestOnlyGlobalHttp2TransportDestructCallback test_only_destruct_callback = + nullptr; +} // namespace + +void TestOnlySetGlobalHttp2TransportInitCallback( + TestOnlyGlobalHttp2TransportInitCallback callback) { + test_only_init_callback = callback; +} + +void TestOnlySetGlobalHttp2TransportDestructCallback( + TestOnlyGlobalHttp2TransportDestructCallback callback) { + test_only_destruct_callback = callback; +} + +} // namespace grpc_core + // // CONSTRUCTION/DESTRUCTION/REFCOUNTING // @@ -183,7 +206,7 @@ grpc_chttp2_transport::~grpc_chttp2_transport() { grpc_slice_buffer_destroy_internal(&outbuf); grpc_chttp2_hpack_compressor_destroy(&hpack_compressor); - grpc_error* error = + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"); // ContextList::Execute follows semantics of a callback function and does not // take a ref on error @@ -221,6 +244,9 @@ grpc_chttp2_transport::~grpc_chttp2_transport() { GRPC_ERROR_UNREF(closed_with_error); gpr_free(ping_acks); + if (grpc_core::test_only_destruct_callback != nullptr) { + grpc_core::test_only_destruct_callback(); + } } static const grpc_transport_vtable* get_vtable(void); @@ -366,7 +392,9 @@ static bool read_channel_args(grpc_chttp2_transport* t, t->channelz_socket = grpc_core::MakeRefCounted( std::string(grpc_endpoint_get_local_address(t->ep)), t->peer_string, - absl::StrFormat("%s %s", get_vtable()->name, t->peer_string)); + absl::StrFormat("%s %s", get_vtable()->name, t->peer_string), + grpc_core::channelz::SocketNode::Security::GetFromChannelArgs( + channel_args)); } return enable_bdp; } @@ -504,9 +532,12 @@ grpc_chttp2_transport::grpc_chttp2_transport( grpc_chttp2_initiate_write(this, GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE); post_benign_reclaimer(this); + if (grpc_core::test_only_init_callback != nullptr) { + grpc_core::test_only_init_callback(); + } } -static void destroy_transport_locked(void* tp, grpc_error* /*error*/) { +static void destroy_transport_locked(void* tp, grpc_error_handle /*error*/) { grpc_chttp2_transport* t = static_cast(tp); t->destroying = 1; close_transport_locked( @@ -524,7 +555,7 @@ static void destroy_transport(grpc_transport* gt) { } static void close_transport_locked(grpc_chttp2_transport* t, - grpc_error* error) { + grpc_error_handle error) { end_all_the_calls(t, GRPC_ERROR_REF(error)); cancel_pings(t, GRPC_ERROR_REF(error)); if (t->closed_with_error == GRPC_ERROR_NONE) { @@ -579,6 +610,11 @@ static void close_transport_locked(grpc_chttp2_transport* t, GRPC_ERROR_REF(error)); t->notify_on_receive_settings = nullptr; } + if (t->notify_on_close != nullptr) { + grpc_core::ExecCtx::Run(DEBUG_LOCATION, t->notify_on_close, + GRPC_ERROR_REF(error)); + t->notify_on_close = nullptr; + } GRPC_ERROR_UNREF(error); } @@ -698,7 +734,7 @@ static int init_stream(grpc_transport* gt, grpc_stream* gs, return 0; } -static void destroy_stream_locked(void* sp, grpc_error* /*error*/) { +static void destroy_stream_locked(void* sp, grpc_error_handle /*error*/) { GPR_TIMER_SCOPE("destroy_stream", 0); grpc_chttp2_stream* s = static_cast(sp); s->~grpc_chttp2_stream(); @@ -786,7 +822,7 @@ static void set_write_state(grpc_chttp2_transport* t, if (st == GRPC_CHTTP2_WRITE_STATE_IDLE) { grpc_core::ExecCtx::RunList(DEBUG_LOCATION, &t->run_after_write); if (t->close_transport_on_writes_finished != nullptr) { - grpc_error* err = t->close_transport_on_writes_finished; + grpc_error_handle err = t->close_transport_on_writes_finished; t->close_transport_on_writes_finished = nullptr; close_transport_locked(t, err); } @@ -918,7 +954,8 @@ static const char* begin_writing_desc(bool partial) { } } -static void write_action_begin_locked(void* gt, grpc_error* /*error_ignored*/) { +static void write_action_begin_locked(void* gt, + grpc_error_handle /*error_ignored*/) { GPR_TIMER_SCOPE("write_action_begin_locked", 0); grpc_chttp2_transport* t = static_cast(gt); GPR_ASSERT(t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE); @@ -957,7 +994,7 @@ static void write_action_begin_locked(void* gt, grpc_error* /*error_ignored*/) { } } -static void write_action(void* gt, grpc_error* /*error*/) { +static void write_action(void* gt, grpc_error_handle /*error*/) { GPR_TIMER_SCOPE("write_action", 0); grpc_chttp2_transport* t = static_cast(gt); void* cl = t->cl; @@ -969,7 +1006,7 @@ static void write_action(void* gt, grpc_error* /*error*/) { cl); } -static void write_action_end(void* tp, grpc_error* error) { +static void write_action_end(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); t->combiner->Run(GRPC_CLOSURE_INIT(&t->write_action_end_locked, write_action_end_locked, t, nullptr), @@ -978,7 +1015,7 @@ static void write_action_end(void* tp, grpc_error* error) { // Callback from the grpc_endpoint after bytes have been written by calling // sendmsg -static void write_action_end_locked(void* tp, grpc_error* error) { +static void write_action_end_locked(void* tp, grpc_error_handle error) { GPR_TIMER_SCOPE("terminate_writing_with_lock", 0); grpc_chttp2_transport* t = static_cast(tp); @@ -1067,7 +1104,7 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t, // received a GOAWAY with a non NO_ERROR code. if (goaway_error != GRPC_HTTP2_NO_ERROR) { gpr_log(GPR_INFO, "%s: Got goaway [%d] err=%s", t->peer_string.c_str(), - goaway_error, grpc_error_string(t->goaway_error)); + goaway_error, grpc_error_std_string(t->goaway_error).c_str()); } absl::Status status = grpc_error_to_absl_status(t->goaway_error); // When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug @@ -1173,7 +1210,8 @@ static void null_then_sched_closure(grpc_closure** closure) { void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, grpc_chttp2_stream* /*s*/, grpc_closure** pclosure, - grpc_error* error, const char* desc) { + grpc_error_handle error, + const char* desc) { grpc_closure* closure = *pclosure; *pclosure = nullptr; if (closure == nullptr) { @@ -1182,7 +1220,6 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, } closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT; if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { - const char* errstr = grpc_error_string(error); gpr_log( GPR_INFO, "complete_closure_step: t=%p %p refs=%d flags=0x%04x desc=%s err=%s " @@ -1192,7 +1229,8 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, CLOSURE_BARRIER_FIRST_REF_BIT), static_cast(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT), - desc, errstr, write_state_name(t->write_state)); + desc, grpc_error_std_string(error).c_str(), + write_state_name(t->write_state)); } if (error != GRPC_ERROR_NONE) { if (closure->error_data.error == GRPC_ERROR_NONE) { @@ -1281,7 +1319,8 @@ static void continue_fetching_send_locked(grpc_chttp2_transport* t, UINT32_MAX, GRPC_CLOSURE_INIT(&s->complete_fetch_locked, ::complete_fetch, s, grpc_schedule_on_exec_ctx))) { - grpc_error* error = s->fetching_send_message->Pull(&s->fetching_slice); + grpc_error_handle error = + s->fetching_send_message->Pull(&s->fetching_slice); if (error != GRPC_ERROR_NONE) { s->fetching_send_message.reset(); grpc_chttp2_cancel_stream(t, s, error); @@ -1292,14 +1331,14 @@ static void continue_fetching_send_locked(grpc_chttp2_transport* t, } } -static void complete_fetch(void* gs, grpc_error* error) { +static void complete_fetch(void* gs, grpc_error_handle error) { grpc_chttp2_stream* s = static_cast(gs); s->t->combiner->Run(GRPC_CLOSURE_INIT(&s->complete_fetch_locked, ::complete_fetch_locked, s, nullptr), GRPC_ERROR_REF(error)); } -static void complete_fetch_locked(void* gs, grpc_error* error) { +static void complete_fetch_locked(void* gs, grpc_error_handle error) { grpc_chttp2_stream* s = static_cast(gs); grpc_chttp2_transport* t = s->t; if (error == GRPC_ERROR_NONE) { @@ -1329,7 +1368,7 @@ static void log_metadata(const grpc_metadata_batch* md_batch, uint32_t id, } static void perform_stream_op_locked(void* stream_op, - grpc_error* /*error_ignored*/) { + grpc_error_handle /*error_ignored*/) { GPR_TIMER_SCOPE("perform_stream_op_locked", 0); grpc_transport_stream_op_batch* op = @@ -1613,7 +1652,7 @@ static void perform_stream_op(grpc_transport* gt, grpc_stream* gs, GRPC_ERROR_NONE); } -static void cancel_pings(grpc_chttp2_transport* t, grpc_error* error) { +static void cancel_pings(grpc_chttp2_transport* t, grpc_error_handle error) { // callback remaining pings: they're not allowed to call into the transport, // and maybe they hold resources that need to be freed grpc_chttp2_ping_queue* pq = &t->ping_queue; @@ -1680,14 +1719,14 @@ static void send_keepalive_ping_locked(grpc_chttp2_transport* t) { GRPC_ERROR_NONE); } -void grpc_chttp2_retry_initiate_ping(void* tp, grpc_error* error) { +void grpc_chttp2_retry_initiate_ping(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); t->combiner->Run(GRPC_CLOSURE_INIT(&t->retry_initiate_ping_locked, retry_initiate_ping_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void retry_initiate_ping_locked(void* tp, grpc_error* error) { +static void retry_initiate_ping_locked(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); t->ping_state.is_delayed_ping_timer_set = false; if (error == GRPC_ERROR_NONE) { @@ -1710,10 +1749,10 @@ void grpc_chttp2_ack_ping(grpc_chttp2_transport* t, uint64_t id) { } } -static void send_goaway(grpc_chttp2_transport* t, grpc_error* error) { +static void send_goaway(grpc_chttp2_transport* t, grpc_error_handle error) { // We want to log this irrespective of whether http tracing is enabled gpr_log(GPR_INFO, "%s: Sending goaway err=%s", t->peer_string.c_str(), - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED; grpc_http2_error_code http_error; grpc_slice slice; @@ -1751,7 +1790,7 @@ void grpc_chttp2_reset_ping_clock(grpc_chttp2_transport* t) { } static void perform_transport_op_locked(void* stream_op, - grpc_error* /*error_ignored*/) { + grpc_error_handle /*error_ignored*/) { grpc_transport_op* op = static_cast(stream_op); grpc_chttp2_transport* t = static_cast(op->handler_private.extra_arg); @@ -1831,7 +1870,7 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata( void grpc_chttp2_maybe_complete_recv_message(grpc_chttp2_transport* /*t*/, grpc_chttp2_stream* s) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (s->recv_message_ready != nullptr) { *s->recv_message = nullptr; if (s->final_metadata_requested && s->seen_error) { @@ -1981,7 +2020,7 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t, } static void remove_stream(grpc_chttp2_transport* t, uint32_t id, - grpc_error* error) { + grpc_error_handle error) { grpc_chttp2_stream* s = static_cast( grpc_chttp2_stream_map_delete(&t->stream_map, id)); GPR_DEBUG_ASSERT(s); @@ -2024,7 +2063,7 @@ static void remove_stream(grpc_chttp2_transport* t, uint32_t id, } void grpc_chttp2_cancel_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_error* due_to_error) { + grpc_error_handle due_to_error) { if (!t->is_client && !s->sent_trailing_metadata && grpc_error_has_clear_grpc_status(due_to_error)) { close_from_api(t, s, due_to_error); @@ -2048,7 +2087,7 @@ void grpc_chttp2_cancel_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s, } void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_error* error) { + grpc_error_handle error) { grpc_status_code status; grpc_slice slice; grpc_error_get_status(error, s->deadline, &status, &slice, nullptr, nullptr); @@ -2085,7 +2124,8 @@ void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s, GRPC_ERROR_UNREF(error); } -static void add_error(grpc_error* error, grpc_error** refs, size_t* nrefs) { +static void add_error(grpc_error_handle error, grpc_error_handle* refs, + size_t* nrefs) { if (error == GRPC_ERROR_NONE) return; for (size_t i = 0; i < *nrefs; i++) { if (error == refs[i]) { @@ -2096,14 +2136,15 @@ static void add_error(grpc_error* error, grpc_error** refs, size_t* nrefs) { ++*nrefs; } -static grpc_error* removal_error(grpc_error* extra_error, grpc_chttp2_stream* s, - const char* main_error_msg) { - grpc_error* refs[3]; +static grpc_error_handle removal_error(grpc_error_handle extra_error, + grpc_chttp2_stream* s, + const char* main_error_msg) { + grpc_error_handle refs[3]; size_t nrefs = 0; add_error(s->read_closed_error, refs, &nrefs); add_error(s->write_closed_error, refs, &nrefs); add_error(extra_error, refs, &nrefs); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (nrefs > 0) { error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(main_error_msg, refs, nrefs); @@ -2113,7 +2154,8 @@ static grpc_error* removal_error(grpc_error* extra_error, grpc_chttp2_stream* s, } static void flush_write_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_chttp2_write_cb** list, grpc_error* error) { + grpc_chttp2_write_cb** list, + grpc_error_handle error) { while (*list) { grpc_chttp2_write_cb* cb = *list; *list = cb->next; @@ -2126,7 +2168,8 @@ static void flush_write_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s, } void grpc_chttp2_fail_pending_writes(grpc_chttp2_transport* t, - grpc_chttp2_stream* s, grpc_error* error) { + grpc_chttp2_stream* s, + grpc_error_handle error) { error = removal_error(error, s, "Pending writes failed due to stream closure"); s->send_initial_metadata = nullptr; @@ -2150,10 +2193,10 @@ void grpc_chttp2_fail_pending_writes(grpc_chttp2_transport* t, void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t, grpc_chttp2_stream* s, int close_reads, - int close_writes, grpc_error* error) { + int close_writes, grpc_error_handle error) { if (s->read_closed && s->write_closed) { // already closed, but we should still fake the status if needed. - grpc_error* overall_error = removal_error(error, s, "Stream removed"); + grpc_error_handle overall_error = removal_error(error, s, "Stream removed"); if (overall_error != GRPC_ERROR_NONE) { grpc_chttp2_fake_status(t, s, overall_error); } @@ -2174,7 +2217,7 @@ void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t, } if (s->read_closed && s->write_closed) { became_closed = true; - grpc_error* overall_error = + grpc_error_handle overall_error = removal_error(GRPC_ERROR_REF(error), s, "Stream removed"); if (s->id != 0) { remove_stream(t, s->id, GRPC_ERROR_REF(overall_error)); @@ -2203,7 +2246,7 @@ void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t, } static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_error* error) { + grpc_error_handle error) { grpc_slice hdr; grpc_slice status_hdr; grpc_slice http_status_hdr; @@ -2361,7 +2404,7 @@ static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s, } struct cancel_stream_cb_args { - grpc_error* error; + grpc_error_handle error; grpc_chttp2_transport* t; }; @@ -2371,7 +2414,8 @@ static void cancel_stream_cb(void* user_data, uint32_t /*key*/, void* stream) { grpc_chttp2_cancel_stream(args->t, s, GRPC_ERROR_REF(args->error)); } -static void end_all_the_calls(grpc_chttp2_transport* t, grpc_error* error) { +static void end_all_the_calls(grpc_chttp2_transport* t, + grpc_error_handle error) { intptr_t http2_error; // If there is no explicit grpc or HTTP/2 error, set to UNAVAILABLE on server. if (!t->is_client && !grpc_error_has_clear_grpc_status(error) && @@ -2425,15 +2469,15 @@ void grpc_chttp2_act_on_flowctl_action( }); } -static grpc_error* try_http_parsing(grpc_chttp2_transport* t) { +static grpc_error_handle try_http_parsing(grpc_chttp2_transport* t) { grpc_http_parser parser; size_t i = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_http_response response; grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response); - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) { parse_error = grpc_http_parser_parse(&parser, t->read_buffer.slices[i], nullptr); @@ -2454,34 +2498,34 @@ static grpc_error* try_http_parsing(grpc_chttp2_transport* t) { return error; } -static void read_action(void* tp, grpc_error* error) { +static void read_action(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); t->combiner->Run( GRPC_CLOSURE_INIT(&t->read_action_locked, read_action_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void read_action_locked(void* tp, grpc_error* error) { +static void read_action_locked(void* tp, grpc_error_handle error) { GPR_TIMER_SCOPE("reading_action_locked", 0); grpc_chttp2_transport* t = static_cast(tp); GRPC_ERROR_REF(error); - grpc_error* err = error; + grpc_error_handle err = error; if (err != GRPC_ERROR_NONE) { err = grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Endpoint read failed", &err, 1), GRPC_ERROR_INT_OCCURRED_DURING_WRITE, t->write_state); } - GPR_SWAP(grpc_error*, err, error); + GPR_SWAP(grpc_error_handle, err, error); GRPC_ERROR_UNREF(err); if (t->closed_with_error == GRPC_ERROR_NONE) { GPR_TIMER_SCOPE("reading_action.parse", 0); size_t i = 0; - grpc_error* errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE, - GRPC_ERROR_NONE}; + grpc_error_handle errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE, + GRPC_ERROR_NONE}; for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) { errors[1] = grpc_chttp2_perform_read(t, t->read_buffer.slices[i]); } @@ -2572,18 +2616,18 @@ void schedule_bdp_ping_locked(grpc_chttp2_transport* t) { grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_BDP_PING); } -static void start_bdp_ping(void* tp, grpc_error* error) { +static void start_bdp_ping(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); t->combiner->Run(GRPC_CLOSURE_INIT(&t->start_bdp_ping_locked, start_bdp_ping_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void start_bdp_ping_locked(void* tp, grpc_error* error) { +static void start_bdp_ping_locked(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { gpr_log(GPR_INFO, "%s: Start BDP ping err=%s", t->peer_string.c_str(), - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } if (error != GRPC_ERROR_NONE || t->closed_with_error != GRPC_ERROR_NONE) { return; @@ -2596,18 +2640,18 @@ static void start_bdp_ping_locked(void* tp, grpc_error* error) { t->bdp_ping_started = true; } -static void finish_bdp_ping(void* tp, grpc_error* error) { +static void finish_bdp_ping(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); t->combiner->Run(GRPC_CLOSURE_INIT(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void finish_bdp_ping_locked(void* tp, grpc_error* error) { +static void finish_bdp_ping_locked(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { gpr_log(GPR_INFO, "%s: Complete BDP ping err=%s", t->peer_string.c_str(), - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } if (error != GRPC_ERROR_NONE || t->closed_with_error != GRPC_ERROR_NONE) { GRPC_CHTTP2_UNREF_TRANSPORT(t, "bdp_ping"); @@ -2633,7 +2677,7 @@ static void finish_bdp_ping_locked(void* tp, grpc_error* error) { &t->next_bdp_ping_timer_expired_locked); } -static void next_bdp_ping_timer_expired(void* tp, grpc_error* error) { +static void next_bdp_ping_timer_expired(void* tp, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); t->combiner->Run( GRPC_CLOSURE_INIT(&t->next_bdp_ping_timer_expired_locked, @@ -2641,7 +2685,8 @@ static void next_bdp_ping_timer_expired(void* tp, grpc_error* error) { GRPC_ERROR_REF(error)); } -static void next_bdp_ping_timer_expired_locked(void* tp, grpc_error* error) { +static void next_bdp_ping_timer_expired_locked(void* tp, + grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(tp); GPR_ASSERT(t->have_next_bdp_ping_timer); t->have_next_bdp_ping_timer = false; @@ -2717,14 +2762,14 @@ void grpc_chttp2_config_default_keepalive_args(grpc_channel_args* args, } } -static void init_keepalive_ping(void* arg, grpc_error* error) { +static void init_keepalive_ping(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); t->combiner->Run(GRPC_CLOSURE_INIT(&t->init_keepalive_ping_locked, init_keepalive_ping_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void init_keepalive_ping_locked(void* arg, grpc_error* error) { +static void init_keepalive_ping_locked(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING); if (t->destroying || t->closed_with_error != GRPC_ERROR_NONE) { @@ -2757,14 +2802,14 @@ static void init_keepalive_ping_locked(void* arg, grpc_error* error) { GRPC_CHTTP2_UNREF_TRANSPORT(t, "init keepalive ping"); } -static void start_keepalive_ping(void* arg, grpc_error* error) { +static void start_keepalive_ping(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); t->combiner->Run(GRPC_CLOSURE_INIT(&t->start_keepalive_ping_locked, start_keepalive_ping_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void start_keepalive_ping_locked(void* arg, grpc_error* error) { +static void start_keepalive_ping_locked(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); if (error != GRPC_ERROR_NONE) { return; @@ -2785,14 +2830,14 @@ static void start_keepalive_ping_locked(void* arg, grpc_error* error) { t->keepalive_ping_started = true; } -static void finish_keepalive_ping(void* arg, grpc_error* error) { +static void finish_keepalive_ping(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); t->combiner->Run(GRPC_CLOSURE_INIT(&t->finish_keepalive_ping_locked, finish_keepalive_ping_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void finish_keepalive_ping_locked(void* arg, grpc_error* error) { +static void finish_keepalive_ping_locked(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { @@ -2823,7 +2868,7 @@ static void finish_keepalive_ping_locked(void* arg, grpc_error* error) { GRPC_CHTTP2_UNREF_TRANSPORT(t, "keepalive ping end"); } -static void keepalive_watchdog_fired(void* arg, grpc_error* error) { +static void keepalive_watchdog_fired(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); t->combiner->Run( GRPC_CLOSURE_INIT(&t->keepalive_watchdog_fired_locked, @@ -2831,7 +2876,8 @@ static void keepalive_watchdog_fired(void* arg, grpc_error* error) { GRPC_ERROR_REF(error)); } -static void keepalive_watchdog_fired_locked(void* arg, grpc_error* error) { +static void keepalive_watchdog_fired_locked(void* arg, + grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) { if (error == GRPC_ERROR_NONE) { @@ -2888,7 +2934,7 @@ static void set_pollset_set(grpc_transport* gt, grpc_stream* /*gs*/, // BYTE STREAM // -static void reset_byte_stream(void* arg, grpc_error* error) { +static void reset_byte_stream(void* arg, grpc_error_handle error) { grpc_chttp2_stream* s = static_cast(arg); s->pending_byte_stream = false; if (error == GRPC_ERROR_NONE) { @@ -2919,8 +2965,8 @@ Chttp2IncomingByteStream::Chttp2IncomingByteStream( stream->byte_stream_error = GRPC_ERROR_NONE; } -void Chttp2IncomingByteStream::OrphanLocked(void* arg, - grpc_error* /*error_ignored*/) { +void Chttp2IncomingByteStream::OrphanLocked( + void* arg, grpc_error_handle /*error_ignored*/) { Chttp2IncomingByteStream* bs = static_cast(arg); grpc_chttp2_stream* s = bs->stream_; grpc_chttp2_transport* t = s->t; @@ -2939,7 +2985,7 @@ void Chttp2IncomingByteStream::Orphan() { } void Chttp2IncomingByteStream::NextLocked(void* arg, - grpc_error* /*error_ignored*/) { + grpc_error_handle /*error_ignored*/) { Chttp2IncomingByteStream* bs = static_cast(arg); grpc_chttp2_transport* t = bs->transport_; grpc_chttp2_stream* s = bs->stream_; @@ -3009,9 +3055,9 @@ void Chttp2IncomingByteStream::MaybeCreateStreamDecompressionCtx() { } } -grpc_error* Chttp2IncomingByteStream::Pull(grpc_slice* slice) { +grpc_error_handle Chttp2IncomingByteStream::Pull(grpc_slice* slice) { GPR_TIMER_SCOPE("incoming_byte_stream_pull", 0); - grpc_error* error; + grpc_error_handle error; if (stream_->unprocessed_incoming_frames_buffer.length > 0) { if (!stream_->unprocessed_incoming_frames_decompressed && stream_->stream_decompression_method != @@ -3054,7 +3100,7 @@ grpc_error* Chttp2IncomingByteStream::Pull(grpc_slice* slice) { return GRPC_ERROR_NONE; } -void Chttp2IncomingByteStream::PublishError(grpc_error* error) { +void Chttp2IncomingByteStream::PublishError(grpc_error_handle error) { GPR_ASSERT(error != GRPC_ERROR_NONE); grpc_core::ExecCtx::Run(DEBUG_LOCATION, stream_->on_next, GRPC_ERROR_REF(error)); @@ -3064,10 +3110,10 @@ void Chttp2IncomingByteStream::PublishError(grpc_error* error) { grpc_chttp2_cancel_stream(transport_, stream_, GRPC_ERROR_REF(error)); } -grpc_error* Chttp2IncomingByteStream::Push(const grpc_slice& slice, - grpc_slice* slice_out) { +grpc_error_handle Chttp2IncomingByteStream::Push(const grpc_slice& slice, + grpc_slice* slice_out) { if (remaining_bytes_ < GRPC_SLICE_LENGTH(slice)) { - grpc_error* error = + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many bytes in stream"); transport_->combiner->Run(&stream_->reset_byte_stream, GRPC_ERROR_REF(error)); @@ -3082,8 +3128,8 @@ grpc_error* Chttp2IncomingByteStream::Push(const grpc_slice& slice, } } -grpc_error* Chttp2IncomingByteStream::Finished(grpc_error* error, - bool reset_on_error) { +grpc_error_handle Chttp2IncomingByteStream::Finished(grpc_error_handle error, + bool reset_on_error) { if (error == GRPC_ERROR_NONE) { if (remaining_bytes_ != 0) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message"); @@ -3097,7 +3143,7 @@ grpc_error* Chttp2IncomingByteStream::Finished(grpc_error* error, return error; } -void Chttp2IncomingByteStream::Shutdown(grpc_error* error) { +void Chttp2IncomingByteStream::Shutdown(grpc_error_handle error) { GRPC_ERROR_UNREF(Finished(error, true /* reset_on_error */)); } @@ -3129,14 +3175,14 @@ static void post_destructive_reclaimer(grpc_chttp2_transport* t) { } } -static void benign_reclaimer(void* arg, grpc_error* error) { +static void benign_reclaimer(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); t->combiner->Run(GRPC_CLOSURE_INIT(&t->benign_reclaimer_locked, benign_reclaimer_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void benign_reclaimer_locked(void* arg, grpc_error* error) { +static void benign_reclaimer_locked(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); if (error == GRPC_ERROR_NONE && grpc_chttp2_stream_map_size(&t->stream_map) == 0) { @@ -3166,14 +3212,14 @@ static void benign_reclaimer_locked(void* arg, grpc_error* error) { GRPC_CHTTP2_UNREF_TRANSPORT(t, "benign_reclaimer"); } -static void destructive_reclaimer(void* arg, grpc_error* error) { +static void destructive_reclaimer(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); t->combiner->Run(GRPC_CLOSURE_INIT(&t->destructive_reclaimer_locked, destructive_reclaimer_locked, t, nullptr), GRPC_ERROR_REF(error)); } -static void destructive_reclaimer_locked(void* arg, grpc_error* error) { +static void destructive_reclaimer_locked(void* arg, grpc_error_handle error) { grpc_chttp2_transport* t = static_cast(arg); size_t n = grpc_chttp2_stream_map_size(&t->stream_map); t->destructive_reclaimer_registered = false; @@ -3291,7 +3337,7 @@ grpc_transport* grpc_create_chttp2_transport( void grpc_chttp2_transport_start_reading( grpc_transport* transport, grpc_slice_buffer* read_buffer, - grpc_closure* notify_on_receive_settings) { + grpc_closure* notify_on_receive_settings, grpc_closure* notify_on_close) { grpc_chttp2_transport* t = reinterpret_cast(transport); GRPC_CHTTP2_REF_TRANSPORT( @@ -3301,6 +3347,7 @@ void grpc_chttp2_transport_start_reading( gpr_free(read_buffer); } t->notify_on_receive_settings = notify_on_receive_settings; + t->notify_on_close = notify_on_close; t->combiner->Run( GRPC_CLOSURE_INIT(&t->read_action_locked, read_action_locked, t, nullptr), GRPC_ERROR_NONE); diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.h b/src/core/ext/transport/chttp2/transport/chttp2_transport.h index b04630bbe2b..a72d268d189 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.h +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.h @@ -47,6 +47,17 @@ grpc_chttp2_transport_get_socket_node(grpc_transport* transport); /// HTTP/2 settings are received from the peer. void grpc_chttp2_transport_start_reading( grpc_transport* transport, grpc_slice_buffer* read_buffer, - grpc_closure* notify_on_receive_settings); + grpc_closure* notify_on_receive_settings, grpc_closure* notify_on_close); + +namespace grpc_core { +typedef void (*TestOnlyGlobalHttp2TransportInitCallback)(); +typedef void (*TestOnlyGlobalHttp2TransportDestructCallback)(); + +void TestOnlySetGlobalHttp2TransportInitCallback( + TestOnlyGlobalHttp2TransportInitCallback callback); + +void TestOnlySetGlobalHttp2TransportDestructCallback( + TestOnlyGlobalHttp2TransportDestructCallback callback); +} // namespace grpc_core #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_CHTTP2_TRANSPORT_H */ diff --git a/src/core/ext/transport/chttp2/transport/context_list.cc b/src/core/ext/transport/chttp2/transport/context_list.cc index a0473ea822a..afb18abc238 100644 --- a/src/core/ext/transport/chttp2/transport/context_list.cc +++ b/src/core/ext/transport/chttp2/transport/context_list.cc @@ -22,7 +22,7 @@ namespace { void (*write_timestamps_callback_g)(void*, grpc_core::Timestamps*, - grpc_error* error) = nullptr; + grpc_error_handle error) = nullptr; void* (*get_copied_context_fn_g)(void*) = nullptr; } // namespace @@ -41,7 +41,7 @@ void ContextList::Append(ContextList** head, grpc_chttp2_stream* s) { } void ContextList::Execute(void* arg, grpc_core::Timestamps* ts, - grpc_error* error) { + grpc_error_handle error) { ContextList* head = static_cast(arg); ContextList* to_be_freed; while (head != nullptr) { @@ -57,9 +57,8 @@ void ContextList::Execute(void* arg, grpc_core::Timestamps* ts, } } -void grpc_http2_set_write_timestamps_callback(void (*fn)(void*, - grpc_core::Timestamps*, - grpc_error* error)) { +void grpc_http2_set_write_timestamps_callback( + void (*fn)(void*, grpc_core::Timestamps*, grpc_error_handle error)) { write_timestamps_callback_g = fn; } diff --git a/src/core/ext/transport/chttp2/transport/context_list.h b/src/core/ext/transport/chttp2/transport/context_list.h index 5b9d2ab3784..54ec87c67ff 100644 --- a/src/core/ext/transport/chttp2/transport/context_list.h +++ b/src/core/ext/transport/chttp2/transport/context_list.h @@ -36,7 +36,8 @@ class ContextList { /* Executes a function \a fn with each context in the list and \a ts. It also * frees up the entire list after this operation. It is intended as a callback * and hence does not take a ref on \a error */ - static void Execute(void* arg, grpc_core::Timestamps* ts, grpc_error* error); + static void Execute(void* arg, grpc_core::Timestamps* ts, + grpc_error_handle error); private: void* trace_context_ = nullptr; @@ -44,9 +45,8 @@ class ContextList { size_t byte_offset_ = 0; }; -void grpc_http2_set_write_timestamps_callback(void (*fn)(void*, - grpc_core::Timestamps*, - grpc_error* error)); +void grpc_http2_set_write_timestamps_callback( + void (*fn)(void*, grpc_core::Timestamps*, grpc_error_handle error)); void grpc_http2_set_fn_get_copied_context(void* (*fn)(void*)); } /* namespace grpc_core */ diff --git a/src/core/ext/transport/chttp2/transport/flow_control.cc b/src/core/ext/transport/chttp2/transport/flow_control.cc index 09bd7ab60a2..5f5e5515c79 100644 --- a/src/core/ext/transport/chttp2/transport/flow_control.cc +++ b/src/core/ext/transport/chttp2/transport/flow_control.cc @@ -203,7 +203,7 @@ uint32_t TransportFlowControl::MaybeSendUpdate(bool writing_anyway) { return 0; } -grpc_error* TransportFlowControl::ValidateRecvData( +grpc_error_handle TransportFlowControl::ValidateRecvData( int64_t incoming_frame_size) { if (incoming_frame_size > announced_window_) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -219,10 +219,10 @@ StreamFlowControl::StreamFlowControl(TransportFlowControl* tfc, const grpc_chttp2_stream* s) : tfc_(tfc), s_(s) {} -grpc_error* StreamFlowControl::RecvData(int64_t incoming_frame_size) { +grpc_error_handle StreamFlowControl::RecvData(int64_t incoming_frame_size) { FlowControlTrace trace(" data recv", tfc_, this); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; error = tfc_->ValidateRecvData(incoming_frame_size); if (error != GRPC_ERROR_NONE) return error; diff --git a/src/core/ext/transport/chttp2/transport/flow_control.h b/src/core/ext/transport/chttp2/transport/flow_control.h index 7e053585b18..e5088964b9e 100644 --- a/src/core/ext/transport/chttp2/transport/flow_control.h +++ b/src/core/ext/transport/chttp2/transport/flow_control.h @@ -168,7 +168,7 @@ class TransportFlowControlBase { // Called to do bookkeeping when a stream owned by this transport receives // data from the wire. Also does error checking for frame size. - virtual grpc_error* RecvData(int64_t /* incoming_frame_size */) = 0; + virtual grpc_error_handle RecvData(int64_t /* incoming_frame_size */) = 0; // Called to do bookkeeping when we receive a WINDOW_UPDATE frame. virtual void RecvUpdate(uint32_t /* size */) = 0; @@ -210,7 +210,7 @@ class TransportFlowControlDisabled final : public TransportFlowControlBase { FlowControlAction MakeAction() override { return FlowControlAction(); } FlowControlAction PeriodicUpdate() override { return FlowControlAction(); } void StreamSentData(int64_t /* size */) override {} - grpc_error* RecvData(int64_t /* incoming_frame_size */) override { + grpc_error_handle RecvData(int64_t /* incoming_frame_size */) override { return GRPC_ERROR_NONE; } void RecvUpdate(uint32_t /* size */) override {} @@ -246,14 +246,14 @@ class TransportFlowControl final : public TransportFlowControlBase { void StreamSentData(int64_t size) override { remote_window_ -= size; } - grpc_error* ValidateRecvData(int64_t incoming_frame_size); + grpc_error_handle ValidateRecvData(int64_t incoming_frame_size); void CommitRecvData(int64_t incoming_frame_size) { announced_window_ -= incoming_frame_size; } - grpc_error* RecvData(int64_t incoming_frame_size) override { + grpc_error_handle RecvData(int64_t incoming_frame_size) override { FlowControlTrace trace(" data recv", this, nullptr); - grpc_error* error = ValidateRecvData(incoming_frame_size); + grpc_error_handle error = ValidateRecvData(incoming_frame_size); if (error != GRPC_ERROR_NONE) return error; CommitRecvData(incoming_frame_size); return GRPC_ERROR_NONE; @@ -352,7 +352,7 @@ class StreamFlowControlBase { virtual void SentData(int64_t /* outgoing_frame_size */) = 0; // Bookkeeping and error checking for when data is received by this stream. - virtual grpc_error* RecvData(int64_t /* incoming_frame_size */) = 0; + virtual grpc_error_handle RecvData(int64_t /* incoming_frame_size */) = 0; // Called to check if this stream needs to send a WINDOW_UPDATE frame. virtual uint32_t MaybeSendUpdate() = 0; @@ -395,7 +395,7 @@ class StreamFlowControlDisabled : public StreamFlowControlBase { } FlowControlAction MakeAction() override { return FlowControlAction(); } void SentData(int64_t /* outgoing_frame_size */) override {} - grpc_error* RecvData(int64_t /* incoming_frame_size */) override { + grpc_error_handle RecvData(int64_t /* incoming_frame_size */) override { return GRPC_ERROR_NONE; } uint32_t MaybeSendUpdate() override { return 0; } @@ -427,7 +427,7 @@ class StreamFlowControl final : public StreamFlowControlBase { } // we have received data from the wire - grpc_error* RecvData(int64_t incoming_frame_size) override; + grpc_error_handle RecvData(int64_t incoming_frame_size) override; // returns an announce if we should send a stream update to our peer, else // returns zero diff --git a/src/core/ext/transport/chttp2/transport/frame_data.cc b/src/core/ext/transport/chttp2/transport/frame_data.cc index ccb28bb239e..745f32a28fe 100644 --- a/src/core/ext/transport/chttp2/transport/frame_data.cc +++ b/src/core/ext/transport/chttp2/transport/frame_data.cc @@ -41,7 +41,7 @@ grpc_chttp2_data_parser::~grpc_chttp2_data_parser() { GRPC_ERROR_UNREF(error); } -grpc_error* grpc_chttp2_data_parser_begin_frame( +grpc_error_handle grpc_chttp2_data_parser_begin_frame( grpc_chttp2_data_parser* /*parser*/, uint8_t flags, uint32_t stream_id, grpc_chttp2_stream* s) { if (flags & ~GRPC_CHTTP2_DATA_FLAG_END_STREAM) { @@ -89,11 +89,11 @@ void grpc_chttp2_encode_data(uint32_t id, grpc_slice_buffer* inbuf, stats->data_bytes += write_bytes; } -grpc_error* grpc_deframe_unprocessed_incoming_frames( +grpc_error_handle grpc_deframe_unprocessed_incoming_frames( grpc_chttp2_data_parser* p, grpc_chttp2_stream* s, grpc_slice_buffer* slices, grpc_slice* slice_out, grpc_core::OrphanablePtr* stream_out) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_chttp2_transport* t = s->t; while (slices->count > 0) { @@ -275,11 +275,11 @@ grpc_error* grpc_deframe_unprocessed_incoming_frames( return GRPC_ERROR_NONE; } -grpc_error* grpc_chttp2_data_parser_parse(void* /*parser*/, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last) { +grpc_error_handle grpc_chttp2_data_parser_parse(void* /*parser*/, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last) { if (!s->pending_byte_stream) { grpc_slice_ref_internal(slice); grpc_slice_buffer_add(&s->frame_storage, slice); diff --git a/src/core/ext/transport/chttp2/transport/frame_data.h b/src/core/ext/transport/chttp2/transport/frame_data.h index ec3890098ec..5aa4a3e7e80 100644 --- a/src/core/ext/transport/chttp2/transport/frame_data.h +++ b/src/core/ext/transport/chttp2/transport/frame_data.h @@ -50,31 +50,31 @@ struct grpc_chttp2_data_parser { grpc_chttp2_stream_state state = GRPC_CHTTP2_DATA_FH_0; uint8_t frame_type = 0; uint32_t frame_size = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; bool is_frame_compressed = false; grpc_core::Chttp2IncomingByteStream* parsing_frame = nullptr; }; /* start processing a new data frame */ -grpc_error* grpc_chttp2_data_parser_begin_frame(grpc_chttp2_data_parser* parser, - uint8_t flags, - uint32_t stream_id, - grpc_chttp2_stream* s); +grpc_error_handle grpc_chttp2_data_parser_begin_frame( + grpc_chttp2_data_parser* parser, uint8_t flags, uint32_t stream_id, + grpc_chttp2_stream* s); /* handle a slice of a data frame - is_last indicates the last slice of a frame */ -grpc_error* grpc_chttp2_data_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, int is_last); +grpc_error_handle grpc_chttp2_data_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last); void grpc_chttp2_encode_data(uint32_t id, grpc_slice_buffer* inbuf, uint32_t write_bytes, int is_eof, grpc_transport_one_way_stats* stats, grpc_slice_buffer* outbuf); -grpc_error* grpc_deframe_unprocessed_incoming_frames( +grpc_error_handle grpc_deframe_unprocessed_incoming_frames( grpc_chttp2_data_parser* p, grpc_chttp2_stream* s, grpc_slice_buffer* slices, grpc_slice* slice_out, grpc_core::OrphanablePtr* stream_out); diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.cc b/src/core/ext/transport/chttp2/transport/frame_goaway.cc index 3831b801598..a139bea15c8 100644 --- a/src/core/ext/transport/chttp2/transport/frame_goaway.cc +++ b/src/core/ext/transport/chttp2/transport/frame_goaway.cc @@ -36,9 +36,8 @@ void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p) { gpr_free(p->debug_data); } -grpc_error* grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser* p, - uint32_t length, - uint8_t /*flags*/) { +grpc_error_handle grpc_chttp2_goaway_parser_begin_frame( + grpc_chttp2_goaway_parser* p, uint32_t length, uint8_t /*flags*/) { if (length < 8) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat("goaway frame too short (%d bytes)", length).c_str()); @@ -52,11 +51,11 @@ grpc_error* grpc_chttp2_goaway_parser_begin_frame(grpc_chttp2_goaway_parser* p, return GRPC_ERROR_NONE; } -grpc_error* grpc_chttp2_goaway_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* /*s*/, - const grpc_slice& slice, - int is_last) { +grpc_error_handle grpc_chttp2_goaway_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* /*s*/, + const grpc_slice& slice, + int is_last) { const uint8_t* const beg = GRPC_SLICE_START_PTR(slice); const uint8_t* const end = GRPC_SLICE_END_PTR(slice); const uint8_t* cur = beg; diff --git a/src/core/ext/transport/chttp2/transport/frame_goaway.h b/src/core/ext/transport/chttp2/transport/frame_goaway.h index df6274d6286..674f7423091 100644 --- a/src/core/ext/transport/chttp2/transport/frame_goaway.h +++ b/src/core/ext/transport/chttp2/transport/frame_goaway.h @@ -47,13 +47,13 @@ struct grpc_chttp2_goaway_parser { }; void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser* p); void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p); -grpc_error* grpc_chttp2_goaway_parser_begin_frame( +grpc_error_handle grpc_chttp2_goaway_parser_begin_frame( grpc_chttp2_goaway_parser* parser, uint32_t length, uint8_t flags); -grpc_error* grpc_chttp2_goaway_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last); +grpc_error_handle grpc_chttp2_goaway_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last); void grpc_chttp2_goaway_append(uint32_t last_stream_id, uint32_t error_code, const grpc_slice& debug_data, diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.cc b/src/core/ext/transport/chttp2/transport/frame_ping.cc index 984123284a3..9da4a72af99 100644 --- a/src/core/ext/transport/chttp2/transport/frame_ping.cc +++ b/src/core/ext/transport/chttp2/transport/frame_ping.cc @@ -55,9 +55,8 @@ grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes) { return slice; } -grpc_error* grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser* parser, - uint32_t length, - uint8_t flags) { +grpc_error_handle grpc_chttp2_ping_parser_begin_frame( + grpc_chttp2_ping_parser* parser, uint32_t length, uint8_t flags) { if (flags & 0xfe || length != 8) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat("invalid ping: length=%d, flags=%02x", length, flags) @@ -69,11 +68,11 @@ grpc_error* grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser* parser, return GRPC_ERROR_NONE; } -grpc_error* grpc_chttp2_ping_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* /*s*/, - const grpc_slice& slice, - int is_last) { +grpc_error_handle grpc_chttp2_ping_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* /*s*/, + const grpc_slice& slice, + int is_last) { const uint8_t* const beg = GRPC_SLICE_START_PTR(slice); const uint8_t* const end = GRPC_SLICE_END_PTR(slice); const uint8_t* cur = beg; diff --git a/src/core/ext/transport/chttp2/transport/frame_ping.h b/src/core/ext/transport/chttp2/transport/frame_ping.h index e356bf43f07..6b5318e9dbb 100644 --- a/src/core/ext/transport/chttp2/transport/frame_ping.h +++ b/src/core/ext/transport/chttp2/transport/frame_ping.h @@ -31,12 +31,13 @@ struct grpc_chttp2_ping_parser { }; grpc_slice grpc_chttp2_ping_create(uint8_t ack, uint64_t opaque_8bytes); -grpc_error* grpc_chttp2_ping_parser_begin_frame(grpc_chttp2_ping_parser* parser, - uint32_t length, uint8_t flags); -grpc_error* grpc_chttp2_ping_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, int is_last); +grpc_error_handle grpc_chttp2_ping_parser_begin_frame( + grpc_chttp2_ping_parser* parser, uint32_t length, uint8_t flags); +grpc_error_handle grpc_chttp2_ping_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last); /* Test-only function for disabling ping ack */ void grpc_set_disable_ping_ack(bool disable_ping_ack); diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc b/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc index bcfcb173b66..03a7c61d569 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc @@ -68,7 +68,7 @@ void grpc_chttp2_add_rst_stream_to_next_write( grpc_chttp2_rst_stream_create(id, code, stats)); } -grpc_error* grpc_chttp2_rst_stream_parser_begin_frame( +grpc_error_handle grpc_chttp2_rst_stream_parser_begin_frame( grpc_chttp2_rst_stream_parser* parser, uint32_t length, uint8_t flags) { if (length != 4) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -80,11 +80,11 @@ grpc_error* grpc_chttp2_rst_stream_parser_begin_frame( return GRPC_ERROR_NONE; } -grpc_error* grpc_chttp2_rst_stream_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last) { +grpc_error_handle grpc_chttp2_rst_stream_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last) { const uint8_t* const beg = GRPC_SLICE_START_PTR(slice); const uint8_t* const end = GRPC_SLICE_END_PTR(slice); const uint8_t* cur = beg; @@ -104,7 +104,7 @@ grpc_error* grpc_chttp2_rst_stream_parser_parse(void* parser, ((static_cast(p->reason_bytes[1])) << 16) | ((static_cast(p->reason_bytes[2])) << 8) | ((static_cast(p->reason_bytes[3]))); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (reason != GRPC_HTTP2_NO_ERROR || s->metadata_buffer[1].size == 0) { error = grpc_error_set_int( grpc_error_set_str( diff --git a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h index e324ee2cfc3..865e74d9f8e 100644 --- a/src/core/ext/transport/chttp2/transport/frame_rst_stream.h +++ b/src/core/ext/transport/chttp2/transport/frame_rst_stream.h @@ -39,12 +39,12 @@ void grpc_chttp2_add_rst_stream_to_next_write( grpc_chttp2_transport* t, uint32_t id, uint32_t code, grpc_transport_one_way_stats* stats); -grpc_error* grpc_chttp2_rst_stream_parser_begin_frame( +grpc_error_handle grpc_chttp2_rst_stream_parser_begin_frame( grpc_chttp2_rst_stream_parser* parser, uint32_t length, uint8_t flags); -grpc_error* grpc_chttp2_rst_stream_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last); +grpc_error_handle grpc_chttp2_rst_stream_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_RST_STREAM_H */ diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.cc b/src/core/ext/transport/chttp2/transport/frame_settings.cc index 7dbfc69ea0d..576f8158c84 100644 --- a/src/core/ext/transport/chttp2/transport/frame_settings.cc +++ b/src/core/ext/transport/chttp2/transport/frame_settings.cc @@ -84,7 +84,7 @@ grpc_slice grpc_chttp2_settings_ack_create(void) { return output; } -grpc_error* grpc_chttp2_settings_parser_begin_frame( +grpc_error_handle grpc_chttp2_settings_parser_begin_frame( grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags, uint32_t* settings) { parser->target_settings = settings; @@ -110,10 +110,11 @@ grpc_error* grpc_chttp2_settings_parser_begin_frame( } } -grpc_error* grpc_chttp2_settings_parser_parse(void* p, grpc_chttp2_transport* t, - grpc_chttp2_stream* /*s*/, - const grpc_slice& slice, - int is_last) { +grpc_error_handle grpc_chttp2_settings_parser_parse(void* p, + grpc_chttp2_transport* t, + grpc_chttp2_stream* /*s*/, + const grpc_slice& slice, + int is_last) { grpc_chttp2_settings_parser* parser = static_cast(p); const uint8_t* cur = GRPC_SLICE_START_PTR(slice); diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.h b/src/core/ext/transport/chttp2/transport/frame_settings.h index 147d5ea3a33..7268277aba5 100644 --- a/src/core/ext/transport/chttp2/transport/frame_settings.h +++ b/src/core/ext/transport/chttp2/transport/frame_settings.h @@ -49,13 +49,13 @@ grpc_slice grpc_chttp2_settings_create(uint32_t* old_settings, /* Create an ack settings frame */ grpc_slice grpc_chttp2_settings_ack_create(void); -grpc_error* grpc_chttp2_settings_parser_begin_frame( +grpc_error_handle grpc_chttp2_settings_parser_begin_frame( grpc_chttp2_settings_parser* parser, uint32_t length, uint8_t flags, uint32_t* settings); -grpc_error* grpc_chttp2_settings_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last); +grpc_error_handle grpc_chttp2_settings_parser_parse(void* parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_SETTINGS_H */ diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.cc b/src/core/ext/transport/chttp2/transport/frame_window_update.cc index 943ea177cbb..37e69ff058e 100644 --- a/src/core/ext/transport/chttp2/transport/frame_window_update.cc +++ b/src/core/ext/transport/chttp2/transport/frame_window_update.cc @@ -53,7 +53,7 @@ grpc_slice grpc_chttp2_window_update_create( return slice; } -grpc_error* grpc_chttp2_window_update_parser_begin_frame( +grpc_error_handle grpc_chttp2_window_update_parser_begin_frame( grpc_chttp2_window_update_parser* parser, uint32_t length, uint8_t flags) { if (flags || length != 4) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -66,11 +66,9 @@ grpc_error* grpc_chttp2_window_update_parser_begin_frame( return GRPC_ERROR_NONE; } -grpc_error* grpc_chttp2_window_update_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last) { +grpc_error_handle grpc_chttp2_window_update_parser_parse( + void* parser, grpc_chttp2_transport* t, grpc_chttp2_stream* s, + const grpc_slice& slice, int is_last) { const uint8_t* const beg = GRPC_SLICE_START_PTR(slice); const uint8_t* const end = GRPC_SLICE_END_PTR(slice); const uint8_t* cur = beg; diff --git a/src/core/ext/transport/chttp2/transport/frame_window_update.h b/src/core/ext/transport/chttp2/transport/frame_window_update.h index 340445d87a4..5a07b9e5921 100644 --- a/src/core/ext/transport/chttp2/transport/frame_window_update.h +++ b/src/core/ext/transport/chttp2/transport/frame_window_update.h @@ -33,12 +33,10 @@ struct grpc_chttp2_window_update_parser { grpc_slice grpc_chttp2_window_update_create( uint32_t id, uint32_t window_delta, grpc_transport_one_way_stats* stats); -grpc_error* grpc_chttp2_window_update_parser_begin_frame( +grpc_error_handle grpc_chttp2_window_update_parser_begin_frame( grpc_chttp2_window_update_parser* parser, uint32_t length, uint8_t flags); -grpc_error* grpc_chttp2_window_update_parser_parse(void* parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last); +grpc_error_handle grpc_chttp2_window_update_parser_parse( + void* parser, grpc_chttp2_transport* t, grpc_chttp2_stream* s, + const grpc_slice& slice, int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_FRAME_WINDOW_UPDATE_H */ diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc index 4ceaec24b3d..cc1eba96582 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc @@ -104,7 +104,7 @@ struct SliceRefComparator { struct MetadataComparator { typedef grpc_mdelem Type; - static const grpc_mdelem Null() { return {0}; } + static grpc_mdelem Null() { return {0}; } static bool IsNull(const grpc_mdelem md) { return md.payload == 0; } static bool Equals(const grpc_mdelem md1, const grpc_mdelem md2) { return md1.payload == md2.payload; diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/src/core/ext/transport/chttp2/transport/hpack_parser.cc index 668c2cb75b5..99c308f078b 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.cc +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.cc @@ -67,71 +67,82 @@ typedef enum { a set of indirect jumps, and so not waste stack space. */ /* forward declarations for parsing states */ -static grpc_error* parse_begin(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_error(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end, grpc_error* error); -static grpc_error* still_parse_error(grpc_chttp2_hpack_parser* p, +static grpc_error_handle parse_begin(grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_illegal_op(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); - -static grpc_error* parse_string_prefix(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_key_string(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_value_string_with_indexed_key( +static grpc_error_handle parse_error(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end, + grpc_error_handle error); +static grpc_error_handle still_parse_error(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_illegal_op(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); + +static grpc_error_handle parse_string_prefix(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_key_string(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_value_string_with_indexed_key( grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_value_string_with_literal_key( +static grpc_error_handle parse_value_string_with_literal_key( grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_value0(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_value1(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_value2(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_value3(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_value4(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_value5up(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); - -static grpc_error* parse_indexed_field(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_indexed_field_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_lithdr_incidx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_lithdr_incidx_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_lithdr_notidx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_lithdr_notidx_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_lithdr_nvridx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end); -static grpc_error* parse_max_tbl_size(grpc_chttp2_hpack_parser* p, +static grpc_error_handle parse_value0(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end); +static grpc_error_handle parse_value1(grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end); -static grpc_error* parse_max_tbl_size_x(grpc_chttp2_hpack_parser* p, +static grpc_error_handle parse_value2(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end); +static grpc_error_handle parse_value3(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end); +static grpc_error_handle parse_value4(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end); +static grpc_error_handle parse_value5up(grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end); +static grpc_error_handle parse_indexed_field(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_indexed_field_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_incidx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_incidx_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_notidx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_notidx_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_nvridx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_max_tbl_size(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); +static grpc_error_handle parse_max_tbl_size_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end); + /* we translate the first byte of a hpack field into one of these decoding cases, then use a lookup table to jump directly to the appropriate parser. @@ -647,14 +658,14 @@ static void GPR_ATTRIBUTE_NOINLINE on_hdr_log(grpc_mdelem md) { /* emission helpers */ template -static grpc_error* on_hdr(grpc_chttp2_hpack_parser* p, grpc_mdelem md) { +static grpc_error_handle on_hdr(grpc_chttp2_hpack_parser* p, grpc_mdelem md) { if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_chttp2_hpack_parser)) { on_hdr_log(md); } if (do_add) { GPR_DEBUG_ASSERT(GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_INTERNED || GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC); - grpc_error* err = grpc_chttp2_hptbl_add(&p->table, md); + grpc_error_handle err = grpc_chttp2_hptbl_add(&p->table, md); if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) return err; } return p->on_header(p->on_header_user_data, md); @@ -693,16 +704,16 @@ static grpc_core::ManagedMemorySlice take_string_intern( } /* jump to the next state */ -static grpc_error* parse_next(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_next(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { p->state = *p->next_state++; return p->state(p, cur, end); } /* begin parsing a header: all functionality is encoded into lookup tables above */ -static grpc_error* parse_begin(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_begin(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { if (cur == end) { p->state = parse_begin; return GRPC_ERROR_NONE; @@ -712,8 +723,9 @@ static grpc_error* parse_begin(grpc_chttp2_hpack_parser* p, const uint8_t* cur, } /* stream dependency and prioritization data: we just skip it */ -static grpc_error* parse_stream_weight(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_stream_weight(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (cur == end) { p->state = parse_stream_weight; return GRPC_ERROR_NONE; @@ -722,8 +734,9 @@ static grpc_error* parse_stream_weight(grpc_chttp2_hpack_parser* p, return p->after_prioritization(p, cur + 1, end); } -static grpc_error* parse_stream_dep3(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_stream_dep3(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (cur == end) { p->state = parse_stream_dep3; return GRPC_ERROR_NONE; @@ -732,8 +745,9 @@ static grpc_error* parse_stream_dep3(grpc_chttp2_hpack_parser* p, return parse_stream_weight(p, cur + 1, end); } -static grpc_error* parse_stream_dep2(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_stream_dep2(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (cur == end) { p->state = parse_stream_dep2; return GRPC_ERROR_NONE; @@ -742,8 +756,9 @@ static grpc_error* parse_stream_dep2(grpc_chttp2_hpack_parser* p, return parse_stream_dep3(p, cur + 1, end); } -static grpc_error* parse_stream_dep1(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_stream_dep1(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (cur == end) { p->state = parse_stream_dep1; return GRPC_ERROR_NONE; @@ -752,8 +767,9 @@ static grpc_error* parse_stream_dep1(grpc_chttp2_hpack_parser* p, return parse_stream_dep2(p, cur + 1, end); } -static grpc_error* parse_stream_dep0(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_stream_dep0(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (cur == end) { p->state = parse_stream_dep0; return GRPC_ERROR_NONE; @@ -762,7 +778,7 @@ static grpc_error* parse_stream_dep0(grpc_chttp2_hpack_parser* p, return parse_stream_dep1(p, cur + 1, end); } -static grpc_error* GPR_ATTRIBUTE_NOINLINE +static grpc_error_handle GPR_ATTRIBUTE_NOINLINE on_invalid_hpack_idx(grpc_chttp2_hpack_parser* p) { return grpc_error_set_int( grpc_error_set_int( @@ -772,22 +788,23 @@ on_invalid_hpack_idx(grpc_chttp2_hpack_parser* p) { } /* emit an indexed field; jumps to begin the next field on completion */ -static grpc_error* finish_indexed_field(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_indexed_field(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { grpc_mdelem md = grpc_chttp2_hptbl_lookup(&p->table, p->index); if (GPR_UNLIKELY(GRPC_MDISNULL(md))) { return on_invalid_hpack_idx(p); } GRPC_STATS_INC_HPACK_RECV_INDEXED(); - grpc_error* err = on_hdr(p, md); + grpc_error_handle err = on_hdr(p, md); if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) return err; return parse_begin(p, cur, end); } /* parse an indexed field with index < 127 */ -static grpc_error* parse_indexed_field(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_indexed_field(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { p->dynamic_table_update_allowed = 0; p->index = (*cur) & 0x7f; p->md_for_index.payload = 0; /* Invalidate cached md when index changes. */ @@ -795,9 +812,9 @@ static grpc_error* parse_indexed_field(grpc_chttp2_hpack_parser* p, } /* parse an indexed field with index >= 127 */ -static grpc_error* parse_indexed_field_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_indexed_field_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { finish_indexed_field}; p->dynamic_table_update_allowed = 0; @@ -830,12 +847,12 @@ static const grpc_core::ManagedMemorySlice& get_indexed_key(grpc_mdelem md) { } /* finish a literal header with incremental indexing */ -static grpc_error* finish_lithdr_incidx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_lithdr_incidx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX(); grpc_mdelem md = get_precomputed_md_for_idx(p); - grpc_error* err = on_hdr( + grpc_error_handle err = on_hdr( p, grpc_mdelem_from_slices(get_indexed_key(md), take_string_intern(p, &p->value))); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); @@ -843,11 +860,11 @@ static grpc_error* finish_lithdr_incidx(grpc_chttp2_hpack_parser* p, } /* finish a literal header with incremental indexing with no index */ -static grpc_error* finish_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { GRPC_STATS_INC_HPACK_RECV_LITHDR_INCIDX_V(); - grpc_error* err = on_hdr( + grpc_error_handle err = on_hdr( p, grpc_mdelem_from_slices(take_string_intern(p, &p->key), take_string_intern(p, &p->value))); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); @@ -855,8 +872,9 @@ static grpc_error* finish_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, } /* parse a literal header with incremental indexing; index < 63 */ -static grpc_error* parse_lithdr_incidx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_lithdr_incidx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_value_string_with_indexed_key, finish_lithdr_incidx}; p->dynamic_table_update_allowed = 0; @@ -867,9 +885,9 @@ static grpc_error* parse_lithdr_incidx(grpc_chttp2_hpack_parser* p, } /* parse a literal header with incremental indexing; index >= 63 */ -static grpc_error* parse_lithdr_incidx_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_lithdr_incidx_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_string_prefix, parse_value_string_with_indexed_key, finish_lithdr_incidx}; @@ -882,9 +900,9 @@ static grpc_error* parse_lithdr_incidx_x(grpc_chttp2_hpack_parser* p, } /* parse a literal header with incremental indexing; index = 0 */ -static grpc_error* parse_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_key_string, parse_string_prefix, parse_value_string_with_literal_key, finish_lithdr_incidx_v}; @@ -894,12 +912,12 @@ static grpc_error* parse_lithdr_incidx_v(grpc_chttp2_hpack_parser* p, } /* finish a literal header without incremental indexing */ -static grpc_error* finish_lithdr_notidx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_lithdr_notidx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX(); grpc_mdelem md = get_precomputed_md_for_idx(p); - grpc_error* err = on_hdr( + grpc_error_handle err = on_hdr( p, grpc_mdelem_from_slices(get_indexed_key(md), take_string_extern(p, &p->value))); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); @@ -907,11 +925,11 @@ static grpc_error* finish_lithdr_notidx(grpc_chttp2_hpack_parser* p, } /* finish a literal header without incremental indexing with index = 0 */ -static grpc_error* finish_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { GRPC_STATS_INC_HPACK_RECV_LITHDR_NOTIDX_V(); - grpc_error* err = on_hdr( + grpc_error_handle err = on_hdr( p, grpc_mdelem_from_slices(take_string_intern(p, &p->key), take_string_extern(p, &p->value))); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); @@ -919,8 +937,9 @@ static grpc_error* finish_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, } /* parse a literal header without incremental indexing; index < 15 */ -static grpc_error* parse_lithdr_notidx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_lithdr_notidx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_value_string_with_indexed_key, finish_lithdr_notidx}; p->dynamic_table_update_allowed = 0; @@ -931,9 +950,9 @@ static grpc_error* parse_lithdr_notidx(grpc_chttp2_hpack_parser* p, } /* parse a literal header without incremental indexing; index >= 15 */ -static grpc_error* parse_lithdr_notidx_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_lithdr_notidx_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_string_prefix, parse_value_string_with_indexed_key, finish_lithdr_notidx}; @@ -946,9 +965,9 @@ static grpc_error* parse_lithdr_notidx_x(grpc_chttp2_hpack_parser* p, } /* parse a literal header without incremental indexing; index == 0 */ -static grpc_error* parse_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_key_string, parse_string_prefix, parse_value_string_with_literal_key, finish_lithdr_notidx_v}; @@ -958,12 +977,12 @@ static grpc_error* parse_lithdr_notidx_v(grpc_chttp2_hpack_parser* p, } /* finish a literal header that is never indexed */ -static grpc_error* finish_lithdr_nvridx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_lithdr_nvridx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX(); grpc_mdelem md = get_precomputed_md_for_idx(p); - grpc_error* err = on_hdr( + grpc_error_handle err = on_hdr( p, grpc_mdelem_from_slices(get_indexed_key(md), take_string_extern(p, &p->value))); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); @@ -971,11 +990,11 @@ static grpc_error* finish_lithdr_nvridx(grpc_chttp2_hpack_parser* p, } /* finish a literal header that is never indexed with an extra value */ -static grpc_error* finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { GRPC_STATS_INC_HPACK_RECV_LITHDR_NVRIDX_V(); - grpc_error* err = on_hdr( + grpc_error_handle err = on_hdr( p, grpc_mdelem_from_slices(take_string_intern(p, &p->key), take_string_extern(p, &p->value))); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); @@ -983,8 +1002,9 @@ static grpc_error* finish_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, } /* parse a literal header that is never indexed; index < 15 */ -static grpc_error* parse_lithdr_nvridx(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_lithdr_nvridx(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_value_string_with_indexed_key, finish_lithdr_nvridx}; p->dynamic_table_update_allowed = 0; @@ -995,9 +1015,9 @@ static grpc_error* parse_lithdr_nvridx(grpc_chttp2_hpack_parser* p, } /* parse a literal header that is never indexed; index >= 15 */ -static grpc_error* parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_string_prefix, parse_value_string_with_indexed_key, finish_lithdr_nvridx}; @@ -1010,9 +1030,9 @@ static grpc_error* parse_lithdr_nvridx_x(grpc_chttp2_hpack_parser* p, } /* parse a literal header that is never indexed; index == 0 */ -static grpc_error* parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { parse_key_string, parse_string_prefix, parse_value_string_with_literal_key, finish_lithdr_nvridx_v}; @@ -1022,20 +1042,22 @@ static grpc_error* parse_lithdr_nvridx_v(grpc_chttp2_hpack_parser* p, } /* finish parsing a max table size change */ -static grpc_error* finish_max_tbl_size(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle finish_max_tbl_size(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_chttp2_hpack_parser)) { gpr_log(GPR_INFO, "MAX TABLE SIZE: %d", p->index); } - grpc_error* err = + grpc_error_handle err = grpc_chttp2_hptbl_set_current_table_size(&p->table, p->index); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); return parse_begin(p, cur, end); } /* parse a max table size change, max size < 15 */ -static grpc_error* parse_max_tbl_size(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_max_tbl_size(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (p->dynamic_table_update_allowed == 0) { return parse_error( p, cur, end, @@ -1049,9 +1071,9 @@ static grpc_error* parse_max_tbl_size(grpc_chttp2_hpack_parser* p, } /* parse a max table size change, max size >= 15 */ -static grpc_error* parse_max_tbl_size_x(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_max_tbl_size_x(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { static const grpc_chttp2_hpack_parser_state and_then[] = { finish_max_tbl_size}; if (p->dynamic_table_update_allowed == 0) { @@ -1069,9 +1091,10 @@ static grpc_error* parse_max_tbl_size_x(grpc_chttp2_hpack_parser* p, } /* a parse error: jam the parse state into parse_error, and return error */ -static grpc_error* parse_error(grpc_chttp2_hpack_parser* p, - const uint8_t* /*cur*/, const uint8_t* /*end*/, - grpc_error* err) { +static grpc_error_handle parse_error(grpc_chttp2_hpack_parser* p, + const uint8_t* /*cur*/, + const uint8_t* /*end*/, + grpc_error_handle err) { GPR_ASSERT(err != GRPC_ERROR_NONE); if (p->last_error == GRPC_ERROR_NONE) { p->last_error = GRPC_ERROR_REF(err); @@ -1080,24 +1103,25 @@ static grpc_error* parse_error(grpc_chttp2_hpack_parser* p, return err; } -static grpc_error* still_parse_error(grpc_chttp2_hpack_parser* p, - const uint8_t* /*cur*/, - const uint8_t* /*end*/) { +static grpc_error_handle still_parse_error(grpc_chttp2_hpack_parser* p, + const uint8_t* /*cur*/, + const uint8_t* /*end*/) { return GRPC_ERROR_REF(p->last_error); } -static grpc_error* parse_illegal_op(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_illegal_op(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { GPR_ASSERT(cur != end); - grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("Illegal hpack op code ", *cur).c_str()); return parse_error(p, cur, end, err); } /* parse the 1st byte of a varint into p->parsing.value no overflow is possible */ -static grpc_error* parse_value0(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_value0(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { if (cur == end) { p->state = parse_value0; return GRPC_ERROR_NONE; @@ -1114,8 +1138,8 @@ static grpc_error* parse_value0(grpc_chttp2_hpack_parser* p, const uint8_t* cur, /* parse the 2nd byte of a varint into p->parsing.value no overflow is possible */ -static grpc_error* parse_value1(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_value1(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { if (cur == end) { p->state = parse_value1; return GRPC_ERROR_NONE; @@ -1132,8 +1156,8 @@ static grpc_error* parse_value1(grpc_chttp2_hpack_parser* p, const uint8_t* cur, /* parse the 3rd byte of a varint into p->parsing.value no overflow is possible */ -static grpc_error* parse_value2(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_value2(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { if (cur == end) { p->state = parse_value2; return GRPC_ERROR_NONE; @@ -1150,8 +1174,8 @@ static grpc_error* parse_value2(grpc_chttp2_hpack_parser* p, const uint8_t* cur, /* parse the 4th byte of a varint into p->parsing.value no overflow is possible */ -static grpc_error* parse_value3(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_value3(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { if (cur == end) { p->state = parse_value3; return GRPC_ERROR_NONE; @@ -1168,8 +1192,8 @@ static grpc_error* parse_value3(grpc_chttp2_hpack_parser* p, const uint8_t* cur, /* parse the 5th byte of a varint into p->parsing.value depending on the byte, we may overflow, and care must be taken */ -static grpc_error* parse_value4(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_value4(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { uint8_t c; uint32_t cur_value; uint32_t add_value; @@ -1199,7 +1223,7 @@ static grpc_error* parse_value4(grpc_chttp2_hpack_parser* p, const uint8_t* cur, } error: - grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat( "integer overflow in hpack integer decoding: have 0x%08x, " "got byte 0x%02x on byte 5", @@ -1211,8 +1235,9 @@ error: /* parse any trailing bytes in a varint: it's possible to append an arbitrary number of 0x80's and not affect the value - a zero will terminate - and anything else will overflow */ -static grpc_error* parse_value5up(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_value5up(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { while (cur != end && *cur == 0x80) { ++cur; } @@ -1226,7 +1251,7 @@ static grpc_error* parse_value5up(grpc_chttp2_hpack_parser* p, return parse_next(p, cur + 1, end); } - grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat( "integer overflow in hpack integer decoding: have 0x%08x, " "got byte 0x%02x sometime after byte 5", @@ -1236,8 +1261,9 @@ static grpc_error* parse_value5up(grpc_chttp2_hpack_parser* p, } /* parse a string prefix */ -static grpc_error* parse_string_prefix(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_string_prefix(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { if (cur == end) { p->state = parse_string_prefix; return GRPC_ERROR_NONE; @@ -1269,8 +1295,8 @@ static void append_bytes(grpc_chttp2_hpack_parser_string* str, str->data.copied.length += static_cast(length); } -static grpc_error* append_string(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle append_string(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { grpc_chttp2_hpack_parser_string* str = p->parsing.str; uint32_t bits; uint8_t decoded[3]; @@ -1372,8 +1398,8 @@ static grpc_error* append_string(grpc_chttp2_hpack_parser* p, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here"))); } -static grpc_error* finish_str(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle finish_str(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { uint8_t decoded[2]; uint32_t bits; grpc_chttp2_hpack_parser_string* str = p->parsing.str; @@ -1391,7 +1417,7 @@ static grpc_error* finish_str(grpc_chttp2_hpack_parser* p, const uint8_t* cur, case B64_BYTE2: bits = p->base64_buffer; if (bits & 0xffff) { - grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat("trailing bits in base64 encoding: 0x%04x", bits & 0xffff) .c_str()); @@ -1403,7 +1429,7 @@ static grpc_error* finish_str(grpc_chttp2_hpack_parser* p, const uint8_t* cur, case B64_BYTE3: bits = p->base64_buffer; if (bits & 0xff) { - grpc_error* err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat("trailing bits in base64 encoding: 0x%02x", bits & 0xff) .c_str()); @@ -1418,13 +1444,14 @@ static grpc_error* finish_str(grpc_chttp2_hpack_parser* p, const uint8_t* cur, } /* decode a nibble from a huffman encoded stream */ -static grpc_error* huff_nibble(grpc_chttp2_hpack_parser* p, uint8_t nibble) { +static grpc_error_handle huff_nibble(grpc_chttp2_hpack_parser* p, + uint8_t nibble) { int16_t emit = emit_sub_tbl[16 * emit_tbl[p->huff_state] + nibble]; int16_t next = next_sub_tbl[16 * next_tbl[p->huff_state] + nibble]; if (emit != -1) { if (emit >= 0 && emit < 256) { uint8_t c = static_cast(emit); - grpc_error* err = append_string(p, &c, (&c) + 1); + grpc_error_handle err = append_string(p, &c, (&c) + 1); if (err != GRPC_ERROR_NONE) return err; } else { assert(emit == 256); @@ -1435,10 +1462,11 @@ static grpc_error* huff_nibble(grpc_chttp2_hpack_parser* p, uint8_t nibble) { } /* decode full bytes from a huffman encoded stream */ -static grpc_error* add_huff_bytes(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle add_huff_bytes(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { for (; cur != end; ++cur) { - grpc_error* err = huff_nibble(p, *cur >> 4); + grpc_error_handle err = huff_nibble(p, *cur >> 4); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); err = huff_nibble(p, *cur & 0xf); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); @@ -1448,8 +1476,8 @@ static grpc_error* add_huff_bytes(grpc_chttp2_hpack_parser* p, /* decode some string bytes based on the current decoding mode (huffman or not) */ -static grpc_error* add_str_bytes(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle add_str_bytes(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { if (p->huff) { return add_huff_bytes(p, cur, end); } else { @@ -1458,18 +1486,18 @@ static grpc_error* add_str_bytes(grpc_chttp2_hpack_parser* p, } /* parse a string - tries to do large chunks at a time */ -static grpc_error* parse_string(grpc_chttp2_hpack_parser* p, const uint8_t* cur, - const uint8_t* end) { +static grpc_error_handle parse_string(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, const uint8_t* end) { size_t remaining = p->strlen - p->strgot; size_t given = static_cast(end - cur); if (remaining <= given) { - grpc_error* err = add_str_bytes(p, cur, cur + remaining); + grpc_error_handle err = add_str_bytes(p, cur, cur + remaining); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); err = finish_str(p, cur + remaining, end); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); return parse_next(p, cur + remaining, end); } else { - grpc_error* err = add_str_bytes(p, cur, cur + given); + grpc_error_handle err = add_str_bytes(p, cur, cur + given); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); GPR_ASSERT(given <= UINT32_MAX - p->strgot); p->strgot += static_cast(given); @@ -1479,10 +1507,9 @@ static grpc_error* parse_string(grpc_chttp2_hpack_parser* p, const uint8_t* cur, } /* begin parsing a string - performs setup, calls parse_string */ -static grpc_error* begin_parse_string(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end, - uint8_t binary, - grpc_chttp2_hpack_parser_string* str) { +static grpc_error_handle begin_parse_string( + grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end, + uint8_t binary, grpc_chttp2_hpack_parser_string* str) { if (!p->huff && binary == NOT_BINARY && static_cast(end - cur) >= p->strlen && p->current_slice_refcount != nullptr) { @@ -1518,8 +1545,9 @@ static grpc_error* begin_parse_string(grpc_chttp2_hpack_parser* p, } /* parse the key string */ -static grpc_error* parse_key_string(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end) { +static grpc_error_handle parse_key_string(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end) { return begin_parse_string(p, cur, end, NOT_BINARY, &p->key); } @@ -1554,8 +1582,8 @@ static void set_precomputed_md_idx(grpc_chttp2_hpack_parser* p, is a binary indexed header during string parsing. We'll need to revisit this metadata when we're done parsing, so we cache the metadata for this index here using set_precomputed_md_idx(). */ -static grpc_error* is_binary_indexed_header(grpc_chttp2_hpack_parser* p, - bool* is) { +static grpc_error_handle is_binary_indexed_header(grpc_chttp2_hpack_parser* p, + bool* is) { grpc_mdelem elem = grpc_chttp2_hptbl_lookup(&p->table, p->index); if (GPR_UNLIKELY(GRPC_MDISNULL(elem))) { return on_invalid_hpack_idx(p); @@ -1574,29 +1602,30 @@ static grpc_error* is_binary_indexed_header(grpc_chttp2_hpack_parser* p, } /* parse the value string */ -static grpc_error* parse_value_string(grpc_chttp2_hpack_parser* p, - const uint8_t* cur, const uint8_t* end, - bool is_binary) { +static grpc_error_handle parse_value_string(grpc_chttp2_hpack_parser* p, + const uint8_t* cur, + const uint8_t* end, + bool is_binary) { return begin_parse_string(p, cur, end, is_binary ? BINARY_BEGIN : NOT_BINARY, &p->value); } -static grpc_error* parse_value_string_with_indexed_key( +static grpc_error_handle parse_value_string_with_indexed_key( grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end) { bool is_binary = false; - grpc_error* err = is_binary_indexed_header(p, &is_binary); + grpc_error_handle err = is_binary_indexed_header(p, &is_binary); if (err != GRPC_ERROR_NONE) return parse_error(p, cur, end, err); return parse_value_string(p, cur, end, is_binary); } -static grpc_error* parse_value_string_with_literal_key( +static grpc_error_handle parse_value_string_with_literal_key( grpc_chttp2_hpack_parser* p, const uint8_t* cur, const uint8_t* end) { return parse_value_string(p, cur, end, is_binary_literal_header(p)); } /* "Uninitialized" header parser to save us a branch in on_hdr(). */ -static grpc_error* on_header_uninitialized(void* /*user_data*/, - grpc_mdelem md) { +static grpc_error_handle on_header_uninitialized(void* /*user_data*/, + grpc_mdelem md) { GRPC_MDELEM_UNREF(md); return GRPC_ERROR_CREATE_FROM_STATIC_STRING("on_header callback not set"); } @@ -1645,15 +1674,15 @@ void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser* p) { gpr_free(p->value.data.copied.str); } -grpc_error* grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser* p, - const grpc_slice& slice) { +grpc_error_handle grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser* p, + const grpc_slice& slice) { /* max number of bytes to parse at a time... limits call stack depth on * compilers without TCO */ #define MAX_PARSE_LENGTH 1024 p->current_slice_refcount = slice.refcount; const uint8_t* start = GRPC_SLICE_START_PTR(slice); const uint8_t* end = GRPC_SLICE_END_PTR(slice); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; while (start != end && error == GRPC_ERROR_NONE) { const uint8_t* target = start + GPR_MIN(MAX_PARSE_LENGTH, end - start); error = p->state(p, start, target); @@ -1669,7 +1698,7 @@ static const maybe_complete_func_type maybe_complete_funcs[] = { grpc_chttp2_maybe_complete_recv_initial_metadata, grpc_chttp2_maybe_complete_recv_trailing_metadata}; -static void force_client_rst_stream(void* sp, grpc_error* /*error*/) { +static void force_client_rst_stream(void* sp, grpc_error_handle /*error*/) { grpc_chttp2_stream* s = static_cast(sp); grpc_chttp2_transport* t = s->t; if (!s->write_closed) { @@ -1699,18 +1728,18 @@ static void parse_stream_compression_md(grpc_chttp2_transport* /*t*/, } } -grpc_error* grpc_chttp2_header_parser_parse(void* hpack_parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last) { +grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last) { GPR_TIMER_SCOPE("grpc_chttp2_header_parser_parse", 0); grpc_chttp2_hpack_parser* parser = static_cast(hpack_parser); if (s != nullptr) { s->stats.incoming.header_bytes += GRPC_SLICE_LENGTH(slice); } - grpc_error* error = grpc_chttp2_hpack_parser_parse(parser, slice); + grpc_error_handle error = grpc_chttp2_hpack_parser_parse(parser, slice); if (error != GRPC_ERROR_NONE) { return error; } diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.h b/src/core/ext/transport/chttp2/transport/hpack_parser.h index 1b859c4d7c6..71aa194a233 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parser.h +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.h @@ -29,7 +29,7 @@ typedef struct grpc_chttp2_hpack_parser grpc_chttp2_hpack_parser; -typedef grpc_error* (*grpc_chttp2_hpack_parser_state)( +typedef grpc_error_handle (*grpc_chttp2_hpack_parser_state)( grpc_chttp2_hpack_parser* p, const uint8_t* beg, const uint8_t* end); struct grpc_chttp2_hpack_parser_string { @@ -45,10 +45,10 @@ struct grpc_chttp2_hpack_parser_string { }; struct grpc_chttp2_hpack_parser { /* user specified callback for each header output */ - grpc_error* (*on_header)(void* user_data, grpc_mdelem md); + grpc_error_handle (*on_header)(void* user_data, grpc_mdelem md); void* on_header_user_data; - grpc_error* last_error; + grpc_error_handle last_error; /* current parse state - or a function that implements it */ grpc_chttp2_hpack_parser_state state; @@ -103,15 +103,15 @@ void grpc_chttp2_hpack_parser_destroy(grpc_chttp2_hpack_parser* p); void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser* p); -grpc_error* grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser* p, - const grpc_slice& slice); +grpc_error_handle grpc_chttp2_hpack_parser_parse(grpc_chttp2_hpack_parser* p, + const grpc_slice& slice); /* wraps grpc_chttp2_hpack_parser_parse to provide a frame level parser for the transport */ -grpc_error* grpc_chttp2_header_parser_parse(void* hpack_parser, - grpc_chttp2_transport* t, - grpc_chttp2_stream* s, - const grpc_slice& slice, - int is_last); +grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser, + grpc_chttp2_transport* t, + grpc_chttp2_stream* s, + const grpc_slice& slice, + int is_last); #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_H */ diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.cc b/src/core/ext/transport/chttp2/transport/hpack_table.cc index 78ee207c89b..696176b49d5 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_table.cc +++ b/src/core/ext/transport/chttp2/transport/hpack_table.cc @@ -114,8 +114,8 @@ void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl* tbl, tbl->max_bytes = max_bytes; } -grpc_error* grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl* tbl, - uint32_t bytes) { +grpc_error_handle grpc_chttp2_hptbl_set_current_table_size( + grpc_chttp2_hptbl* tbl, uint32_t bytes) { if (tbl->current_table_bytes == bytes) { return GRPC_ERROR_NONE; } @@ -145,7 +145,8 @@ grpc_error* grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl* tbl, return GRPC_ERROR_NONE; } -grpc_error* grpc_chttp2_hptbl_add(grpc_chttp2_hptbl* tbl, grpc_mdelem md) { +grpc_error_handle grpc_chttp2_hptbl_add(grpc_chttp2_hptbl* tbl, + grpc_mdelem md) { /* determine how many bytes of buffer this entry represents */ size_t elem_bytes = GRPC_SLICE_LENGTH(GRPC_MDKEY(md)) + GRPC_SLICE_LENGTH(GRPC_MDVALUE(md)) + diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.h b/src/core/ext/transport/chttp2/transport/hpack_table.h index 34c3dceda75..14a77932a2e 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_table.h +++ b/src/core/ext/transport/chttp2/transport/hpack_table.h @@ -89,8 +89,8 @@ struct grpc_chttp2_hptbl { void grpc_chttp2_hptbl_destroy(grpc_chttp2_hptbl* tbl); void grpc_chttp2_hptbl_set_max_bytes(grpc_chttp2_hptbl* tbl, uint32_t max_bytes); -grpc_error* grpc_chttp2_hptbl_set_current_table_size(grpc_chttp2_hptbl* tbl, - uint32_t bytes); +grpc_error_handle grpc_chttp2_hptbl_set_current_table_size( + grpc_chttp2_hptbl* tbl, uint32_t bytes); /* lookup a table entry based on its hpack index */ grpc_mdelem grpc_chttp2_hptbl_lookup_dynamic_index(const grpc_chttp2_hptbl* tbl, @@ -117,8 +117,8 @@ inline grpc_mdelem grpc_chttp2_hptbl_lookup(const grpc_chttp2_hptbl* tbl, } } /* add a table entry to the index */ -grpc_error* grpc_chttp2_hptbl_add(grpc_chttp2_hptbl* tbl, - grpc_mdelem md) GRPC_MUST_USE_RESULT; +grpc_error_handle grpc_chttp2_hptbl_add(grpc_chttp2_hptbl* tbl, + grpc_mdelem md) GRPC_MUST_USE_RESULT; size_t grpc_chttp2_get_size_in_hpack_table(grpc_mdelem elem, bool use_true_binary_metadata); diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.cc b/src/core/ext/transport/chttp2/transport/incoming_metadata.cc index d04630d726b..361b7b7ee0b 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.cc +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.cc @@ -27,7 +27,7 @@ #include #include -grpc_error* grpc_chttp2_incoming_metadata_buffer_add( +grpc_error_handle grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) { buffer->size += GRPC_MDELEM_LENGTH(elem); grpc_linked_mdelem* storage; @@ -42,7 +42,7 @@ grpc_error* grpc_chttp2_incoming_metadata_buffer_add( return grpc_metadata_batch_link_tail(&buffer->batch, storage); } -grpc_error* grpc_chttp2_incoming_metadata_buffer_replace_or_add( +grpc_error_handle grpc_chttp2_incoming_metadata_buffer_replace_or_add( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) { for (grpc_linked_mdelem* l = buffer->batch.list.head; l != nullptr; l = l->next) { diff --git a/src/core/ext/transport/chttp2/transport/incoming_metadata.h b/src/core/ext/transport/chttp2/transport/incoming_metadata.h index b63caa1ae25..68413b068c7 100644 --- a/src/core/ext/transport/chttp2/transport/incoming_metadata.h +++ b/src/core/ext/transport/chttp2/transport/incoming_metadata.h @@ -46,10 +46,10 @@ struct grpc_chttp2_incoming_metadata_buffer { void grpc_chttp2_incoming_metadata_buffer_publish( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_metadata_batch* batch); -grpc_error* grpc_chttp2_incoming_metadata_buffer_add( +grpc_error_handle grpc_chttp2_incoming_metadata_buffer_add( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) GRPC_MUST_USE_RESULT; -grpc_error* grpc_chttp2_incoming_metadata_buffer_replace_or_add( +grpc_error_handle grpc_chttp2_incoming_metadata_buffer_replace_or_add( grpc_chttp2_incoming_metadata_buffer* buffer, grpc_mdelem elem) GRPC_MUST_USE_RESULT; void grpc_chttp2_incoming_metadata_buffer_set_deadline( diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 408a425135b..9c7f5fce532 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -217,8 +217,8 @@ class Chttp2IncomingByteStream : public ByteStream { void Orphan() override; bool Next(size_t max_size_hint, grpc_closure* on_complete) override; - grpc_error* Pull(grpc_slice* slice) override; - void Shutdown(grpc_error* error) override; + grpc_error_handle Pull(grpc_slice* slice) override; + void Shutdown(grpc_error_handle error) override; // TODO(roth): When I converted this class to C++, I wanted to make it // inherit from RefCounted or InternallyRefCounted instead of continuing @@ -241,17 +241,17 @@ class Chttp2IncomingByteStream : public ByteStream { } } - void PublishError(grpc_error* error); + void PublishError(grpc_error_handle error); - grpc_error* Push(const grpc_slice& slice, grpc_slice* slice_out); + grpc_error_handle Push(const grpc_slice& slice, grpc_slice* slice_out); - grpc_error* Finished(grpc_error* error, bool reset_on_error); + grpc_error_handle Finished(grpc_error_handle error, bool reset_on_error); uint32_t remaining_bytes() const { return remaining_bytes_; } private: - static void NextLocked(void* arg, grpc_error* error_ignored); - static void OrphanLocked(void* arg, grpc_error* error_ignored); + static void NextLocked(void* arg, grpc_error_handle error_ignored); + static void OrphanLocked(void* arg, grpc_error_handle error_ignored); void MaybeCreateStreamDecompressionCtx(); @@ -301,6 +301,7 @@ struct grpc_chttp2_transport { grpc_core::Combiner* combiner; grpc_closure* notify_on_receive_settings = nullptr; + grpc_closure* notify_on_close = nullptr; /** write execution state of the transport */ grpc_chttp2_write_state write_state = GRPC_CHTTP2_WRITE_STATE_IDLE; @@ -308,7 +309,7 @@ struct grpc_chttp2_transport { /** is the transport destroying itself? */ uint8_t destroying = false; /** has the upper layer closed the transport? */ - grpc_error* closed_with_error = GRPC_ERROR_NONE; + grpc_error_handle closed_with_error = GRPC_ERROR_NONE; /** is there a read request to the endpoint outstanding? */ uint8_t endpoint_reading = 1; @@ -357,7 +358,7 @@ struct grpc_chttp2_transport { /** Set to a grpc_error object if a goaway frame is received. By default, set * to GRPC_ERROR_NONE */ - grpc_error* goaway_error = GRPC_ERROR_NONE; + grpc_error_handle goaway_error = GRPC_ERROR_NONE; grpc_chttp2_sent_goaway_state sent_goaway_state = GRPC_CHTTP2_NO_GOAWAY_SEND; @@ -427,9 +428,9 @@ struct grpc_chttp2_transport { /* active parser */ void* parser_data = nullptr; grpc_chttp2_stream* incoming_stream = nullptr; - grpc_error* (*parser)(void* parser_user_data, grpc_chttp2_transport* t, - grpc_chttp2_stream* s, const grpc_slice& slice, - int is_last); + grpc_error_handle (*parser)(void* parser_user_data, grpc_chttp2_transport* t, + grpc_chttp2_stream* s, const grpc_slice& slice, + int is_last); grpc_chttp2_write_cb* write_cb_pool = nullptr; @@ -442,7 +443,7 @@ struct grpc_chttp2_transport { /* if non-NULL, close the transport with this error when writes are finished */ - grpc_error* close_transport_on_writes_finished = GRPC_ERROR_NONE; + grpc_error_handle close_transport_on_writes_finished = GRPC_ERROR_NONE; /* a list of closures to run after writes are finished */ grpc_closure_list run_after_write = GRPC_CLOSURE_LIST_INIT; @@ -580,9 +581,9 @@ struct grpc_chttp2_stream { bool eos_sent = false; /** the error that resulted in this stream being read-closed */ - grpc_error* read_closed_error = GRPC_ERROR_NONE; + grpc_error_handle read_closed_error = GRPC_ERROR_NONE; /** the error that resulted in this stream being write-closed */ - grpc_error* write_closed_error = GRPC_ERROR_NONE; + grpc_error_handle write_closed_error = GRPC_ERROR_NONE; grpc_published_metadata_method published_metadata[2] = {}; bool final_metadata_requested = false; @@ -603,13 +604,14 @@ struct grpc_chttp2_stream { * true */ grpc_slice_buffer unprocessed_incoming_frames_buffer; grpc_closure reset_byte_stream; - grpc_error* byte_stream_error = GRPC_ERROR_NONE; /* protected by t combiner */ - bool received_last_frame = false; /* protected by t combiner */ + grpc_error_handle byte_stream_error = + GRPC_ERROR_NONE; /* protected by t combiner */ + bool received_last_frame = false; /* protected by t combiner */ grpc_millis deadline = GRPC_MILLIS_INF_FUTURE; /** saw some stream level error */ - grpc_error* forced_close_error = GRPC_ERROR_NONE; + grpc_error_handle forced_close_error = GRPC_ERROR_NONE; /** how many header frames have we received? */ uint8_t header_frames_received = 0; /** parsing state for data frames */ @@ -695,12 +697,12 @@ struct grpc_chttp2_begin_write_result { }; grpc_chttp2_begin_write_result grpc_chttp2_begin_write( grpc_chttp2_transport* t); -void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error* error); +void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error_handle error); /** Process one slice of incoming data; return 1 if the connection is still viable after reading, or 0 if the connection should be torn down */ -grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t, - const grpc_slice& slice); +grpc_error_handle grpc_chttp2_perform_read(grpc_chttp2_transport* t, + const grpc_slice& slice); bool grpc_chttp2_list_add_writable_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s); @@ -770,7 +772,8 @@ void grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport* t); void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, grpc_chttp2_stream* s, grpc_closure** pclosure, - grpc_error* error, const char* desc); + grpc_error_handle error, + const char* desc); #define GRPC_HEADER_SIZE_IN_BYTES 5 #define MAX_SIZE_T (~(size_t)0) @@ -790,10 +793,11 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, } while (0) void grpc_chttp2_fake_status(grpc_chttp2_transport* t, - grpc_chttp2_stream* stream, grpc_error* error); + grpc_chttp2_stream* stream, + grpc_error_handle error); void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t, grpc_chttp2_stream* s, int close_reads, - int close_writes, grpc_error* error); + int close_writes, grpc_error_handle error); void grpc_chttp2_start_writing(grpc_chttp2_transport* t); #ifndef NDEBUG @@ -861,7 +865,7 @@ void grpc_chttp2_mark_stream_writable(grpc_chttp2_transport* t, grpc_chttp2_stream* s); void grpc_chttp2_cancel_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_error* due_to_error); + grpc_error_handle due_to_error); void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_chttp2_transport* t, grpc_chttp2_stream* s); @@ -871,14 +875,15 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t, grpc_chttp2_stream* s); void grpc_chttp2_fail_pending_writes(grpc_chttp2_transport* t, - grpc_chttp2_stream* s, grpc_error* error); + grpc_chttp2_stream* s, + grpc_error_handle error); /** Set the default keepalive configurations, must only be called at initialization */ void grpc_chttp2_config_default_keepalive_args(grpc_channel_args* args, bool is_client); -void grpc_chttp2_retry_initiate_ping(void* tp, grpc_error* error); +void grpc_chttp2_retry_initiate_ping(void* tp, grpc_error_handle error); void schedule_bdp_ping_locked(grpc_chttp2_transport* t); diff --git a/src/core/ext/transport/chttp2/transport/parsing.cc b/src/core/ext/transport/chttp2/transport/parsing.cc index f4b02bbfac2..68e7c69c65f 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.cc +++ b/src/core/ext/transport/chttp2/transport/parsing.cc @@ -36,27 +36,29 @@ #include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/timeout_encoding.h" -static grpc_error* init_frame_parser(grpc_chttp2_transport* t); -static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, - int is_continuation); -static grpc_error* init_data_frame_parser(grpc_chttp2_transport* t); -static grpc_error* init_rst_stream_parser(grpc_chttp2_transport* t); -static grpc_error* init_settings_frame_parser(grpc_chttp2_transport* t); -static grpc_error* init_window_update_frame_parser(grpc_chttp2_transport* t); -static grpc_error* init_ping_parser(grpc_chttp2_transport* t); -static grpc_error* init_goaway_parser(grpc_chttp2_transport* t); -static grpc_error* init_skip_frame_parser(grpc_chttp2_transport* t, - int is_header); - -static grpc_error* parse_frame_slice(grpc_chttp2_transport* t, - const grpc_slice& slice, int is_last); - -grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t, - const grpc_slice& slice) { +static grpc_error_handle init_frame_parser(grpc_chttp2_transport* t); +static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t, + int is_continuation); +static grpc_error_handle init_data_frame_parser(grpc_chttp2_transport* t); +static grpc_error_handle init_rst_stream_parser(grpc_chttp2_transport* t); +static grpc_error_handle init_settings_frame_parser(grpc_chttp2_transport* t); +static grpc_error_handle init_window_update_frame_parser( + grpc_chttp2_transport* t); +static grpc_error_handle init_ping_parser(grpc_chttp2_transport* t); +static grpc_error_handle init_goaway_parser(grpc_chttp2_transport* t); +static grpc_error_handle init_skip_frame_parser(grpc_chttp2_transport* t, + int is_header); + +static grpc_error_handle parse_frame_slice(grpc_chttp2_transport* t, + const grpc_slice& slice, + int is_last); + +grpc_error_handle grpc_chttp2_perform_read(grpc_chttp2_transport* t, + const grpc_slice& slice) { const uint8_t* beg = GRPC_SLICE_START_PTR(slice); const uint8_t* end = GRPC_SLICE_END_PTR(slice); const uint8_t* cur = beg; - grpc_error* err; + grpc_error_handle err; if (cur == end) return GRPC_ERROR_NONE; @@ -250,7 +252,7 @@ grpc_error* grpc_chttp2_perform_read(grpc_chttp2_transport* t, GPR_UNREACHABLE_CODE(return nullptr); } -static grpc_error* init_frame_parser(grpc_chttp2_transport* t) { +static grpc_error_handle init_frame_parser(grpc_chttp2_transport* t) { if (t->is_first_frame && t->incoming_frame_type != GRPC_CHTTP2_FRAME_SETTINGS) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -303,19 +305,21 @@ static grpc_error* init_frame_parser(grpc_chttp2_transport* t) { } } -static grpc_error* skip_parser(void* /*parser*/, grpc_chttp2_transport* /*t*/, - grpc_chttp2_stream* /*s*/, - const grpc_slice& /*slice*/, int /*is_last*/) { +static grpc_error_handle skip_parser(void* /*parser*/, + grpc_chttp2_transport* /*t*/, + grpc_chttp2_stream* /*s*/, + const grpc_slice& /*slice*/, + int /*is_last*/) { return GRPC_ERROR_NONE; } -static grpc_error* skip_header(void* /*tp*/, grpc_mdelem md) { +static grpc_error_handle skip_header(void* /*tp*/, grpc_mdelem md) { GRPC_MDELEM_UNREF(md); return GRPC_ERROR_NONE; } -static grpc_error* init_skip_frame_parser(grpc_chttp2_transport* t, - int is_header) { +static grpc_error_handle init_skip_frame_parser(grpc_chttp2_transport* t, + int is_header) { if (is_header) { uint8_t is_eoh = t->expect_continuation_stream_id != 0; t->parser = grpc_chttp2_header_parser_parse; @@ -334,7 +338,7 @@ void grpc_chttp2_parsing_become_skip_parser(grpc_chttp2_transport* t) { init_skip_frame_parser(t, t->parser == grpc_chttp2_header_parser_parse); } -static grpc_error* init_data_frame_parser(grpc_chttp2_transport* t) { +static grpc_error_handle init_data_frame_parser(grpc_chttp2_transport* t) { // Update BDP accounting since we have received a data frame. grpc_core::BdpEstimator* bdp_est = t->flow_control->bdp_estimator(); if (bdp_est) { @@ -347,7 +351,7 @@ static grpc_error* init_data_frame_parser(grpc_chttp2_transport* t) { } grpc_chttp2_stream* s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id); - grpc_error* err = GRPC_ERROR_NONE; + grpc_error_handle err = GRPC_ERROR_NONE; grpc_core::chttp2::FlowControlAction action; if (s == nullptr) { err = t->flow_control->RecvData(t->incoming_frame_size); @@ -413,8 +417,8 @@ static void GPR_ATTRIBUTE_NOINLINE on_initial_header_log( gpr_free(value); } -static grpc_error* GPR_ATTRIBUTE_NOINLINE handle_timeout(grpc_chttp2_stream* s, - grpc_mdelem md) { +static grpc_error_handle GPR_ATTRIBUTE_NOINLINE +handle_timeout(grpc_chttp2_stream* s, grpc_mdelem md) { grpc_millis* cached_timeout = static_cast(grpc_mdelem_get_user_data(md, free_timeout)); grpc_millis timeout; @@ -443,9 +447,11 @@ static grpc_error* GPR_ATTRIBUTE_NOINLINE handle_timeout(grpc_chttp2_stream* s, return GRPC_ERROR_NONE; } -static grpc_error* GPR_ATTRIBUTE_NOINLINE handle_metadata_size_limit_exceeded( - grpc_chttp2_transport* t, grpc_chttp2_stream* s, grpc_mdelem md, - size_t new_size, size_t metadata_size_limit) { +static grpc_error_handle GPR_ATTRIBUTE_NOINLINE +handle_metadata_size_limit_exceeded(grpc_chttp2_transport* t, + grpc_chttp2_stream* s, grpc_mdelem md, + size_t new_size, + size_t metadata_size_limit) { gpr_log(GPR_DEBUG, "received initial metadata size exceeds limit (%" PRIuPTR " vs. %" PRIuPTR @@ -463,9 +469,9 @@ static grpc_error* GPR_ATTRIBUTE_NOINLINE handle_metadata_size_limit_exceeded( return GRPC_ERROR_NONE; } -static grpc_error* GPR_ATTRIBUTE_NOINLINE +static grpc_error_handle GPR_ATTRIBUTE_NOINLINE handle_metadata_add_failure(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_mdelem md, grpc_error* error) { + grpc_mdelem md, grpc_error_handle error) { grpc_chttp2_cancel_stream(t, s, error); grpc_chttp2_parsing_become_skip_parser(t); s->seen_error = true; @@ -473,7 +479,7 @@ handle_metadata_add_failure(grpc_chttp2_transport* t, grpc_chttp2_stream* s, return GRPC_ERROR_NONE; } -static grpc_error* on_initial_header(void* tp, grpc_mdelem md) { +static grpc_error_handle on_initial_header(void* tp, grpc_mdelem md) { GPR_TIMER_SCOPE("on_initial_header", 0); grpc_chttp2_transport* t = static_cast(tp); @@ -496,7 +502,7 @@ static grpc_error* on_initial_header(void* tp, grpc_mdelem md) { return handle_metadata_size_limit_exceeded(t, s, md, new_size, metadata_size_limit); } else { - grpc_error* error = + grpc_error_handle error = grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[0], md); if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { return handle_metadata_add_failure(t, s, md, error); @@ -506,7 +512,7 @@ static grpc_error* on_initial_header(void* tp, grpc_mdelem md) { return GRPC_ERROR_NONE; } -static grpc_error* on_trailing_header(void* tp, grpc_mdelem md) { +static grpc_error_handle on_trailing_header(void* tp, grpc_mdelem md) { GPR_TIMER_SCOPE("on_trailing_header", 0); grpc_chttp2_transport* t = static_cast(tp); @@ -545,7 +551,7 @@ static grpc_error* on_trailing_header(void* tp, grpc_mdelem md) { s->seen_error = true; GRPC_MDELEM_UNREF(md); } else { - grpc_error* error = + grpc_error_handle error = grpc_chttp2_incoming_metadata_buffer_add(&s->metadata_buffer[1], md); if (error != GRPC_ERROR_NONE) { grpc_chttp2_cancel_stream(t, s, error); @@ -557,8 +563,8 @@ static grpc_error* on_trailing_header(void* tp, grpc_mdelem md) { return GRPC_ERROR_NONE; } -static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, - int is_continuation) { +static grpc_error_handle init_header_frame_parser(grpc_chttp2_transport* t, + int is_continuation) { uint8_t is_eoh = (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_HEADERS) != 0; grpc_chttp2_stream* s; @@ -595,7 +601,7 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, GRPC_CHTTP2_IF_TRACING(gpr_log( GPR_ERROR, "ignoring new grpc_chttp2_stream creation on client")); } - grpc_error* err = init_skip_frame_parser(t, 1); + grpc_error_handle err = init_skip_frame_parser(t, 1); if (t->incoming_frame_flags & GRPC_CHTTP2_FLAG_HAS_PRIORITY) { grpc_chttp2_hpack_parser_set_has_priority(&t->hpack_parser); } @@ -678,8 +684,9 @@ static grpc_error* init_header_frame_parser(grpc_chttp2_transport* t, return GRPC_ERROR_NONE; } -static grpc_error* init_window_update_frame_parser(grpc_chttp2_transport* t) { - grpc_error* err = grpc_chttp2_window_update_parser_begin_frame( +static grpc_error_handle init_window_update_frame_parser( + grpc_chttp2_transport* t) { + grpc_error_handle err = grpc_chttp2_window_update_parser_begin_frame( &t->simple.window_update, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; @@ -696,8 +703,8 @@ static grpc_error* init_window_update_frame_parser(grpc_chttp2_transport* t) { return GRPC_ERROR_NONE; } -static grpc_error* init_ping_parser(grpc_chttp2_transport* t) { - grpc_error* err = grpc_chttp2_ping_parser_begin_frame( +static grpc_error_handle init_ping_parser(grpc_chttp2_transport* t) { + grpc_error_handle err = grpc_chttp2_ping_parser_begin_frame( &t->simple.ping, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; t->parser = grpc_chttp2_ping_parser_parse; @@ -705,8 +712,8 @@ static grpc_error* init_ping_parser(grpc_chttp2_transport* t) { return GRPC_ERROR_NONE; } -static grpc_error* init_rst_stream_parser(grpc_chttp2_transport* t) { - grpc_error* err = grpc_chttp2_rst_stream_parser_begin_frame( +static grpc_error_handle init_rst_stream_parser(grpc_chttp2_transport* t) { + grpc_error_handle err = grpc_chttp2_rst_stream_parser_begin_frame( &t->simple.rst_stream, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; grpc_chttp2_stream* s = t->incoming_stream = @@ -720,8 +727,8 @@ static grpc_error* init_rst_stream_parser(grpc_chttp2_transport* t) { return GRPC_ERROR_NONE; } -static grpc_error* init_goaway_parser(grpc_chttp2_transport* t) { - grpc_error* err = grpc_chttp2_goaway_parser_begin_frame( +static grpc_error_handle init_goaway_parser(grpc_chttp2_transport* t) { + grpc_error_handle err = grpc_chttp2_goaway_parser_begin_frame( &t->goaway_parser, t->incoming_frame_size, t->incoming_frame_flags); if (err != GRPC_ERROR_NONE) return err; t->parser = grpc_chttp2_goaway_parser_parse; @@ -729,13 +736,13 @@ static grpc_error* init_goaway_parser(grpc_chttp2_transport* t) { return GRPC_ERROR_NONE; } -static grpc_error* init_settings_frame_parser(grpc_chttp2_transport* t) { +static grpc_error_handle init_settings_frame_parser(grpc_chttp2_transport* t) { if (t->incoming_stream_id != 0) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Settings frame received for grpc_chttp2_stream"); } - grpc_error* err = grpc_chttp2_settings_parser_begin_frame( + grpc_error_handle err = grpc_chttp2_settings_parser_begin_frame( &t->simple.settings, t->incoming_frame_size, t->incoming_frame_flags, t->settings[GRPC_PEER_SETTINGS]); if (err != GRPC_ERROR_NONE) { @@ -755,17 +762,17 @@ static grpc_error* init_settings_frame_parser(grpc_chttp2_transport* t) { return GRPC_ERROR_NONE; } -static grpc_error* parse_frame_slice(grpc_chttp2_transport* t, - const grpc_slice& slice, int is_last) { +static grpc_error_handle parse_frame_slice(grpc_chttp2_transport* t, + const grpc_slice& slice, + int is_last) { grpc_chttp2_stream* s = t->incoming_stream; - grpc_error* err = t->parser(t->parser_data, t, s, slice, is_last); + grpc_error_handle err = t->parser(t->parser_data, t, s, slice, is_last); intptr_t unused; if (GPR_LIKELY(err == GRPC_ERROR_NONE)) { return err; } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, &unused)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { - const char* msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "%s", msg); + gpr_log(GPR_ERROR, "%s", grpc_error_std_string(err).c_str()); } grpc_chttp2_parsing_become_skip_parser(t); if (s) { diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index 317afcc5103..e34856ca5f1 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -39,7 +39,7 @@ static void add_to_write_list(grpc_chttp2_write_cb** list, } static void finish_write_cb(grpc_chttp2_transport* t, grpc_chttp2_stream* s, - grpc_chttp2_write_cb* cb, grpc_error* error) { + grpc_chttp2_write_cb* cb, grpc_error_handle error) { grpc_chttp2_complete_closure_step(t, s, &cb->closure, error, "finish_write_cb"); cb->next = t->write_cb_pool; @@ -75,6 +75,10 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) { } return; } + // InvalidateNow to avoid getting stuck re-initializing the ping timer + // in a loop while draining the currently-held combiner. Also see + // https://github.com/grpc/grpc/issues/26079. + grpc_core::ExecCtx::Get()->InvalidateNow(); grpc_millis now = grpc_core::ExecCtx::Get()->Now(); grpc_millis next_allowed_ping_interval = @@ -134,7 +138,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) { static bool update_list(grpc_chttp2_transport* t, grpc_chttp2_stream* s, int64_t send_bytes, grpc_chttp2_write_cb** list, - int64_t* ctr, grpc_error* error) { + int64_t* ctr, grpc_error_handle error) { bool sched_any = false; grpc_chttp2_write_cb* cb = *list; *list = nullptr; @@ -678,7 +682,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write( return ctx.Result(); } -void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error* error) { +void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error_handle error) { GPR_TIMER_SCOPE("grpc_chttp2_end_write", 0); grpc_chttp2_stream* s; diff --git a/src/core/ext/transport/cronet/transport/cronet_status.cc b/src/core/ext/transport/cronet/transport/cronet_status.cc index f904aee2c3e..9c047b3a1c6 100644 --- a/src/core/ext/transport/cronet/transport/cronet_status.cc +++ b/src/core/ext/transport/cronet/transport/cronet_status.cc @@ -491,3 +491,37 @@ const char* cronet_net_error_as_string(cronet_net_error_code net_error) { } return "UNAVAILABLE."; } + +grpc_status_code cronet_net_error_to_grpc_error( + cronet_net_error_code net_error) { + switch (net_error) { + case OK: + return GRPC_STATUS_OK; + case CRONET_NET_ERROR_ABORTED: + return GRPC_STATUS_ABORTED; + case CRONET_NET_ERROR_ACCESS_DENIED: + case CRONET_NET_ERROR_NETWORK_ACCESS_DENIED: + return GRPC_STATUS_PERMISSION_DENIED; + case CRONET_NET_ERROR_SSL_CLIENT_AUTH_CERT_NEEDED: + case CRONET_NET_ERROR_PROXY_AUTH_UNSUPPORTED: + case CRONET_NET_ERROR_BAD_SSL_CLIENT_AUTH_CERT: + case CRONET_NET_ERROR_PROXY_AUTH_REQUESTED: + case CRONET_NET_ERROR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED: + case CRONET_NET_ERROR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY: + case CRONET_NET_ERROR_SSL_CLIENT_AUTH_SIGNATURE_FAILED: + case CRONET_NET_ERROR_CLIENT_AUTH_CERT_TYPE_UNSUPPORTED: + case CRONET_NET_ERROR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT: + case CRONET_NET_ERROR_SSL_CLIENT_AUTH_NO_COMMON_ALGORITHMS: + case CRONET_NET_ERROR_CERT_AUTHORITY_INVALID: + case CRONET_NET_ERROR_UNEXPECTED_PROXY_AUTH: + case CRONET_NET_ERROR_MALFORMED_IDENTITY: + case CRONET_NET_ERROR_INVALID_AUTH_CREDENTIALS: + case CRONET_NET_ERROR_UNSUPPORTED_AUTH_SCHEME: + case CRONET_NET_ERROR_MISSING_AUTH_CREDENTIALS: + return GRPC_STATUS_UNAUTHENTICATED; + default: + return GRPC_STATUS_UNAVAILABLE; + } + + return GRPC_STATUS_UNAVAILABLE; +} diff --git a/src/core/ext/transport/cronet/transport/cronet_status.h b/src/core/ext/transport/cronet/transport/cronet_status.h index d6d1ed8ff2e..ee1262a0172 100644 --- a/src/core/ext/transport/cronet/transport/cronet_status.h +++ b/src/core/ext/transport/cronet/transport/cronet_status.h @@ -21,6 +21,8 @@ #include +#include + enum cronet_net_error_code { // // Ranges: @@ -1037,5 +1039,7 @@ enum cronet_net_error_code { }; const char* cronet_net_error_as_string(cronet_net_error_code net_error); +grpc_status_code cronet_net_error_to_grpc_error( + cronet_net_error_code net_error); #endif /* GRPC_CORE_EXT_TRANSPORT_CRONET_TRANSPORT_CRONET_STATUS_H */ diff --git a/src/core/ext/transport/cronet/transport/cronet_transport.cc b/src/core/ext/transport/cronet/transport/cronet_transport.cc index 329207f4c92..061b2e0916f 100644 --- a/src/core/ext/transport/cronet/transport/cronet_transport.cc +++ b/src/core/ext/transport/cronet/transport/cronet_transport.cc @@ -165,7 +165,7 @@ struct op_state { /* User requested RECV_TRAILING_METADATA */ bool pending_recv_trailing_metadata = false; cronet_net_error_code net_error = OK; - grpc_error* cancel_error = GRPC_ERROR_NONE; + grpc_error_handle cancel_error = GRPC_ERROR_NONE; /* data structure for storing data coming from server */ struct read_state rs; /* data structure for storing data going to the server */ @@ -306,13 +306,13 @@ static void read_grpc_header(stream_obj* s) { s->state.rs.remaining_bytes); } -static grpc_error* make_error_with_desc(int error_code, - int cronet_internal_error_code, - const char* desc) { +static grpc_error_handle make_error_with_desc(int error_code, + int cronet_internal_error_code, + const char* desc) { std::string error_message = absl::StrFormat("Cronet error code:%d, Cronet error detail:%s", cronet_internal_error_code, desc); - grpc_error* error = + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_message.c_str()); error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, error_code); return error; @@ -1200,7 +1200,7 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; result = ACTION_TAKEN_NO_CALLBACK; - } else if (stream_state->rs.read_stream_closed == true) { + } else if (stream_state->rs.read_stream_closed) { /* No more data will be received */ CRONET_LOG(GPR_DEBUG, "read stream closed"); grpc_core::ExecCtx::Run( @@ -1217,7 +1217,7 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { stream_state->state_op_done[OP_RECV_MESSAGE] = true; oas->state.state_op_done[OP_RECV_MESSAGE] = true; result = ACTION_TAKEN_NO_CALLBACK; - } else if (stream_state->rs.length_field_received == false) { + } else if (!stream_state->rs.length_field_received) { if (stream_state->rs.received_bytes == GRPC_HEADER_SIZE_IN_BYTES && stream_state->rs.remaining_bytes == 0) { /* Start a read operation for data */ @@ -1317,13 +1317,15 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { op_can_be_run(stream_op, s, &oas->state, OP_RECV_TRAILING_METADATA)) { CRONET_LOG(GPR_DEBUG, "running: %p OP_RECV_TRAILING_METADATA", oas); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (stream_state->state_op_done[OP_CANCEL_ERROR]) { error = GRPC_ERROR_REF(stream_state->cancel_error); } else if (stream_state->state_callback_received[OP_FAILED]) { + grpc_status_code grpc_error_code = + cronet_net_error_to_grpc_error(stream_state->net_error); const char* desc = cronet_net_error_as_string(stream_state->net_error); - error = make_error_with_desc(GRPC_STATUS_UNAVAILABLE, - stream_state->net_error, desc); + error = + make_error_with_desc(grpc_error_code, stream_state->net_error, desc); } else if (oas->s->state.rs.trailing_metadata_valid) { grpc_chttp2_incoming_metadata_buffer_publish( &oas->s->state.rs.trailing_metadata, @@ -1362,10 +1364,12 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { if (stream_op->on_complete) { const char* error_message = cronet_net_error_as_string(stream_state->net_error); + grpc_status_code grpc_error_code = + cronet_net_error_to_grpc_error(stream_state->net_error); grpc_core::ExecCtx::Run( DEBUG_LOCATION, stream_op->on_complete, - make_error_with_desc(GRPC_STATUS_UNAVAILABLE, - stream_state->net_error, error_message)); + make_error_with_desc(grpc_error_code, stream_state->net_error, + error_message)); } } else { /* All actions in this stream_op are complete. Call the on_complete diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc index 213c142b974..0c21db7f3af 100644 --- a/src/core/ext/transport/inproc/inproc_transport.cc +++ b/src/core/ext/transport/inproc/inproc_transport.cc @@ -50,15 +50,15 @@ grpc_slice g_fake_auth_key; grpc_slice g_fake_auth_value; struct inproc_stream; -bool cancel_stream_locked(inproc_stream* s, grpc_error* error); -void maybe_process_ops_locked(inproc_stream* s, grpc_error* error); -void op_state_machine_locked(inproc_stream* s, grpc_error* error); +bool cancel_stream_locked(inproc_stream* s, grpc_error_handle error); +void maybe_process_ops_locked(inproc_stream* s, grpc_error_handle error); +void op_state_machine_locked(inproc_stream* s, grpc_error_handle error); void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, bool is_initial); -grpc_error* fill_in_metadata(inproc_stream* s, - const grpc_metadata_batch* metadata, - uint32_t flags, grpc_metadata_batch* out_md, - uint32_t* outflags, bool* markfilled); +grpc_error_handle fill_in_metadata(inproc_stream* s, + const grpc_metadata_batch* metadata, + uint32_t flags, grpc_metadata_batch* out_md, + uint32_t* outflags, bool* markfilled); struct shared_mu { shared_mu() { @@ -239,7 +239,7 @@ struct inproc_stream { grpc_millis write_buffer_deadline = GRPC_MILLIS_INF_FUTURE; grpc_metadata_batch write_buffer_trailing_md; bool write_buffer_trailing_md_filled = false; - grpc_error* write_buffer_cancel_error = GRPC_ERROR_NONE; + grpc_error_handle write_buffer_cancel_error = GRPC_ERROR_NONE; struct inproc_stream* other_side; bool other_side_closed = false; // won't talk anymore @@ -270,8 +270,8 @@ struct inproc_stream { bool closed = false; - grpc_error* cancel_self_error = GRPC_ERROR_NONE; - grpc_error* cancel_other_error = GRPC_ERROR_NONE; + grpc_error_handle cancel_self_error = GRPC_ERROR_NONE; + grpc_error_handle cancel_other_error = GRPC_ERROR_NONE; grpc_millis deadline = GRPC_MILLIS_INF_FUTURE; @@ -293,10 +293,10 @@ void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, } } -grpc_error* fill_in_metadata(inproc_stream* s, - const grpc_metadata_batch* metadata, - uint32_t flags, grpc_metadata_batch* out_md, - uint32_t* outflags, bool* markfilled) { +grpc_error_handle fill_in_metadata(inproc_stream* s, + const grpc_metadata_batch* metadata, + uint32_t flags, grpc_metadata_batch* out_md, + uint32_t* outflags, bool* markfilled) { if (GRPC_TRACE_FLAG_ENABLED(grpc_inproc_trace)) { log_metadata(metadata, s->t->is_client, outflags != nullptr); } @@ -307,7 +307,7 @@ grpc_error* fill_in_metadata(inproc_stream* s, if (markfilled != nullptr) { *markfilled = true; } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; for (grpc_linked_mdelem* elem = metadata->list.head; (elem != nullptr) && (error == GRPC_ERROR_NONE); elem = elem->next) { grpc_linked_mdelem* nelem = @@ -374,7 +374,7 @@ void close_other_side_locked(inproc_stream* s, const char* reason) { // this stream_op_batch is only one of the pending operations for this // stream. This is called when one of the pending operations for the stream // is done and about to be NULLed out -void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error, +void complete_if_batch_end_locked(inproc_stream* s, grpc_error_handle error, grpc_transport_stream_op_batch* op, const char* msg) { int is_sm = static_cast(op == s->send_message_op); @@ -394,14 +394,14 @@ void complete_if_batch_end_locked(inproc_stream* s, grpc_error* error, } } -void maybe_process_ops_locked(inproc_stream* s, grpc_error* error) { +void maybe_process_ops_locked(inproc_stream* s, grpc_error_handle error) { if (s && (error != GRPC_ERROR_NONE || s->ops_needed)) { s->ops_needed = false; op_state_machine_locked(s, error); } } -void fail_helper_locked(inproc_stream* s, grpc_error* error) { +void fail_helper_locked(inproc_stream* s, grpc_error_handle error) { INPROC_LOG(GPR_INFO, "op_state_machine %p fail_helper", s); // If we're failing this side, we need to make sure that // we also send or have already sent trailing metadata @@ -431,7 +431,7 @@ void fail_helper_locked(inproc_stream* s, grpc_error* error) { } } if (s->recv_initial_md_op) { - grpc_error* err; + grpc_error_handle err; if (!s->t->is_client) { // If this is a server, provide initial metadata with a path and authority // since it expects that as well as no error yet @@ -550,7 +550,7 @@ void message_transfer_locked(inproc_stream* sender, inproc_stream* receiver) { GPR_ASSERT( sender->send_message_op->payload->send_message.send_message->Next( SIZE_MAX, &unused)); - grpc_error* error = + grpc_error_handle error = sender->send_message_op->payload->send_message.send_message->Pull( &message_slice); if (error != GRPC_ERROR_NONE) { @@ -583,13 +583,13 @@ void message_transfer_locked(inproc_stream* sender, inproc_stream* receiver) { sender->send_message_op = nullptr; } -void op_state_machine_locked(inproc_stream* s, grpc_error* error) { +void op_state_machine_locked(inproc_stream* s, grpc_error_handle error) { // This function gets called when we have contents in the unprocessed reads // Get what we want based on our ops wanted // Schedule our appropriate closures // and then return to ops_needed state if still needed - grpc_error* new_err = GRPC_ERROR_NONE; + grpc_error_handle new_err = GRPC_ERROR_NONE; bool needs_close = false; @@ -887,9 +887,10 @@ done: GRPC_ERROR_UNREF(new_err); } -bool cancel_stream_locked(inproc_stream* s, grpc_error* error) { +bool cancel_stream_locked(inproc_stream* s, grpc_error_handle error) { bool ret = false; // was the cancel accepted - INPROC_LOG(GPR_INFO, "cancel_stream %p with %s", s, grpc_error_string(error)); + INPROC_LOG(GPR_INFO, "cancel_stream %p with %s", s, + grpc_error_std_string(error).c_str()); if (s->cancel_self_error == GRPC_ERROR_NONE) { ret = true; s->cancel_self_error = GRPC_ERROR_REF(error); @@ -943,7 +944,7 @@ bool cancel_stream_locked(inproc_stream* s, grpc_error* error) { return ret; } -void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} +void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} void perform_stream_op(grpc_transport* gt, grpc_stream* gs, grpc_transport_stream_op_batch* op) { @@ -962,7 +963,7 @@ void perform_stream_op(grpc_transport* gt, grpc_stream* gs, s->t->is_client, false); } } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_closure* on_complete = op->on_complete; // TODO(roth): This is a hack needed because we use data inside of the // closure itself to do the barrier calculation (i.e., to ensure that @@ -1293,7 +1294,7 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server, client_args); // TODO(ncteisen): design and support channelz GetSocket for inproc. - grpc_error* error = server->core_server->SetupTransport( + grpc_error_handle error = server->core_server->SetupTransport( server_transport, nullptr, server_args, nullptr); grpc_channel* channel = nullptr; if (error == GRPC_ERROR_NONE) { @@ -1303,7 +1304,7 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server, if (error != GRPC_ERROR_NONE) { GPR_ASSERT(!channel); gpr_log(GPR_ERROR, "Failed to create client channel: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); intptr_t integer; grpc_status_code status = GRPC_STATUS_INTERNAL; if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) { @@ -1318,7 +1319,7 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server, } else { GPR_ASSERT(!channel); gpr_log(GPR_ERROR, "Failed to create server channel: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); intptr_t integer; grpc_status_code status = GRPC_STATUS_INTERNAL; if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &integer)) { diff --git a/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c b/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c new file mode 100644 index 00000000000..d230ccb2ff6 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c @@ -0,0 +1,406 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/admin/v3/config_dump.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/admin/v3/config_dump.upb.h" +#include "envoy/config/bootstrap/v3/bootstrap.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/timestamp.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_admin_v3_ConfigDump_submsgs[1] = { + &google_protobuf_Any_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ConfigDump__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_admin_v3_ConfigDump_msginit = { + &envoy_admin_v3_ConfigDump_submsgs[0], + &envoy_admin_v3_ConfigDump__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_UpdateFailureState_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_UpdateFailureState__fields[4] = { + {1, UPB_SIZE(20, 40), 1, 0, 11, 1}, + {2, UPB_SIZE(24, 48), 2, 1, 11, 1}, + {3, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {4, UPB_SIZE(12, 24), 0, 0, 9, 1}, +}; + +const upb_msglayout envoy_admin_v3_UpdateFailureState_msginit = { + &envoy_admin_v3_UpdateFailureState_submsgs[0], + &envoy_admin_v3_UpdateFailureState__fields[0], + UPB_SIZE(32, 64), 4, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_BootstrapConfigDump_submsgs[2] = { + &envoy_config_bootstrap_v3_Bootstrap_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_BootstrapConfigDump__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 2, 1, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_BootstrapConfigDump_msginit = { + &envoy_admin_v3_BootstrapConfigDump_submsgs[0], + &envoy_admin_v3_BootstrapConfigDump__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ListenersConfigDump_submsgs[2] = { + &envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit, + &envoy_admin_v3_ListenersConfigDump_StaticListener_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ListenersConfigDump__fields[3] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {2, UPB_SIZE(8, 16), 0, 1, 11, 3}, + {3, UPB_SIZE(12, 24), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_admin_v3_ListenersConfigDump_msginit = { + &envoy_admin_v3_ListenersConfigDump_submsgs[0], + &envoy_admin_v3_ListenersConfigDump__fields[0], + UPB_SIZE(16, 32), 3, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ListenersConfigDump_StaticListener_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ListenersConfigDump_StaticListener__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 2, 1, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_ListenersConfigDump_StaticListener_msginit = { + &envoy_admin_v3_ListenersConfigDump_StaticListener_submsgs[0], + &envoy_admin_v3_ListenersConfigDump_StaticListener__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ListenersConfigDump_DynamicListenerState_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ListenersConfigDump_DynamicListenerState__fields[3] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(12, 24), 1, 0, 11, 1}, + {3, UPB_SIZE(16, 32), 2, 1, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit = { + &envoy_admin_v3_ListenersConfigDump_DynamicListenerState_submsgs[0], + &envoy_admin_v3_ListenersConfigDump_DynamicListenerState__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ListenersConfigDump_DynamicListener_submsgs[2] = { + &envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, + &envoy_admin_v3_UpdateFailureState_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ListenersConfigDump_DynamicListener__fields[6] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 24), 1, 0, 11, 1}, + {3, UPB_SIZE(20, 32), 2, 0, 11, 1}, + {4, UPB_SIZE(24, 40), 3, 0, 11, 1}, + {5, UPB_SIZE(28, 48), 4, 1, 11, 1}, + {6, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit = { + &envoy_admin_v3_ListenersConfigDump_DynamicListener_submsgs[0], + &envoy_admin_v3_ListenersConfigDump_DynamicListener__fields[0], + UPB_SIZE(32, 64), 6, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ClustersConfigDump_submsgs[2] = { + &envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, + &envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ClustersConfigDump__fields[4] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {2, UPB_SIZE(8, 16), 0, 1, 11, 3}, + {3, UPB_SIZE(12, 24), 0, 0, 11, 3}, + {4, UPB_SIZE(16, 32), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_admin_v3_ClustersConfigDump_msginit = { + &envoy_admin_v3_ClustersConfigDump_submsgs[0], + &envoy_admin_v3_ClustersConfigDump__fields[0], + UPB_SIZE(24, 48), 4, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ClustersConfigDump_StaticCluster_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ClustersConfigDump_StaticCluster__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 2, 1, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit = { + &envoy_admin_v3_ClustersConfigDump_StaticCluster_submsgs[0], + &envoy_admin_v3_ClustersConfigDump_StaticCluster__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ClustersConfigDump_DynamicCluster_submsgs[3] = { + &envoy_admin_v3_UpdateFailureState_msginit, + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ClustersConfigDump_DynamicCluster__fields[5] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 24), 1, 1, 11, 1}, + {3, UPB_SIZE(20, 32), 2, 2, 11, 1}, + {4, UPB_SIZE(24, 40), 3, 0, 11, 1}, + {5, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit = { + &envoy_admin_v3_ClustersConfigDump_DynamicCluster_submsgs[0], + &envoy_admin_v3_ClustersConfigDump_DynamicCluster__fields[0], + UPB_SIZE(32, 48), 5, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_RoutesConfigDump_submsgs[2] = { + &envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit, + &envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_RoutesConfigDump__fields[2] = { + {2, UPB_SIZE(0, 0), 0, 1, 11, 3}, + {3, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_admin_v3_RoutesConfigDump_msginit = { + &envoy_admin_v3_RoutesConfigDump_submsgs[0], + &envoy_admin_v3_RoutesConfigDump__fields[0], + UPB_SIZE(8, 16), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_RoutesConfigDump_StaticRouteConfig__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 2, 1, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit = { + &envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_submsgs[0], + &envoy_admin_v3_RoutesConfigDump_StaticRouteConfig__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_submsgs[3] = { + &envoy_admin_v3_UpdateFailureState_msginit, + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig__fields[5] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 24), 1, 1, 11, 1}, + {3, UPB_SIZE(20, 32), 2, 2, 11, 1}, + {4, UPB_SIZE(24, 40), 3, 0, 11, 1}, + {5, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit = { + &envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_submsgs[0], + &envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig__fields[0], + UPB_SIZE(32, 48), 5, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ScopedRoutesConfigDump_submsgs[2] = { + &envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit, + &envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ScopedRoutesConfigDump__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 1, 11, 3}, + {2, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_msginit = { + &envoy_admin_v3_ScopedRoutesConfigDump_submsgs[0], + &envoy_admin_v3_ScopedRoutesConfigDump__fields[0], + UPB_SIZE(8, 16), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs__fields[3] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 32), 0, 0, 11, 3}, + {3, UPB_SIZE(12, 24), 1, 1, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit = { + &envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_submsgs[0], + &envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_submsgs[3] = { + &envoy_admin_v3_UpdateFailureState_msginit, + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs__fields[6] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 24), 0, 0, 9, 1}, + {3, UPB_SIZE(32, 56), 0, 1, 11, 3}, + {4, UPB_SIZE(24, 40), 1, 2, 11, 1}, + {5, UPB_SIZE(28, 48), 2, 0, 11, 1}, + {6, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit = { + &envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_submsgs[0], + &envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs__fields[0], + UPB_SIZE(40, 64), 6, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_SecretsConfigDump_submsgs[2] = { + &envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, + &envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_SecretsConfigDump__fields[3] = { + {1, UPB_SIZE(0, 0), 0, 1, 11, 3}, + {2, UPB_SIZE(4, 8), 0, 0, 11, 3}, + {3, UPB_SIZE(8, 16), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_admin_v3_SecretsConfigDump_msginit = { + &envoy_admin_v3_SecretsConfigDump_submsgs[0], + &envoy_admin_v3_SecretsConfigDump__fields[0], + UPB_SIZE(16, 24), 3, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_SecretsConfigDump_DynamicSecret_submsgs[3] = { + &envoy_admin_v3_UpdateFailureState_msginit, + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_SecretsConfigDump_DynamicSecret__fields[6] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 24), 0, 0, 9, 1}, + {3, UPB_SIZE(24, 40), 1, 2, 11, 1}, + {4, UPB_SIZE(28, 48), 2, 1, 11, 1}, + {5, UPB_SIZE(32, 56), 3, 0, 11, 1}, + {6, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit = { + &envoy_admin_v3_SecretsConfigDump_DynamicSecret_submsgs[0], + &envoy_admin_v3_SecretsConfigDump_DynamicSecret__fields[0], + UPB_SIZE(40, 64), 6, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_SecretsConfigDump_StaticSecret_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_SecretsConfigDump_StaticSecret__fields[3] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(12, 24), 1, 1, 11, 1}, + {3, UPB_SIZE(16, 32), 2, 0, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit = { + &envoy_admin_v3_SecretsConfigDump_StaticSecret_submsgs[0], + &envoy_admin_v3_SecretsConfigDump_StaticSecret__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_EndpointsConfigDump_submsgs[2] = { + &envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit, + &envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_EndpointsConfigDump__fields[2] = { + {2, UPB_SIZE(0, 0), 0, 1, 11, 3}, + {3, UPB_SIZE(4, 8), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_admin_v3_EndpointsConfigDump_msginit = { + &envoy_admin_v3_EndpointsConfigDump_submsgs[0], + &envoy_admin_v3_EndpointsConfigDump__fields[0], + UPB_SIZE(8, 16), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_submsgs[2] = { + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 2, 1, 11, 1}, +}; + +const upb_msglayout envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit = { + &envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_submsgs[0], + &envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_submsgs[3] = { + &envoy_admin_v3_UpdateFailureState_msginit, + &google_protobuf_Any_msginit, + &google_protobuf_Timestamp_msginit, +}; + +static const upb_msglayout_field envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig__fields[5] = { + {1, UPB_SIZE(8, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 24), 1, 1, 11, 1}, + {3, UPB_SIZE(20, 32), 2, 2, 11, 1}, + {4, UPB_SIZE(24, 40), 3, 0, 11, 1}, + {5, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit = { + &envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_submsgs[0], + &envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig__fields[0], + UPB_SIZE(32, 48), 5, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h b/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h new file mode 100644 index 00000000000..6f117c6659d --- /dev/null +++ b/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h @@ -0,0 +1,1459 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/admin/v3/config_dump.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_ADMIN_V3_CONFIG_DUMP_PROTO_UPB_H_ +#define ENVOY_ADMIN_V3_CONFIG_DUMP_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_admin_v3_ConfigDump; +struct envoy_admin_v3_UpdateFailureState; +struct envoy_admin_v3_BootstrapConfigDump; +struct envoy_admin_v3_ListenersConfigDump; +struct envoy_admin_v3_ListenersConfigDump_StaticListener; +struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState; +struct envoy_admin_v3_ListenersConfigDump_DynamicListener; +struct envoy_admin_v3_ClustersConfigDump; +struct envoy_admin_v3_ClustersConfigDump_StaticCluster; +struct envoy_admin_v3_ClustersConfigDump_DynamicCluster; +struct envoy_admin_v3_RoutesConfigDump; +struct envoy_admin_v3_RoutesConfigDump_StaticRouteConfig; +struct envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig; +struct envoy_admin_v3_ScopedRoutesConfigDump; +struct envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs; +struct envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs; +struct envoy_admin_v3_SecretsConfigDump; +struct envoy_admin_v3_SecretsConfigDump_DynamicSecret; +struct envoy_admin_v3_SecretsConfigDump_StaticSecret; +struct envoy_admin_v3_EndpointsConfigDump; +struct envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig; +struct envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig; +typedef struct envoy_admin_v3_ConfigDump envoy_admin_v3_ConfigDump; +typedef struct envoy_admin_v3_UpdateFailureState envoy_admin_v3_UpdateFailureState; +typedef struct envoy_admin_v3_BootstrapConfigDump envoy_admin_v3_BootstrapConfigDump; +typedef struct envoy_admin_v3_ListenersConfigDump envoy_admin_v3_ListenersConfigDump; +typedef struct envoy_admin_v3_ListenersConfigDump_StaticListener envoy_admin_v3_ListenersConfigDump_StaticListener; +typedef struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState envoy_admin_v3_ListenersConfigDump_DynamicListenerState; +typedef struct envoy_admin_v3_ListenersConfigDump_DynamicListener envoy_admin_v3_ListenersConfigDump_DynamicListener; +typedef struct envoy_admin_v3_ClustersConfigDump envoy_admin_v3_ClustersConfigDump; +typedef struct envoy_admin_v3_ClustersConfigDump_StaticCluster envoy_admin_v3_ClustersConfigDump_StaticCluster; +typedef struct envoy_admin_v3_ClustersConfigDump_DynamicCluster envoy_admin_v3_ClustersConfigDump_DynamicCluster; +typedef struct envoy_admin_v3_RoutesConfigDump envoy_admin_v3_RoutesConfigDump; +typedef struct envoy_admin_v3_RoutesConfigDump_StaticRouteConfig envoy_admin_v3_RoutesConfigDump_StaticRouteConfig; +typedef struct envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig; +typedef struct envoy_admin_v3_ScopedRoutesConfigDump envoy_admin_v3_ScopedRoutesConfigDump; +typedef struct envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs; +typedef struct envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs; +typedef struct envoy_admin_v3_SecretsConfigDump envoy_admin_v3_SecretsConfigDump; +typedef struct envoy_admin_v3_SecretsConfigDump_DynamicSecret envoy_admin_v3_SecretsConfigDump_DynamicSecret; +typedef struct envoy_admin_v3_SecretsConfigDump_StaticSecret envoy_admin_v3_SecretsConfigDump_StaticSecret; +typedef struct envoy_admin_v3_EndpointsConfigDump envoy_admin_v3_EndpointsConfigDump; +typedef struct envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig; +typedef struct envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig; +extern const upb_msglayout envoy_admin_v3_ConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_UpdateFailureState_msginit; +extern const upb_msglayout envoy_admin_v3_BootstrapConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_StaticListener_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit; +extern const upb_msglayout envoy_admin_v3_ClustersConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit; +extern const upb_msglayout envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit; +extern const upb_msglayout envoy_admin_v3_RoutesConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit; +extern const upb_msglayout envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit; +extern const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit; +extern const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit; +extern const upb_msglayout envoy_admin_v3_SecretsConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit; +extern const upb_msglayout envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit; +extern const upb_msglayout envoy_admin_v3_EndpointsConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit; +extern const upb_msglayout envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit; +struct envoy_config_bootstrap_v3_Bootstrap; +struct google_protobuf_Any; +struct google_protobuf_Timestamp; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_msginit; +extern const upb_msglayout google_protobuf_Any_msginit; +extern const upb_msglayout google_protobuf_Timestamp_msginit; + +typedef enum { + envoy_admin_v3_UNKNOWN = 0, + envoy_admin_v3_REQUESTED = 1, + envoy_admin_v3_DOES_NOT_EXIST = 2, + envoy_admin_v3_ACKED = 3, + envoy_admin_v3_NACKED = 4 +} envoy_admin_v3_ClientResourceStatus; + + +/* envoy.admin.v3.ConfigDump */ + +UPB_INLINE envoy_admin_v3_ConfigDump *envoy_admin_v3_ConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_ConfigDump *)_upb_msg_new(&envoy_admin_v3_ConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ConfigDump *envoy_admin_v3_ConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ConfigDump *ret = envoy_admin_v3_ConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ConfigDump *envoy_admin_v3_ConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ConfigDump *ret = envoy_admin_v3_ConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ConfigDump_serialize(const envoy_admin_v3_ConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ConfigDump_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_ConfigDump_has_configs(const envoy_admin_v3_ConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const struct google_protobuf_Any* const* envoy_admin_v3_ConfigDump_configs(const envoy_admin_v3_ConfigDump *msg, size_t *len) { return (const struct google_protobuf_Any* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE struct google_protobuf_Any** envoy_admin_v3_ConfigDump_mutable_configs(envoy_admin_v3_ConfigDump *msg, size_t *len) { + return (struct google_protobuf_Any**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE struct google_protobuf_Any** envoy_admin_v3_ConfigDump_resize_configs(envoy_admin_v3_ConfigDump *msg, size_t len, upb_arena *arena) { + return (struct google_protobuf_Any**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_ConfigDump_add_configs(envoy_admin_v3_ConfigDump *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.admin.v3.UpdateFailureState */ + +UPB_INLINE envoy_admin_v3_UpdateFailureState *envoy_admin_v3_UpdateFailureState_new(upb_arena *arena) { + return (envoy_admin_v3_UpdateFailureState *)_upb_msg_new(&envoy_admin_v3_UpdateFailureState_msginit, arena); +} +UPB_INLINE envoy_admin_v3_UpdateFailureState *envoy_admin_v3_UpdateFailureState_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_UpdateFailureState *ret = envoy_admin_v3_UpdateFailureState_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_UpdateFailureState_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_UpdateFailureState *envoy_admin_v3_UpdateFailureState_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_UpdateFailureState *ret = envoy_admin_v3_UpdateFailureState_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_UpdateFailureState_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_UpdateFailureState_serialize(const envoy_admin_v3_UpdateFailureState *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_UpdateFailureState_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_UpdateFailureState_has_failed_configuration(const envoy_admin_v3_UpdateFailureState *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_UpdateFailureState_failed_configuration(const envoy_admin_v3_UpdateFailureState *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_UpdateFailureState_has_last_update_attempt(const envoy_admin_v3_UpdateFailureState *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_UpdateFailureState_last_update_attempt(const envoy_admin_v3_UpdateFailureState *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 48), const struct google_protobuf_Timestamp*); } +UPB_INLINE upb_strview envoy_admin_v3_UpdateFailureState_details(const envoy_admin_v3_UpdateFailureState *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE upb_strview envoy_admin_v3_UpdateFailureState_version_info(const envoy_admin_v3_UpdateFailureState *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } + +UPB_INLINE void envoy_admin_v3_UpdateFailureState_set_failed_configuration(envoy_admin_v3_UpdateFailureState *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_UpdateFailureState_mutable_failed_configuration(envoy_admin_v3_UpdateFailureState *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_UpdateFailureState_failed_configuration(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_UpdateFailureState_set_failed_configuration(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_UpdateFailureState_set_last_update_attempt(envoy_admin_v3_UpdateFailureState *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(24, 48), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_UpdateFailureState_mutable_last_update_attempt(envoy_admin_v3_UpdateFailureState *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_UpdateFailureState_last_update_attempt(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_UpdateFailureState_set_last_update_attempt(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_UpdateFailureState_set_details(envoy_admin_v3_UpdateFailureState *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_UpdateFailureState_set_version_info(envoy_admin_v3_UpdateFailureState *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} + +/* envoy.admin.v3.BootstrapConfigDump */ + +UPB_INLINE envoy_admin_v3_BootstrapConfigDump *envoy_admin_v3_BootstrapConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_BootstrapConfigDump *)_upb_msg_new(&envoy_admin_v3_BootstrapConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_BootstrapConfigDump *envoy_admin_v3_BootstrapConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_BootstrapConfigDump *ret = envoy_admin_v3_BootstrapConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_BootstrapConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_BootstrapConfigDump *envoy_admin_v3_BootstrapConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_BootstrapConfigDump *ret = envoy_admin_v3_BootstrapConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_BootstrapConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_BootstrapConfigDump_serialize(const envoy_admin_v3_BootstrapConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_BootstrapConfigDump_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_BootstrapConfigDump_has_bootstrap(const envoy_admin_v3_BootstrapConfigDump *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_bootstrap_v3_Bootstrap* envoy_admin_v3_BootstrapConfigDump_bootstrap(const envoy_admin_v3_BootstrapConfigDump *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_config_bootstrap_v3_Bootstrap*); } +UPB_INLINE bool envoy_admin_v3_BootstrapConfigDump_has_last_updated(const envoy_admin_v3_BootstrapConfigDump *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_BootstrapConfigDump_last_updated(const envoy_admin_v3_BootstrapConfigDump *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_Timestamp*); } + +UPB_INLINE void envoy_admin_v3_BootstrapConfigDump_set_bootstrap(envoy_admin_v3_BootstrapConfigDump *msg, struct envoy_config_bootstrap_v3_Bootstrap* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_config_bootstrap_v3_Bootstrap*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Bootstrap* envoy_admin_v3_BootstrapConfigDump_mutable_bootstrap(envoy_admin_v3_BootstrapConfigDump *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Bootstrap* sub = (struct envoy_config_bootstrap_v3_Bootstrap*)envoy_admin_v3_BootstrapConfigDump_bootstrap(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Bootstrap*)_upb_msg_new(&envoy_config_bootstrap_v3_Bootstrap_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_BootstrapConfigDump_set_bootstrap(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_BootstrapConfigDump_set_last_updated(envoy_admin_v3_BootstrapConfigDump *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_BootstrapConfigDump_mutable_last_updated(envoy_admin_v3_BootstrapConfigDump *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_BootstrapConfigDump_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_BootstrapConfigDump_set_last_updated(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.ListenersConfigDump */ + +UPB_INLINE envoy_admin_v3_ListenersConfigDump *envoy_admin_v3_ListenersConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_ListenersConfigDump *)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump *envoy_admin_v3_ListenersConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ListenersConfigDump *ret = envoy_admin_v3_ListenersConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump *envoy_admin_v3_ListenersConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ListenersConfigDump *ret = envoy_admin_v3_ListenersConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ListenersConfigDump_serialize(const envoy_admin_v3_ListenersConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ListenersConfigDump_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_ListenersConfigDump_version_info(const envoy_admin_v3_ListenersConfigDump *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_has_static_listeners(const envoy_admin_v3_ListenersConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const envoy_admin_v3_ListenersConfigDump_StaticListener* const* envoy_admin_v3_ListenersConfigDump_static_listeners(const envoy_admin_v3_ListenersConfigDump *msg, size_t *len) { return (const envoy_admin_v3_ListenersConfigDump_StaticListener* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_has_dynamic_listeners(const envoy_admin_v3_ListenersConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 24)); } +UPB_INLINE const envoy_admin_v3_ListenersConfigDump_DynamicListener* const* envoy_admin_v3_ListenersConfigDump_dynamic_listeners(const envoy_admin_v3_ListenersConfigDump *msg, size_t *len) { return (const envoy_admin_v3_ListenersConfigDump_DynamicListener* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); } + +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_set_version_info(envoy_admin_v3_ListenersConfigDump *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_StaticListener** envoy_admin_v3_ListenersConfigDump_mutable_static_listeners(envoy_admin_v3_ListenersConfigDump *msg, size_t *len) { + return (envoy_admin_v3_ListenersConfigDump_StaticListener**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_StaticListener** envoy_admin_v3_ListenersConfigDump_resize_static_listeners(envoy_admin_v3_ListenersConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_ListenersConfigDump_StaticListener**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_ListenersConfigDump_StaticListener* envoy_admin_v3_ListenersConfigDump_add_static_listeners(envoy_admin_v3_ListenersConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_ListenersConfigDump_StaticListener* sub = (struct envoy_admin_v3_ListenersConfigDump_StaticListener*)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_StaticListener_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListener** envoy_admin_v3_ListenersConfigDump_mutable_dynamic_listeners(envoy_admin_v3_ListenersConfigDump *msg, size_t *len) { + return (envoy_admin_v3_ListenersConfigDump_DynamicListener**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len); +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListener** envoy_admin_v3_ListenersConfigDump_resize_dynamic_listeners(envoy_admin_v3_ListenersConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_ListenersConfigDump_DynamicListener**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_ListenersConfigDump_DynamicListener* envoy_admin_v3_ListenersConfigDump_add_dynamic_listeners(envoy_admin_v3_ListenersConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_ListenersConfigDump_DynamicListener* sub = (struct envoy_admin_v3_ListenersConfigDump_DynamicListener*)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(12, 24), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.admin.v3.ListenersConfigDump.StaticListener */ + +UPB_INLINE envoy_admin_v3_ListenersConfigDump_StaticListener *envoy_admin_v3_ListenersConfigDump_StaticListener_new(upb_arena *arena) { + return (envoy_admin_v3_ListenersConfigDump_StaticListener *)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_StaticListener_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_StaticListener *envoy_admin_v3_ListenersConfigDump_StaticListener_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ListenersConfigDump_StaticListener *ret = envoy_admin_v3_ListenersConfigDump_StaticListener_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_StaticListener_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_StaticListener *envoy_admin_v3_ListenersConfigDump_StaticListener_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ListenersConfigDump_StaticListener *ret = envoy_admin_v3_ListenersConfigDump_StaticListener_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_StaticListener_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ListenersConfigDump_StaticListener_serialize(const envoy_admin_v3_ListenersConfigDump_StaticListener *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ListenersConfigDump_StaticListener_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_StaticListener_has_listener(const envoy_admin_v3_ListenersConfigDump_StaticListener *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_ListenersConfigDump_StaticListener_listener(const envoy_admin_v3_ListenersConfigDump_StaticListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_StaticListener_has_last_updated(const envoy_admin_v3_ListenersConfigDump_StaticListener *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_ListenersConfigDump_StaticListener_last_updated(const envoy_admin_v3_ListenersConfigDump_StaticListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_Timestamp*); } + +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_StaticListener_set_listener(envoy_admin_v3_ListenersConfigDump_StaticListener *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_ListenersConfigDump_StaticListener_mutable_listener(envoy_admin_v3_ListenersConfigDump_StaticListener *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_ListenersConfigDump_StaticListener_listener(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_StaticListener_set_listener(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_StaticListener_set_last_updated(envoy_admin_v3_ListenersConfigDump_StaticListener *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_ListenersConfigDump_StaticListener_mutable_last_updated(envoy_admin_v3_ListenersConfigDump_StaticListener *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_ListenersConfigDump_StaticListener_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_StaticListener_set_last_updated(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.ListenersConfigDump.DynamicListenerState */ + +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListenerState *envoy_admin_v3_ListenersConfigDump_DynamicListenerState_new(upb_arena *arena) { + return (envoy_admin_v3_ListenersConfigDump_DynamicListenerState *)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListenerState *envoy_admin_v3_ListenersConfigDump_DynamicListenerState_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ListenersConfigDump_DynamicListenerState *ret = envoy_admin_v3_ListenersConfigDump_DynamicListenerState_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListenerState *envoy_admin_v3_ListenersConfigDump_DynamicListenerState_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ListenersConfigDump_DynamicListenerState *ret = envoy_admin_v3_ListenersConfigDump_DynamicListenerState_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ListenersConfigDump_DynamicListenerState_serialize(const envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_ListenersConfigDump_DynamicListenerState_version_info(const envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_DynamicListenerState_has_listener(const envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_ListenersConfigDump_DynamicListenerState_listener(const envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_DynamicListenerState_has_last_updated(const envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_ListenersConfigDump_DynamicListenerState_last_updated(const envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), const struct google_protobuf_Timestamp*); } + +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_version_info(envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_listener(envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_ListenersConfigDump_DynamicListenerState_mutable_listener(envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_ListenersConfigDump_DynamicListenerState_listener(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_listener(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_last_updated(envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(16, 32), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_ListenersConfigDump_DynamicListenerState_mutable_last_updated(envoy_admin_v3_ListenersConfigDump_DynamicListenerState *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_ListenersConfigDump_DynamicListenerState_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_last_updated(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.ListenersConfigDump.DynamicListener */ + +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListener *envoy_admin_v3_ListenersConfigDump_DynamicListener_new(upb_arena *arena) { + return (envoy_admin_v3_ListenersConfigDump_DynamicListener *)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListener *envoy_admin_v3_ListenersConfigDump_DynamicListener_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ListenersConfigDump_DynamicListener *ret = envoy_admin_v3_ListenersConfigDump_DynamicListener_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ListenersConfigDump_DynamicListener *envoy_admin_v3_ListenersConfigDump_DynamicListener_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ListenersConfigDump_DynamicListener *ret = envoy_admin_v3_ListenersConfigDump_DynamicListener_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ListenersConfigDump_DynamicListener_serialize(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_ListenersConfigDump_DynamicListener_name(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_DynamicListener_has_active_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const envoy_admin_v3_ListenersConfigDump_DynamicListenerState* envoy_admin_v3_ListenersConfigDump_DynamicListener_active_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const envoy_admin_v3_ListenersConfigDump_DynamicListenerState*); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_DynamicListener_has_warming_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const envoy_admin_v3_ListenersConfigDump_DynamicListenerState* envoy_admin_v3_ListenersConfigDump_DynamicListener_warming_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const envoy_admin_v3_ListenersConfigDump_DynamicListenerState*); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_DynamicListener_has_draining_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const envoy_admin_v3_ListenersConfigDump_DynamicListenerState* envoy_admin_v3_ListenersConfigDump_DynamicListener_draining_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), const envoy_admin_v3_ListenersConfigDump_DynamicListenerState*); } +UPB_INLINE bool envoy_admin_v3_ListenersConfigDump_DynamicListener_has_error_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const envoy_admin_v3_UpdateFailureState* envoy_admin_v3_ListenersConfigDump_DynamicListener_error_state(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 48), const envoy_admin_v3_UpdateFailureState*); } +UPB_INLINE int32_t envoy_admin_v3_ListenersConfigDump_DynamicListener_client_status(const envoy_admin_v3_ListenersConfigDump_DynamicListener *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListener_set_name(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListener_set_active_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, envoy_admin_v3_ListenersConfigDump_DynamicListenerState* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), envoy_admin_v3_ListenersConfigDump_DynamicListenerState*) = value; +} +UPB_INLINE struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState* envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_active_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, upb_arena *arena) { + struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState* sub = (struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState*)envoy_admin_v3_ListenersConfigDump_DynamicListener_active_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState*)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_DynamicListener_set_active_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListener_set_warming_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, envoy_admin_v3_ListenersConfigDump_DynamicListenerState* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(20, 32), envoy_admin_v3_ListenersConfigDump_DynamicListenerState*) = value; +} +UPB_INLINE struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState* envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_warming_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, upb_arena *arena) { + struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState* sub = (struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState*)envoy_admin_v3_ListenersConfigDump_DynamicListener_warming_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState*)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_DynamicListener_set_warming_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListener_set_draining_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, envoy_admin_v3_ListenersConfigDump_DynamicListenerState* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(24, 40), envoy_admin_v3_ListenersConfigDump_DynamicListenerState*) = value; +} +UPB_INLINE struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState* envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_draining_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, upb_arena *arena) { + struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState* sub = (struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState*)envoy_admin_v3_ListenersConfigDump_DynamicListener_draining_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_ListenersConfigDump_DynamicListenerState*)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_DynamicListener_set_draining_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListener_set_error_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, envoy_admin_v3_UpdateFailureState* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(28, 48), envoy_admin_v3_UpdateFailureState*) = value; +} +UPB_INLINE struct envoy_admin_v3_UpdateFailureState* envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_error_state(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, upb_arena *arena) { + struct envoy_admin_v3_UpdateFailureState* sub = (struct envoy_admin_v3_UpdateFailureState*)envoy_admin_v3_ListenersConfigDump_DynamicListener_error_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_UpdateFailureState*)_upb_msg_new(&envoy_admin_v3_UpdateFailureState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ListenersConfigDump_DynamicListener_set_error_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ListenersConfigDump_DynamicListener_set_client_status(envoy_admin_v3_ListenersConfigDump_DynamicListener *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +/* envoy.admin.v3.ClustersConfigDump */ + +UPB_INLINE envoy_admin_v3_ClustersConfigDump *envoy_admin_v3_ClustersConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_ClustersConfigDump *)_upb_msg_new(&envoy_admin_v3_ClustersConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump *envoy_admin_v3_ClustersConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ClustersConfigDump *ret = envoy_admin_v3_ClustersConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ClustersConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump *envoy_admin_v3_ClustersConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ClustersConfigDump *ret = envoy_admin_v3_ClustersConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ClustersConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ClustersConfigDump_serialize(const envoy_admin_v3_ClustersConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ClustersConfigDump_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_ClustersConfigDump_version_info(const envoy_admin_v3_ClustersConfigDump *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_has_static_clusters(const envoy_admin_v3_ClustersConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const envoy_admin_v3_ClustersConfigDump_StaticCluster* const* envoy_admin_v3_ClustersConfigDump_static_clusters(const envoy_admin_v3_ClustersConfigDump *msg, size_t *len) { return (const envoy_admin_v3_ClustersConfigDump_StaticCluster* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_has_dynamic_active_clusters(const envoy_admin_v3_ClustersConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 24)); } +UPB_INLINE const envoy_admin_v3_ClustersConfigDump_DynamicCluster* const* envoy_admin_v3_ClustersConfigDump_dynamic_active_clusters(const envoy_admin_v3_ClustersConfigDump *msg, size_t *len) { return (const envoy_admin_v3_ClustersConfigDump_DynamicCluster* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); } +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_has_dynamic_warming_clusters(const envoy_admin_v3_ClustersConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const envoy_admin_v3_ClustersConfigDump_DynamicCluster* const* envoy_admin_v3_ClustersConfigDump_dynamic_warming_clusters(const envoy_admin_v3_ClustersConfigDump *msg, size_t *len) { return (const envoy_admin_v3_ClustersConfigDump_DynamicCluster* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } + +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_set_version_info(envoy_admin_v3_ClustersConfigDump *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_StaticCluster** envoy_admin_v3_ClustersConfigDump_mutable_static_clusters(envoy_admin_v3_ClustersConfigDump *msg, size_t *len) { + return (envoy_admin_v3_ClustersConfigDump_StaticCluster**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_StaticCluster** envoy_admin_v3_ClustersConfigDump_resize_static_clusters(envoy_admin_v3_ClustersConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_ClustersConfigDump_StaticCluster**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_ClustersConfigDump_StaticCluster* envoy_admin_v3_ClustersConfigDump_add_static_clusters(envoy_admin_v3_ClustersConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_ClustersConfigDump_StaticCluster* sub = (struct envoy_admin_v3_ClustersConfigDump_StaticCluster*)_upb_msg_new(&envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_DynamicCluster** envoy_admin_v3_ClustersConfigDump_mutable_dynamic_active_clusters(envoy_admin_v3_ClustersConfigDump *msg, size_t *len) { + return (envoy_admin_v3_ClustersConfigDump_DynamicCluster**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len); +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_DynamicCluster** envoy_admin_v3_ClustersConfigDump_resize_dynamic_active_clusters(envoy_admin_v3_ClustersConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_ClustersConfigDump_DynamicCluster**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_ClustersConfigDump_DynamicCluster* envoy_admin_v3_ClustersConfigDump_add_dynamic_active_clusters(envoy_admin_v3_ClustersConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_ClustersConfigDump_DynamicCluster* sub = (struct envoy_admin_v3_ClustersConfigDump_DynamicCluster*)_upb_msg_new(&envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(12, 24), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_DynamicCluster** envoy_admin_v3_ClustersConfigDump_mutable_dynamic_warming_clusters(envoy_admin_v3_ClustersConfigDump *msg, size_t *len) { + return (envoy_admin_v3_ClustersConfigDump_DynamicCluster**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_DynamicCluster** envoy_admin_v3_ClustersConfigDump_resize_dynamic_warming_clusters(envoy_admin_v3_ClustersConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_ClustersConfigDump_DynamicCluster**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_ClustersConfigDump_DynamicCluster* envoy_admin_v3_ClustersConfigDump_add_dynamic_warming_clusters(envoy_admin_v3_ClustersConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_ClustersConfigDump_DynamicCluster* sub = (struct envoy_admin_v3_ClustersConfigDump_DynamicCluster*)_upb_msg_new(&envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.admin.v3.ClustersConfigDump.StaticCluster */ + +UPB_INLINE envoy_admin_v3_ClustersConfigDump_StaticCluster *envoy_admin_v3_ClustersConfigDump_StaticCluster_new(upb_arena *arena) { + return (envoy_admin_v3_ClustersConfigDump_StaticCluster *)_upb_msg_new(&envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_StaticCluster *envoy_admin_v3_ClustersConfigDump_StaticCluster_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ClustersConfigDump_StaticCluster *ret = envoy_admin_v3_ClustersConfigDump_StaticCluster_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_StaticCluster *envoy_admin_v3_ClustersConfigDump_StaticCluster_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ClustersConfigDump_StaticCluster *ret = envoy_admin_v3_ClustersConfigDump_StaticCluster_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ClustersConfigDump_StaticCluster_serialize(const envoy_admin_v3_ClustersConfigDump_StaticCluster *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_StaticCluster_has_cluster(const envoy_admin_v3_ClustersConfigDump_StaticCluster *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_ClustersConfigDump_StaticCluster_cluster(const envoy_admin_v3_ClustersConfigDump_StaticCluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_StaticCluster_has_last_updated(const envoy_admin_v3_ClustersConfigDump_StaticCluster *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_ClustersConfigDump_StaticCluster_last_updated(const envoy_admin_v3_ClustersConfigDump_StaticCluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_Timestamp*); } + +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_StaticCluster_set_cluster(envoy_admin_v3_ClustersConfigDump_StaticCluster *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_ClustersConfigDump_StaticCluster_mutable_cluster(envoy_admin_v3_ClustersConfigDump_StaticCluster *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_ClustersConfigDump_StaticCluster_cluster(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ClustersConfigDump_StaticCluster_set_cluster(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_StaticCluster_set_last_updated(envoy_admin_v3_ClustersConfigDump_StaticCluster *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_ClustersConfigDump_StaticCluster_mutable_last_updated(envoy_admin_v3_ClustersConfigDump_StaticCluster *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_ClustersConfigDump_StaticCluster_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ClustersConfigDump_StaticCluster_set_last_updated(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.ClustersConfigDump.DynamicCluster */ + +UPB_INLINE envoy_admin_v3_ClustersConfigDump_DynamicCluster *envoy_admin_v3_ClustersConfigDump_DynamicCluster_new(upb_arena *arena) { + return (envoy_admin_v3_ClustersConfigDump_DynamicCluster *)_upb_msg_new(&envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_DynamicCluster *envoy_admin_v3_ClustersConfigDump_DynamicCluster_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ClustersConfigDump_DynamicCluster *ret = envoy_admin_v3_ClustersConfigDump_DynamicCluster_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ClustersConfigDump_DynamicCluster *envoy_admin_v3_ClustersConfigDump_DynamicCluster_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ClustersConfigDump_DynamicCluster *ret = envoy_admin_v3_ClustersConfigDump_DynamicCluster_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ClustersConfigDump_DynamicCluster_serialize(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_ClustersConfigDump_DynamicCluster_version_info(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_DynamicCluster_has_cluster(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_ClustersConfigDump_DynamicCluster_cluster(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_DynamicCluster_has_last_updated(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_ClustersConfigDump_DynamicCluster_last_updated(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const struct google_protobuf_Timestamp*); } +UPB_INLINE bool envoy_admin_v3_ClustersConfigDump_DynamicCluster_has_error_state(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const envoy_admin_v3_UpdateFailureState* envoy_admin_v3_ClustersConfigDump_DynamicCluster_error_state(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), const envoy_admin_v3_UpdateFailureState*); } +UPB_INLINE int32_t envoy_admin_v3_ClustersConfigDump_DynamicCluster_client_status(const envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_version_info(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_cluster(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_ClustersConfigDump_DynamicCluster_mutable_cluster(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_ClustersConfigDump_DynamicCluster_cluster(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_cluster(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_last_updated(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(20, 32), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_ClustersConfigDump_DynamicCluster_mutable_last_updated(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_ClustersConfigDump_DynamicCluster_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_last_updated(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_error_state(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, envoy_admin_v3_UpdateFailureState* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(24, 40), envoy_admin_v3_UpdateFailureState*) = value; +} +UPB_INLINE struct envoy_admin_v3_UpdateFailureState* envoy_admin_v3_ClustersConfigDump_DynamicCluster_mutable_error_state(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, upb_arena *arena) { + struct envoy_admin_v3_UpdateFailureState* sub = (struct envoy_admin_v3_UpdateFailureState*)envoy_admin_v3_ClustersConfigDump_DynamicCluster_error_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_UpdateFailureState*)_upb_msg_new(&envoy_admin_v3_UpdateFailureState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_error_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_client_status(envoy_admin_v3_ClustersConfigDump_DynamicCluster *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +/* envoy.admin.v3.RoutesConfigDump */ + +UPB_INLINE envoy_admin_v3_RoutesConfigDump *envoy_admin_v3_RoutesConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_RoutesConfigDump *)_upb_msg_new(&envoy_admin_v3_RoutesConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump *envoy_admin_v3_RoutesConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_RoutesConfigDump *ret = envoy_admin_v3_RoutesConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_RoutesConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump *envoy_admin_v3_RoutesConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_RoutesConfigDump *ret = envoy_admin_v3_RoutesConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_RoutesConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_RoutesConfigDump_serialize(const envoy_admin_v3_RoutesConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_RoutesConfigDump_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_RoutesConfigDump_has_static_route_configs(const envoy_admin_v3_RoutesConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig* const* envoy_admin_v3_RoutesConfigDump_static_route_configs(const envoy_admin_v3_RoutesConfigDump *msg, size_t *len) { return (const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } +UPB_INLINE bool envoy_admin_v3_RoutesConfigDump_has_dynamic_route_configs(const envoy_admin_v3_RoutesConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig* const* envoy_admin_v3_RoutesConfigDump_dynamic_route_configs(const envoy_admin_v3_RoutesConfigDump *msg, size_t *len) { return (const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE envoy_admin_v3_RoutesConfigDump_StaticRouteConfig** envoy_admin_v3_RoutesConfigDump_mutable_static_route_configs(envoy_admin_v3_RoutesConfigDump *msg, size_t *len) { + return (envoy_admin_v3_RoutesConfigDump_StaticRouteConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump_StaticRouteConfig** envoy_admin_v3_RoutesConfigDump_resize_static_route_configs(envoy_admin_v3_RoutesConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_RoutesConfigDump_StaticRouteConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_RoutesConfigDump_StaticRouteConfig* envoy_admin_v3_RoutesConfigDump_add_static_route_configs(envoy_admin_v3_RoutesConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_RoutesConfigDump_StaticRouteConfig* sub = (struct envoy_admin_v3_RoutesConfigDump_StaticRouteConfig*)_upb_msg_new(&envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig** envoy_admin_v3_RoutesConfigDump_mutable_dynamic_route_configs(envoy_admin_v3_RoutesConfigDump *msg, size_t *len) { + return (envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig** envoy_admin_v3_RoutesConfigDump_resize_dynamic_route_configs(envoy_admin_v3_RoutesConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig* envoy_admin_v3_RoutesConfigDump_add_dynamic_route_configs(envoy_admin_v3_RoutesConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig* sub = (struct envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig*)_upb_msg_new(&envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.admin.v3.RoutesConfigDump.StaticRouteConfig */ + +UPB_INLINE envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_new(upb_arena *arena) { + return (envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *)_upb_msg_new(&envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit, arena); +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *ret = envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *ret = envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_serialize(const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_has_route_config(const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_route_config(const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_has_last_updated(const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_last_updated(const envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_Timestamp*); } + +UPB_INLINE void envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_set_route_config(envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_mutable_route_config(envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_route_config(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_set_route_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_set_last_updated(envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_mutable_last_updated(envoy_admin_v3_RoutesConfigDump_StaticRouteConfig *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_set_last_updated(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig */ + +UPB_INLINE envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_new(upb_arena *arena) { + return (envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *)_upb_msg_new(&envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit, arena); +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *ret = envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *ret = envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_serialize(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_version_info(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE bool envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_has_route_config(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_route_config(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_has_last_updated(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_last_updated(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const struct google_protobuf_Timestamp*); } +UPB_INLINE bool envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_has_error_state(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const envoy_admin_v3_UpdateFailureState* envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_error_state(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), const envoy_admin_v3_UpdateFailureState*); } +UPB_INLINE int32_t envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_client_status(const envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_version_info(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_route_config(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_mutable_route_config(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_route_config(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_route_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_last_updated(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(20, 32), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_mutable_last_updated(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_last_updated(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_error_state(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, envoy_admin_v3_UpdateFailureState* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(24, 40), envoy_admin_v3_UpdateFailureState*) = value; +} +UPB_INLINE struct envoy_admin_v3_UpdateFailureState* envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_mutable_error_state(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, upb_arena *arena) { + struct envoy_admin_v3_UpdateFailureState* sub = (struct envoy_admin_v3_UpdateFailureState*)envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_error_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_UpdateFailureState*)_upb_msg_new(&envoy_admin_v3_UpdateFailureState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_error_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_client_status(envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +/* envoy.admin.v3.ScopedRoutesConfigDump */ + +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump *envoy_admin_v3_ScopedRoutesConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_ScopedRoutesConfigDump *)_upb_msg_new(&envoy_admin_v3_ScopedRoutesConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump *envoy_admin_v3_ScopedRoutesConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ScopedRoutesConfigDump *ret = envoy_admin_v3_ScopedRoutesConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ScopedRoutesConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump *envoy_admin_v3_ScopedRoutesConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ScopedRoutesConfigDump *ret = envoy_admin_v3_ScopedRoutesConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ScopedRoutesConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ScopedRoutesConfigDump_serialize(const envoy_admin_v3_ScopedRoutesConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ScopedRoutesConfigDump_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_ScopedRoutesConfigDump_has_inline_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs* const* envoy_admin_v3_ScopedRoutesConfigDump_inline_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump *msg, size_t *len) { return (const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } +UPB_INLINE bool envoy_admin_v3_ScopedRoutesConfigDump_has_dynamic_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs* const* envoy_admin_v3_ScopedRoutesConfigDump_dynamic_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump *msg, size_t *len) { return (const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs** envoy_admin_v3_ScopedRoutesConfigDump_mutable_inline_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump *msg, size_t *len) { + return (envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs** envoy_admin_v3_ScopedRoutesConfigDump_resize_inline_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs* envoy_admin_v3_ScopedRoutesConfigDump_add_inline_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs* sub = (struct envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs*)_upb_msg_new(&envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs** envoy_admin_v3_ScopedRoutesConfigDump_mutable_dynamic_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump *msg, size_t *len) { + return (envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs** envoy_admin_v3_ScopedRoutesConfigDump_resize_dynamic_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs* envoy_admin_v3_ScopedRoutesConfigDump_add_dynamic_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs* sub = (struct envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs*)_upb_msg_new(&envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.admin.v3.ScopedRoutesConfigDump.InlineScopedRouteConfigs */ + +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_new(upb_arena *arena) { + return (envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *)_upb_msg_new(&envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *ret = envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *ret = envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_serialize(const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_name(const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_has_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const struct google_protobuf_Any* const* envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, size_t *len) { return (const struct google_protobuf_Any* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_has_last_updated(const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_last_updated(const envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Timestamp*); } + +UPB_INLINE void envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_set_name(envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE struct google_protobuf_Any** envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_mutable_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, size_t *len) { + return (struct google_protobuf_Any**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE struct google_protobuf_Any** envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_resize_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, size_t len, upb_arena *arena) { + return (struct google_protobuf_Any**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_add_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_set_last_updated(envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_mutable_last_updated(envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_set_last_updated(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.ScopedRoutesConfigDump.DynamicScopedRouteConfigs */ + +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_new(upb_arena *arena) { + return (envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *)_upb_msg_new(&envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit, arena); +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *ret = envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *ret = envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_serialize(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_name(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE upb_strview envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_version_info(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), upb_strview); } +UPB_INLINE bool envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_has_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(32, 56)); } +UPB_INLINE const struct google_protobuf_Any* const* envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_scoped_route_configs(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, size_t *len) { return (const struct google_protobuf_Any* const*)_upb_array_accessor(msg, UPB_SIZE(32, 56), len); } +UPB_INLINE bool envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_has_last_updated(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_last_updated(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), const struct google_protobuf_Timestamp*); } +UPB_INLINE bool envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_has_error_state(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const envoy_admin_v3_UpdateFailureState* envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_error_state(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 48), const envoy_admin_v3_UpdateFailureState*); } +UPB_INLINE int32_t envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_client_status(const envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_set_name(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_set_version_info(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), upb_strview) = value; +} +UPB_INLINE struct google_protobuf_Any** envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_mutable_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, size_t *len) { + return (struct google_protobuf_Any**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 56), len); +} +UPB_INLINE struct google_protobuf_Any** envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_resize_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, size_t len, upb_arena *arena) { + return (struct google_protobuf_Any**)_upb_array_resize_accessor2(msg, UPB_SIZE(32, 56), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_add_scoped_route_configs(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(32, 56), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_set_last_updated(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(24, 40), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_mutable_last_updated(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_set_last_updated(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_set_error_state(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, envoy_admin_v3_UpdateFailureState* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(28, 48), envoy_admin_v3_UpdateFailureState*) = value; +} +UPB_INLINE struct envoy_admin_v3_UpdateFailureState* envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_mutable_error_state(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, upb_arena *arena) { + struct envoy_admin_v3_UpdateFailureState* sub = (struct envoy_admin_v3_UpdateFailureState*)envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_error_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_UpdateFailureState*)_upb_msg_new(&envoy_admin_v3_UpdateFailureState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_set_error_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_set_client_status(envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +/* envoy.admin.v3.SecretsConfigDump */ + +UPB_INLINE envoy_admin_v3_SecretsConfigDump *envoy_admin_v3_SecretsConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_SecretsConfigDump *)_upb_msg_new(&envoy_admin_v3_SecretsConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump *envoy_admin_v3_SecretsConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_SecretsConfigDump *ret = envoy_admin_v3_SecretsConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_SecretsConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump *envoy_admin_v3_SecretsConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_SecretsConfigDump *ret = envoy_admin_v3_SecretsConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_SecretsConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_SecretsConfigDump_serialize(const envoy_admin_v3_SecretsConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_SecretsConfigDump_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_has_static_secrets(const envoy_admin_v3_SecretsConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const envoy_admin_v3_SecretsConfigDump_StaticSecret* const* envoy_admin_v3_SecretsConfigDump_static_secrets(const envoy_admin_v3_SecretsConfigDump *msg, size_t *len) { return (const envoy_admin_v3_SecretsConfigDump_StaticSecret* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_has_dynamic_active_secrets(const envoy_admin_v3_SecretsConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const envoy_admin_v3_SecretsConfigDump_DynamicSecret* const* envoy_admin_v3_SecretsConfigDump_dynamic_active_secrets(const envoy_admin_v3_SecretsConfigDump *msg, size_t *len) { return (const envoy_admin_v3_SecretsConfigDump_DynamicSecret* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_has_dynamic_warming_secrets(const envoy_admin_v3_SecretsConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const envoy_admin_v3_SecretsConfigDump_DynamicSecret* const* envoy_admin_v3_SecretsConfigDump_dynamic_warming_secrets(const envoy_admin_v3_SecretsConfigDump *msg, size_t *len) { return (const envoy_admin_v3_SecretsConfigDump_DynamicSecret* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } + +UPB_INLINE envoy_admin_v3_SecretsConfigDump_StaticSecret** envoy_admin_v3_SecretsConfigDump_mutable_static_secrets(envoy_admin_v3_SecretsConfigDump *msg, size_t *len) { + return (envoy_admin_v3_SecretsConfigDump_StaticSecret**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_StaticSecret** envoy_admin_v3_SecretsConfigDump_resize_static_secrets(envoy_admin_v3_SecretsConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_SecretsConfigDump_StaticSecret**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_SecretsConfigDump_StaticSecret* envoy_admin_v3_SecretsConfigDump_add_static_secrets(envoy_admin_v3_SecretsConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_SecretsConfigDump_StaticSecret* sub = (struct envoy_admin_v3_SecretsConfigDump_StaticSecret*)_upb_msg_new(&envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_DynamicSecret** envoy_admin_v3_SecretsConfigDump_mutable_dynamic_active_secrets(envoy_admin_v3_SecretsConfigDump *msg, size_t *len) { + return (envoy_admin_v3_SecretsConfigDump_DynamicSecret**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_DynamicSecret** envoy_admin_v3_SecretsConfigDump_resize_dynamic_active_secrets(envoy_admin_v3_SecretsConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_SecretsConfigDump_DynamicSecret**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_SecretsConfigDump_DynamicSecret* envoy_admin_v3_SecretsConfigDump_add_dynamic_active_secrets(envoy_admin_v3_SecretsConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_SecretsConfigDump_DynamicSecret* sub = (struct envoy_admin_v3_SecretsConfigDump_DynamicSecret*)_upb_msg_new(&envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_DynamicSecret** envoy_admin_v3_SecretsConfigDump_mutable_dynamic_warming_secrets(envoy_admin_v3_SecretsConfigDump *msg, size_t *len) { + return (envoy_admin_v3_SecretsConfigDump_DynamicSecret**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_DynamicSecret** envoy_admin_v3_SecretsConfigDump_resize_dynamic_warming_secrets(envoy_admin_v3_SecretsConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_SecretsConfigDump_DynamicSecret**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_SecretsConfigDump_DynamicSecret* envoy_admin_v3_SecretsConfigDump_add_dynamic_warming_secrets(envoy_admin_v3_SecretsConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_SecretsConfigDump_DynamicSecret* sub = (struct envoy_admin_v3_SecretsConfigDump_DynamicSecret*)_upb_msg_new(&envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.admin.v3.SecretsConfigDump.DynamicSecret */ + +UPB_INLINE envoy_admin_v3_SecretsConfigDump_DynamicSecret *envoy_admin_v3_SecretsConfigDump_DynamicSecret_new(upb_arena *arena) { + return (envoy_admin_v3_SecretsConfigDump_DynamicSecret *)_upb_msg_new(&envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, arena); +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_DynamicSecret *envoy_admin_v3_SecretsConfigDump_DynamicSecret_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_SecretsConfigDump_DynamicSecret *ret = envoy_admin_v3_SecretsConfigDump_DynamicSecret_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_DynamicSecret *envoy_admin_v3_SecretsConfigDump_DynamicSecret_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_SecretsConfigDump_DynamicSecret *ret = envoy_admin_v3_SecretsConfigDump_DynamicSecret_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_SecretsConfigDump_DynamicSecret_serialize(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_SecretsConfigDump_DynamicSecret_name(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE upb_strview envoy_admin_v3_SecretsConfigDump_DynamicSecret_version_info(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), upb_strview); } +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_DynamicSecret_has_last_updated(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_SecretsConfigDump_DynamicSecret_last_updated(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), const struct google_protobuf_Timestamp*); } +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_DynamicSecret_has_secret(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_SecretsConfigDump_DynamicSecret_secret(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 48), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_DynamicSecret_has_error_state(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const envoy_admin_v3_UpdateFailureState* envoy_admin_v3_SecretsConfigDump_DynamicSecret_error_state(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 56), const envoy_admin_v3_UpdateFailureState*); } +UPB_INLINE int32_t envoy_admin_v3_SecretsConfigDump_DynamicSecret_client_status(const envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_name(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_version_info(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_last_updated(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(24, 40), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_SecretsConfigDump_DynamicSecret_mutable_last_updated(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_SecretsConfigDump_DynamicSecret_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_last_updated(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_secret(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(28, 48), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_SecretsConfigDump_DynamicSecret_mutable_secret(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_SecretsConfigDump_DynamicSecret_secret(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_secret(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_error_state(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, envoy_admin_v3_UpdateFailureState* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(32, 56), envoy_admin_v3_UpdateFailureState*) = value; +} +UPB_INLINE struct envoy_admin_v3_UpdateFailureState* envoy_admin_v3_SecretsConfigDump_DynamicSecret_mutable_error_state(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, upb_arena *arena) { + struct envoy_admin_v3_UpdateFailureState* sub = (struct envoy_admin_v3_UpdateFailureState*)envoy_admin_v3_SecretsConfigDump_DynamicSecret_error_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_UpdateFailureState*)_upb_msg_new(&envoy_admin_v3_UpdateFailureState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_error_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_DynamicSecret_set_client_status(envoy_admin_v3_SecretsConfigDump_DynamicSecret *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +/* envoy.admin.v3.SecretsConfigDump.StaticSecret */ + +UPB_INLINE envoy_admin_v3_SecretsConfigDump_StaticSecret *envoy_admin_v3_SecretsConfigDump_StaticSecret_new(upb_arena *arena) { + return (envoy_admin_v3_SecretsConfigDump_StaticSecret *)_upb_msg_new(&envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit, arena); +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_StaticSecret *envoy_admin_v3_SecretsConfigDump_StaticSecret_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_SecretsConfigDump_StaticSecret *ret = envoy_admin_v3_SecretsConfigDump_StaticSecret_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_SecretsConfigDump_StaticSecret *envoy_admin_v3_SecretsConfigDump_StaticSecret_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_SecretsConfigDump_StaticSecret *ret = envoy_admin_v3_SecretsConfigDump_StaticSecret_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_SecretsConfigDump_StaticSecret_serialize(const envoy_admin_v3_SecretsConfigDump_StaticSecret *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_SecretsConfigDump_StaticSecret_name(const envoy_admin_v3_SecretsConfigDump_StaticSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_StaticSecret_has_last_updated(const envoy_admin_v3_SecretsConfigDump_StaticSecret *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_SecretsConfigDump_StaticSecret_last_updated(const envoy_admin_v3_SecretsConfigDump_StaticSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Timestamp*); } +UPB_INLINE bool envoy_admin_v3_SecretsConfigDump_StaticSecret_has_secret(const envoy_admin_v3_SecretsConfigDump_StaticSecret *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_SecretsConfigDump_StaticSecret_secret(const envoy_admin_v3_SecretsConfigDump_StaticSecret *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), const struct google_protobuf_Any*); } + +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_StaticSecret_set_name(envoy_admin_v3_SecretsConfigDump_StaticSecret *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_StaticSecret_set_last_updated(envoy_admin_v3_SecretsConfigDump_StaticSecret *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_SecretsConfigDump_StaticSecret_mutable_last_updated(envoy_admin_v3_SecretsConfigDump_StaticSecret *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_SecretsConfigDump_StaticSecret_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_SecretsConfigDump_StaticSecret_set_last_updated(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_SecretsConfigDump_StaticSecret_set_secret(envoy_admin_v3_SecretsConfigDump_StaticSecret *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(16, 32), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_SecretsConfigDump_StaticSecret_mutable_secret(envoy_admin_v3_SecretsConfigDump_StaticSecret *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_SecretsConfigDump_StaticSecret_secret(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_SecretsConfigDump_StaticSecret_set_secret(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.EndpointsConfigDump */ + +UPB_INLINE envoy_admin_v3_EndpointsConfigDump *envoy_admin_v3_EndpointsConfigDump_new(upb_arena *arena) { + return (envoy_admin_v3_EndpointsConfigDump *)_upb_msg_new(&envoy_admin_v3_EndpointsConfigDump_msginit, arena); +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump *envoy_admin_v3_EndpointsConfigDump_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_EndpointsConfigDump *ret = envoy_admin_v3_EndpointsConfigDump_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_EndpointsConfigDump_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump *envoy_admin_v3_EndpointsConfigDump_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_EndpointsConfigDump *ret = envoy_admin_v3_EndpointsConfigDump_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_EndpointsConfigDump_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_EndpointsConfigDump_serialize(const envoy_admin_v3_EndpointsConfigDump *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_EndpointsConfigDump_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_EndpointsConfigDump_has_static_endpoint_configs(const envoy_admin_v3_EndpointsConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig* const* envoy_admin_v3_EndpointsConfigDump_static_endpoint_configs(const envoy_admin_v3_EndpointsConfigDump *msg, size_t *len) { return (const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } +UPB_INLINE bool envoy_admin_v3_EndpointsConfigDump_has_dynamic_endpoint_configs(const envoy_admin_v3_EndpointsConfigDump *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig* const* envoy_admin_v3_EndpointsConfigDump_dynamic_endpoint_configs(const envoy_admin_v3_EndpointsConfigDump *msg, size_t *len) { return (const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } + +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig** envoy_admin_v3_EndpointsConfigDump_mutable_static_endpoint_configs(envoy_admin_v3_EndpointsConfigDump *msg, size_t *len) { + return (envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig** envoy_admin_v3_EndpointsConfigDump_resize_static_endpoint_configs(envoy_admin_v3_EndpointsConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig* envoy_admin_v3_EndpointsConfigDump_add_static_endpoint_configs(envoy_admin_v3_EndpointsConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig* sub = (struct envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig*)_upb_msg_new(&envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig** envoy_admin_v3_EndpointsConfigDump_mutable_dynamic_endpoint_configs(envoy_admin_v3_EndpointsConfigDump *msg, size_t *len) { + return (envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig** envoy_admin_v3_EndpointsConfigDump_resize_dynamic_endpoint_configs(envoy_admin_v3_EndpointsConfigDump *msg, size_t len, upb_arena *arena) { + return (envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig* envoy_admin_v3_EndpointsConfigDump_add_dynamic_endpoint_configs(envoy_admin_v3_EndpointsConfigDump *msg, upb_arena *arena) { + struct envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig* sub = (struct envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig*)_upb_msg_new(&envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.admin.v3.EndpointsConfigDump.StaticEndpointConfig */ + +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_new(upb_arena *arena) { + return (envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *)_upb_msg_new(&envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit, arena); +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *ret = envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *ret = envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_serialize(const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit, arena, len); +} + +UPB_INLINE bool envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_has_endpoint_config(const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_endpoint_config(const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_has_last_updated(const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_last_updated(const envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_Timestamp*); } + +UPB_INLINE void envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_set_endpoint_config(envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_mutable_endpoint_config(envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_endpoint_config(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_set_endpoint_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_set_last_updated(envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_mutable_last_updated(envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_set_last_updated(msg, sub); + } + return sub; +} + +/* envoy.admin.v3.EndpointsConfigDump.DynamicEndpointConfig */ + +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_new(upb_arena *arena) { + return (envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *)_upb_msg_new(&envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit, arena); +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *ret = envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *ret = envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_serialize(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_version_info(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview); } +UPB_INLINE bool envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_has_endpoint_config(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_endpoint_config(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const struct google_protobuf_Any*); } +UPB_INLINE bool envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_has_last_updated(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Timestamp* envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_last_updated(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const struct google_protobuf_Timestamp*); } +UPB_INLINE bool envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_has_error_state(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const envoy_admin_v3_UpdateFailureState* envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_error_state(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 40), const envoy_admin_v3_UpdateFailureState*); } +UPB_INLINE int32_t envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_client_status(const envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_version_info(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_strview) = value; +} +UPB_INLINE void envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_endpoint_config(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(16, 24), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_mutable_endpoint_config(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_endpoint_config(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_endpoint_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_last_updated(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, struct google_protobuf_Timestamp* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(20, 32), struct google_protobuf_Timestamp*) = value; +} +UPB_INLINE struct google_protobuf_Timestamp* envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_mutable_last_updated(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, upb_arena *arena) { + struct google_protobuf_Timestamp* sub = (struct google_protobuf_Timestamp*)envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_last_updated(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Timestamp*)_upb_msg_new(&google_protobuf_Timestamp_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_last_updated(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_error_state(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, envoy_admin_v3_UpdateFailureState* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(24, 40), envoy_admin_v3_UpdateFailureState*) = value; +} +UPB_INLINE struct envoy_admin_v3_UpdateFailureState* envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_mutable_error_state(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, upb_arena *arena) { + struct envoy_admin_v3_UpdateFailureState* sub = (struct envoy_admin_v3_UpdateFailureState*)envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_error_state(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_UpdateFailureState*)_upb_msg_new(&envoy_admin_v3_UpdateFailureState_msginit, arena); + if (!sub) return NULL; + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_error_state(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_client_status(envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_ADMIN_V3_CONFIG_DUMP_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c b/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c new file mode 100644 index 00000000000..b7f9387b242 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c @@ -0,0 +1,350 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/bootstrap/v3/bootstrap.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/config/bootstrap/v3/bootstrap.upb.h" +#include "envoy/config/cluster/v3/cluster.upb.h" +#include "envoy/config/core/v3/address.upb.h" +#include "envoy/config/core/v3/base.upb.h" +#include "envoy/config/core/v3/config_source.upb.h" +#include "envoy/config/core/v3/event_service_config.upb.h" +#include "envoy/config/core/v3/extension.upb.h" +#include "envoy/config/core/v3/socket_option.upb.h" +#include "envoy/config/listener/v3/listener.upb.h" +#include "envoy/config/metrics/v3/stats.upb.h" +#include "envoy/config/overload/v3/overload.upb.h" +#include "envoy/config/trace/v3/http_tracer.upb.h" +#include "envoy/extensions/transport_sockets/tls/v3/secret.upb.h" +#include "envoy/type/v3/percent.upb.h" +#include "google/protobuf/duration.upb.h" +#include "google/protobuf/struct.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "udpa/annotations/migrate.upb.h" +#include "udpa/annotations/security.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_config_bootstrap_v3_Bootstrap_submsgs[19] = { + &envoy_config_bootstrap_v3_Admin_msginit, + &envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_msginit, + &envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit, + &envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit, + &envoy_config_bootstrap_v3_ClusterManager_msginit, + &envoy_config_bootstrap_v3_FatalAction_msginit, + &envoy_config_bootstrap_v3_LayeredRuntime_msginit, + &envoy_config_bootstrap_v3_Watchdog_msginit, + &envoy_config_bootstrap_v3_Watchdogs_msginit, + &envoy_config_core_v3_ApiConfigSource_msginit, + &envoy_config_core_v3_ConfigSource_msginit, + &envoy_config_core_v3_Node_msginit, + &envoy_config_core_v3_TypedExtensionConfig_msginit, + &envoy_config_metrics_v3_StatsConfig_msginit, + &envoy_config_metrics_v3_StatsSink_msginit, + &envoy_config_overload_v3_OverloadManager_msginit, + &envoy_config_trace_v3_Tracing_msginit, + &google_protobuf_Duration_msginit, + &google_protobuf_UInt64Value_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Bootstrap__fields[27] = { + {1, UPB_SIZE(28, 56), 1, 11, 11, 1}, + {2, UPB_SIZE(32, 64), 2, 3, 11, 1}, + {3, UPB_SIZE(36, 72), 3, 2, 11, 1}, + {4, UPB_SIZE(40, 80), 4, 4, 11, 1}, + {5, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {6, UPB_SIZE(88, 176), 0, 14, 11, 3}, + {7, UPB_SIZE(44, 88), 5, 17, 11, 1}, + {8, UPB_SIZE(48, 96), 6, 7, 11, 1}, + {9, UPB_SIZE(52, 104), 7, 16, 11, 1}, + {12, UPB_SIZE(56, 112), 8, 0, 11, 1}, + {13, UPB_SIZE(60, 120), 9, 13, 11, 1}, + {14, UPB_SIZE(64, 128), 10, 9, 11, 1}, + {15, UPB_SIZE(68, 136), 11, 15, 11, 1}, + {16, UPB_SIZE(2, 2), 0, 0, 8, 1}, + {17, UPB_SIZE(72, 144), 12, 6, 11, 1}, + {18, UPB_SIZE(12, 24), 0, 0, 9, 1}, + {19, UPB_SIZE(76, 152), 13, 18, 11, 1}, + {20, UPB_SIZE(3, 3), 0, 0, 8, 1}, + {21, UPB_SIZE(92, 184), 0, 12, 11, 3}, + {22, UPB_SIZE(96, 192), 0, 10, 11, 3}, + {23, UPB_SIZE(80, 160), 14, 10, 11, 1}, + {24, UPB_SIZE(20, 40), 0, 0, 9, 1}, + {25, UPB_SIZE(100, 200), 0, 1, 11, _UPB_LABEL_MAP}, + {26, UPB_SIZE(104, 208), 0, 0, 9, 3}, + {27, UPB_SIZE(84, 168), 15, 8, 11, 1}, + {28, UPB_SIZE(108, 216), 0, 5, 11, 3}, + {29, UPB_SIZE(112, 224), UPB_SIZE(-117, -229), 0, 8, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_msginit = { + &envoy_config_bootstrap_v3_Bootstrap_submsgs[0], + &envoy_config_bootstrap_v3_Bootstrap__fields[0], + UPB_SIZE(120, 240), 27, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Bootstrap_StaticResources_submsgs[3] = { + &envoy_config_cluster_v3_Cluster_msginit, + &envoy_config_listener_v3_Listener_msginit, + &envoy_extensions_transport_sockets_tls_v3_Secret_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Bootstrap_StaticResources__fields[3] = { + {1, UPB_SIZE(0, 0), 0, 1, 11, 3}, + {2, UPB_SIZE(4, 8), 0, 0, 11, 3}, + {3, UPB_SIZE(8, 16), 0, 2, 11, 3}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit = { + &envoy_config_bootstrap_v3_Bootstrap_StaticResources_submsgs[0], + &envoy_config_bootstrap_v3_Bootstrap_StaticResources__fields[0], + UPB_SIZE(16, 24), 3, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Bootstrap_DynamicResources_submsgs[2] = { + &envoy_config_core_v3_ApiConfigSource_msginit, + &envoy_config_core_v3_ConfigSource_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Bootstrap_DynamicResources__fields[5] = { + {1, UPB_SIZE(20, 40), 1, 1, 11, 1}, + {2, UPB_SIZE(24, 48), 2, 1, 11, 1}, + {3, UPB_SIZE(28, 56), 3, 0, 11, 1}, + {5, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {6, UPB_SIZE(12, 24), 0, 0, 9, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit = { + &envoy_config_bootstrap_v3_Bootstrap_DynamicResources_submsgs[0], + &envoy_config_bootstrap_v3_Bootstrap_DynamicResources__fields[0], + UPB_SIZE(32, 64), 5, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_submsgs[1] = { + &envoy_config_core_v3_TypedExtensionConfig_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {2, UPB_SIZE(8, 16), 0, 0, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_msginit = { + &envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_submsgs[0], + &envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Admin_submsgs[2] = { + &envoy_config_core_v3_Address_msginit, + &envoy_config_core_v3_SocketOption_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Admin__fields[4] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(12, 24), 0, 0, 9, 1}, + {3, UPB_SIZE(20, 40), 1, 0, 11, 1}, + {4, UPB_SIZE(24, 48), 0, 1, 11, 3}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Admin_msginit = { + &envoy_config_bootstrap_v3_Admin_submsgs[0], + &envoy_config_bootstrap_v3_Admin__fields[0], + UPB_SIZE(32, 64), 4, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_ClusterManager_submsgs[3] = { + &envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit, + &envoy_config_core_v3_ApiConfigSource_msginit, + &envoy_config_core_v3_BindConfig_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_ClusterManager__fields[4] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(12, 24), 1, 0, 11, 1}, + {3, UPB_SIZE(16, 32), 2, 2, 11, 1}, + {4, UPB_SIZE(20, 40), 3, 1, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_ClusterManager_msginit = { + &envoy_config_bootstrap_v3_ClusterManager_submsgs[0], + &envoy_config_bootstrap_v3_ClusterManager__fields[0], + UPB_SIZE(24, 48), 4, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_submsgs[1] = { + &envoy_config_core_v3_EventServiceConfig_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_ClusterManager_OutlierDetection__fields[2] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(12, 24), 1, 0, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit = { + &envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_submsgs[0], + &envoy_config_bootstrap_v3_ClusterManager_OutlierDetection__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Watchdogs_submsgs[1] = { + &envoy_config_bootstrap_v3_Watchdog_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Watchdogs__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 2, 0, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Watchdogs_msginit = { + &envoy_config_bootstrap_v3_Watchdogs_submsgs[0], + &envoy_config_bootstrap_v3_Watchdogs__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Watchdog_submsgs[3] = { + &envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit, + &envoy_type_v3_Percent_msginit, + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Watchdog__fields[7] = { + {1, UPB_SIZE(4, 8), 1, 2, 11, 1}, + {2, UPB_SIZE(8, 16), 2, 2, 11, 1}, + {3, UPB_SIZE(12, 24), 3, 2, 11, 1}, + {4, UPB_SIZE(16, 32), 4, 2, 11, 1}, + {5, UPB_SIZE(20, 40), 5, 1, 11, 1}, + {6, UPB_SIZE(24, 48), 6, 2, 11, 1}, + {7, UPB_SIZE(28, 56), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Watchdog_msginit = { + &envoy_config_bootstrap_v3_Watchdog_submsgs[0], + &envoy_config_bootstrap_v3_Watchdog__fields[0], + UPB_SIZE(32, 64), 7, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Watchdog_WatchdogAction_submsgs[1] = { + &envoy_config_core_v3_TypedExtensionConfig_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Watchdog_WatchdogAction__fields[2] = { + {1, UPB_SIZE(8, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit = { + &envoy_config_bootstrap_v3_Watchdog_WatchdogAction_submsgs[0], + &envoy_config_bootstrap_v3_Watchdog_WatchdogAction__fields[0], + UPB_SIZE(16, 16), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_FatalAction_submsgs[1] = { + &envoy_config_core_v3_TypedExtensionConfig_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_FatalAction__fields[1] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_FatalAction_msginit = { + &envoy_config_bootstrap_v3_FatalAction_submsgs[0], + &envoy_config_bootstrap_v3_FatalAction__fields[0], + UPB_SIZE(8, 16), 1, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_Runtime_submsgs[1] = { + &google_protobuf_Struct_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_Runtime__fields[4] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(12, 24), 0, 0, 9, 1}, + {3, UPB_SIZE(20, 40), 0, 0, 9, 1}, + {4, UPB_SIZE(28, 56), 1, 0, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_Runtime_msginit = { + &envoy_config_bootstrap_v3_Runtime_submsgs[0], + &envoy_config_bootstrap_v3_Runtime__fields[0], + UPB_SIZE(32, 64), 4, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_RuntimeLayer_submsgs[4] = { + &envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit, + &envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit, + &envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit, + &google_protobuf_Struct_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_RuntimeLayer__fields[5] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 3, 11, 1}, + {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1}, + {4, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1}, + {5, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 2, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_msginit = { + &envoy_config_bootstrap_v3_RuntimeLayer_submsgs[0], + &envoy_config_bootstrap_v3_RuntimeLayer__fields[0], + UPB_SIZE(16, 32), 5, false, 255, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer__fields[3] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(0, 0), 0, 0, 8, 1}, + {3, UPB_SIZE(12, 24), 0, 0, 9, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit = { + NULL, + &envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit = { + NULL, + NULL, + UPB_SIZE(0, 0), 0, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_submsgs[1] = { + &envoy_config_core_v3_ConfigSource_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer__fields[2] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(12, 24), 1, 0, 11, 1}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit = { + &envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_submsgs[0], + &envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_bootstrap_v3_LayeredRuntime_submsgs[1] = { + &envoy_config_bootstrap_v3_RuntimeLayer_msginit, +}; + +static const upb_msglayout_field envoy_config_bootstrap_v3_LayeredRuntime__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_config_bootstrap_v3_LayeredRuntime_msginit = { + &envoy_config_bootstrap_v3_LayeredRuntime_submsgs[0], + &envoy_config_bootstrap_v3_LayeredRuntime__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h b/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h new file mode 100644 index 00000000000..42e4c8583d9 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h @@ -0,0 +1,1348 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/bootstrap/v3/bootstrap.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_CONFIG_BOOTSTRAP_V3_BOOTSTRAP_PROTO_UPB_H_ +#define ENVOY_CONFIG_BOOTSTRAP_V3_BOOTSTRAP_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_config_bootstrap_v3_Bootstrap; +struct envoy_config_bootstrap_v3_Bootstrap_StaticResources; +struct envoy_config_bootstrap_v3_Bootstrap_DynamicResources; +struct envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry; +struct envoy_config_bootstrap_v3_Admin; +struct envoy_config_bootstrap_v3_ClusterManager; +struct envoy_config_bootstrap_v3_ClusterManager_OutlierDetection; +struct envoy_config_bootstrap_v3_Watchdogs; +struct envoy_config_bootstrap_v3_Watchdog; +struct envoy_config_bootstrap_v3_Watchdog_WatchdogAction; +struct envoy_config_bootstrap_v3_FatalAction; +struct envoy_config_bootstrap_v3_Runtime; +struct envoy_config_bootstrap_v3_RuntimeLayer; +struct envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer; +struct envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer; +struct envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer; +struct envoy_config_bootstrap_v3_LayeredRuntime; +typedef struct envoy_config_bootstrap_v3_Bootstrap envoy_config_bootstrap_v3_Bootstrap; +typedef struct envoy_config_bootstrap_v3_Bootstrap_StaticResources envoy_config_bootstrap_v3_Bootstrap_StaticResources; +typedef struct envoy_config_bootstrap_v3_Bootstrap_DynamicResources envoy_config_bootstrap_v3_Bootstrap_DynamicResources; +typedef struct envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry; +typedef struct envoy_config_bootstrap_v3_Admin envoy_config_bootstrap_v3_Admin; +typedef struct envoy_config_bootstrap_v3_ClusterManager envoy_config_bootstrap_v3_ClusterManager; +typedef struct envoy_config_bootstrap_v3_ClusterManager_OutlierDetection envoy_config_bootstrap_v3_ClusterManager_OutlierDetection; +typedef struct envoy_config_bootstrap_v3_Watchdogs envoy_config_bootstrap_v3_Watchdogs; +typedef struct envoy_config_bootstrap_v3_Watchdog envoy_config_bootstrap_v3_Watchdog; +typedef struct envoy_config_bootstrap_v3_Watchdog_WatchdogAction envoy_config_bootstrap_v3_Watchdog_WatchdogAction; +typedef struct envoy_config_bootstrap_v3_FatalAction envoy_config_bootstrap_v3_FatalAction; +typedef struct envoy_config_bootstrap_v3_Runtime envoy_config_bootstrap_v3_Runtime; +typedef struct envoy_config_bootstrap_v3_RuntimeLayer envoy_config_bootstrap_v3_RuntimeLayer; +typedef struct envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer; +typedef struct envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer; +typedef struct envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer; +typedef struct envoy_config_bootstrap_v3_LayeredRuntime envoy_config_bootstrap_v3_LayeredRuntime; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Admin_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_ClusterManager_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Watchdogs_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Watchdog_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_FatalAction_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Runtime_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_LayeredRuntime_msginit; +struct envoy_config_cluster_v3_Cluster; +struct envoy_config_core_v3_Address; +struct envoy_config_core_v3_ApiConfigSource; +struct envoy_config_core_v3_BindConfig; +struct envoy_config_core_v3_ConfigSource; +struct envoy_config_core_v3_EventServiceConfig; +struct envoy_config_core_v3_Node; +struct envoy_config_core_v3_SocketOption; +struct envoy_config_core_v3_TypedExtensionConfig; +struct envoy_config_listener_v3_Listener; +struct envoy_config_metrics_v3_StatsConfig; +struct envoy_config_metrics_v3_StatsSink; +struct envoy_config_overload_v3_OverloadManager; +struct envoy_config_trace_v3_Tracing; +struct envoy_extensions_transport_sockets_tls_v3_Secret; +struct envoy_type_v3_Percent; +struct google_protobuf_Duration; +struct google_protobuf_Struct; +struct google_protobuf_UInt64Value; +extern const upb_msglayout envoy_config_cluster_v3_Cluster_msginit; +extern const upb_msglayout envoy_config_core_v3_Address_msginit; +extern const upb_msglayout envoy_config_core_v3_ApiConfigSource_msginit; +extern const upb_msglayout envoy_config_core_v3_BindConfig_msginit; +extern const upb_msglayout envoy_config_core_v3_ConfigSource_msginit; +extern const upb_msglayout envoy_config_core_v3_EventServiceConfig_msginit; +extern const upb_msglayout envoy_config_core_v3_Node_msginit; +extern const upb_msglayout envoy_config_core_v3_SocketOption_msginit; +extern const upb_msglayout envoy_config_core_v3_TypedExtensionConfig_msginit; +extern const upb_msglayout envoy_config_listener_v3_Listener_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsConfig_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsSink_msginit; +extern const upb_msglayout envoy_config_overload_v3_OverloadManager_msginit; +extern const upb_msglayout envoy_config_trace_v3_Tracing_msginit; +extern const upb_msglayout envoy_extensions_transport_sockets_tls_v3_Secret_msginit; +extern const upb_msglayout envoy_type_v3_Percent_msginit; +extern const upb_msglayout google_protobuf_Duration_msginit; +extern const upb_msglayout google_protobuf_Struct_msginit; +extern const upb_msglayout google_protobuf_UInt64Value_msginit; + +typedef enum { + envoy_config_bootstrap_v3_Watchdog_WatchdogAction_UNKNOWN = 0, + envoy_config_bootstrap_v3_Watchdog_WatchdogAction_KILL = 1, + envoy_config_bootstrap_v3_Watchdog_WatchdogAction_MULTIKILL = 2, + envoy_config_bootstrap_v3_Watchdog_WatchdogAction_MEGAMISS = 3, + envoy_config_bootstrap_v3_Watchdog_WatchdogAction_MISS = 4 +} envoy_config_bootstrap_v3_Watchdog_WatchdogAction_WatchdogEvent; + + +/* envoy.config.bootstrap.v3.Bootstrap */ + +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap *envoy_config_bootstrap_v3_Bootstrap_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Bootstrap *)_upb_msg_new(&envoy_config_bootstrap_v3_Bootstrap_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap *envoy_config_bootstrap_v3_Bootstrap_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Bootstrap *ret = envoy_config_bootstrap_v3_Bootstrap_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Bootstrap_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap *envoy_config_bootstrap_v3_Bootstrap_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Bootstrap *ret = envoy_config_bootstrap_v3_Bootstrap_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Bootstrap_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Bootstrap_serialize(const envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Bootstrap_msginit, arena, len); +} + +typedef enum { + envoy_config_bootstrap_v3_Bootstrap_stats_flush_stats_flush_on_admin = 29, + envoy_config_bootstrap_v3_Bootstrap_stats_flush_NOT_SET = 0 +} envoy_config_bootstrap_v3_Bootstrap_stats_flush_oneofcases; +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_stats_flush_oneofcases envoy_config_bootstrap_v3_Bootstrap_stats_flush_case(const envoy_config_bootstrap_v3_Bootstrap* msg) { return (envoy_config_bootstrap_v3_Bootstrap_stats_flush_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(116, 228), int32_t); } + +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_node(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_Node* envoy_config_bootstrap_v3_Bootstrap_node(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const struct envoy_config_core_v3_Node*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_static_resources(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const envoy_config_bootstrap_v3_Bootstrap_StaticResources* envoy_config_bootstrap_v3_Bootstrap_static_resources(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(32, 64), const envoy_config_bootstrap_v3_Bootstrap_StaticResources*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_dynamic_resources(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const envoy_config_bootstrap_v3_Bootstrap_DynamicResources* envoy_config_bootstrap_v3_Bootstrap_dynamic_resources(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 72), const envoy_config_bootstrap_v3_Bootstrap_DynamicResources*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_cluster_manager(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const envoy_config_bootstrap_v3_ClusterManager* envoy_config_bootstrap_v3_Bootstrap_cluster_manager(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(40, 80), const envoy_config_bootstrap_v3_ClusterManager*); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Bootstrap_flags_path(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_stats_sinks(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(88, 176)); } +UPB_INLINE const struct envoy_config_metrics_v3_StatsSink* const* envoy_config_bootstrap_v3_Bootstrap_stats_sinks(const envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { return (const struct envoy_config_metrics_v3_StatsSink* const*)_upb_array_accessor(msg, UPB_SIZE(88, 176), len); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_stats_flush_interval(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_bootstrap_v3_Bootstrap_stats_flush_interval(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 88), const struct google_protobuf_Duration*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_watchdog(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE const envoy_config_bootstrap_v3_Watchdog* envoy_config_bootstrap_v3_Bootstrap_watchdog(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(48, 96), const envoy_config_bootstrap_v3_Watchdog*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_tracing(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 7); } +UPB_INLINE const struct envoy_config_trace_v3_Tracing* envoy_config_bootstrap_v3_Bootstrap_tracing(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 104), const struct envoy_config_trace_v3_Tracing*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_admin(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 8); } +UPB_INLINE const envoy_config_bootstrap_v3_Admin* envoy_config_bootstrap_v3_Bootstrap_admin(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(56, 112), const envoy_config_bootstrap_v3_Admin*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_stats_config(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 9); } +UPB_INLINE const struct envoy_config_metrics_v3_StatsConfig* envoy_config_bootstrap_v3_Bootstrap_stats_config(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 120), const struct envoy_config_metrics_v3_StatsConfig*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_hds_config(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 10); } +UPB_INLINE const struct envoy_config_core_v3_ApiConfigSource* envoy_config_bootstrap_v3_Bootstrap_hds_config(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(64, 128), const struct envoy_config_core_v3_ApiConfigSource*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_overload_manager(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 11); } +UPB_INLINE const struct envoy_config_overload_v3_OverloadManager* envoy_config_bootstrap_v3_Bootstrap_overload_manager(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 136), const struct envoy_config_overload_v3_OverloadManager*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_enable_dispatcher_stats(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_layered_runtime(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 12); } +UPB_INLINE const envoy_config_bootstrap_v3_LayeredRuntime* envoy_config_bootstrap_v3_Bootstrap_layered_runtime(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(72, 144), const envoy_config_bootstrap_v3_LayeredRuntime*); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Bootstrap_header_prefix(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_stats_server_version_override(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 13); } +UPB_INLINE const struct google_protobuf_UInt64Value* envoy_config_bootstrap_v3_Bootstrap_stats_server_version_override(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 152), const struct google_protobuf_UInt64Value*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_use_tcp_for_dns_lookups(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_bootstrap_extensions(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(92, 184)); } +UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* const* envoy_config_bootstrap_v3_Bootstrap_bootstrap_extensions(const envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { return (const struct envoy_config_core_v3_TypedExtensionConfig* const*)_upb_array_accessor(msg, UPB_SIZE(92, 184), len); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_config_sources(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(96, 192)); } +UPB_INLINE const struct envoy_config_core_v3_ConfigSource* const* envoy_config_bootstrap_v3_Bootstrap_config_sources(const envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { return (const struct envoy_config_core_v3_ConfigSource* const*)_upb_array_accessor(msg, UPB_SIZE(96, 192), len); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_default_config_source(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 14); } +UPB_INLINE const struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_Bootstrap_default_config_source(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(80, 160), const struct envoy_config_core_v3_ConfigSource*); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Bootstrap_default_socket_interface(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_certificate_provider_instances(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(100, 200)); } +UPB_INLINE size_t envoy_config_bootstrap_v3_Bootstrap_certificate_provider_instances_size(const envoy_config_bootstrap_v3_Bootstrap *msg) {return _upb_msg_map_size(msg, UPB_SIZE(100, 200)); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_certificate_provider_instances_get(const envoy_config_bootstrap_v3_Bootstrap *msg, upb_strview key, struct envoy_config_core_v3_TypedExtensionConfig* *val) { return _upb_msg_map_get(msg, UPB_SIZE(100, 200), &key, 0, val, sizeof(*val)); } +UPB_INLINE const envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry* envoy_config_bootstrap_v3_Bootstrap_certificate_provider_instances_next(const envoy_config_bootstrap_v3_Bootstrap *msg, size_t* iter) { return (const envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry*)_upb_msg_map_next(msg, UPB_SIZE(100, 200), iter); } +UPB_INLINE upb_strview const* envoy_config_bootstrap_v3_Bootstrap_node_context_params(const envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(104, 208), len); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_watchdogs(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_hasbit(msg, 15); } +UPB_INLINE const envoy_config_bootstrap_v3_Watchdogs* envoy_config_bootstrap_v3_Bootstrap_watchdogs(const envoy_config_bootstrap_v3_Bootstrap *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(84, 168), const envoy_config_bootstrap_v3_Watchdogs*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_fatal_actions(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(108, 216)); } +UPB_INLINE const envoy_config_bootstrap_v3_FatalAction* const* envoy_config_bootstrap_v3_Bootstrap_fatal_actions(const envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { return (const envoy_config_bootstrap_v3_FatalAction* const*)_upb_array_accessor(msg, UPB_SIZE(108, 216), len); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_has_stats_flush_on_admin(const envoy_config_bootstrap_v3_Bootstrap *msg) { return _upb_getoneofcase(msg, UPB_SIZE(116, 228)) == 29; } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_stats_flush_on_admin(const envoy_config_bootstrap_v3_Bootstrap *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(112, 224), UPB_SIZE(116, 228), 29, false); } + +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_node(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_core_v3_Node* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), struct envoy_config_core_v3_Node*) = value; +} +UPB_INLINE struct envoy_config_core_v3_Node* envoy_config_bootstrap_v3_Bootstrap_mutable_node(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_core_v3_Node* sub = (struct envoy_config_core_v3_Node*)envoy_config_bootstrap_v3_Bootstrap_node(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_Node*)_upb_msg_new(&envoy_config_core_v3_Node_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_node(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_static_resources(envoy_config_bootstrap_v3_Bootstrap *msg, envoy_config_bootstrap_v3_Bootstrap_StaticResources* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(32, 64), envoy_config_bootstrap_v3_Bootstrap_StaticResources*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Bootstrap_StaticResources* envoy_config_bootstrap_v3_Bootstrap_mutable_static_resources(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Bootstrap_StaticResources* sub = (struct envoy_config_bootstrap_v3_Bootstrap_StaticResources*)envoy_config_bootstrap_v3_Bootstrap_static_resources(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Bootstrap_StaticResources*)_upb_msg_new(&envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_static_resources(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_dynamic_resources(envoy_config_bootstrap_v3_Bootstrap *msg, envoy_config_bootstrap_v3_Bootstrap_DynamicResources* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(36, 72), envoy_config_bootstrap_v3_Bootstrap_DynamicResources*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Bootstrap_DynamicResources* envoy_config_bootstrap_v3_Bootstrap_mutable_dynamic_resources(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Bootstrap_DynamicResources* sub = (struct envoy_config_bootstrap_v3_Bootstrap_DynamicResources*)envoy_config_bootstrap_v3_Bootstrap_dynamic_resources(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Bootstrap_DynamicResources*)_upb_msg_new(&envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_dynamic_resources(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_cluster_manager(envoy_config_bootstrap_v3_Bootstrap *msg, envoy_config_bootstrap_v3_ClusterManager* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(40, 80), envoy_config_bootstrap_v3_ClusterManager*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_ClusterManager* envoy_config_bootstrap_v3_Bootstrap_mutable_cluster_manager(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_ClusterManager* sub = (struct envoy_config_bootstrap_v3_ClusterManager*)envoy_config_bootstrap_v3_Bootstrap_cluster_manager(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_ClusterManager*)_upb_msg_new(&envoy_config_bootstrap_v3_ClusterManager_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_cluster_manager(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_flags_path(envoy_config_bootstrap_v3_Bootstrap *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE struct envoy_config_metrics_v3_StatsSink** envoy_config_bootstrap_v3_Bootstrap_mutable_stats_sinks(envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { + return (struct envoy_config_metrics_v3_StatsSink**)_upb_array_mutable_accessor(msg, UPB_SIZE(88, 176), len); +} +UPB_INLINE struct envoy_config_metrics_v3_StatsSink** envoy_config_bootstrap_v3_Bootstrap_resize_stats_sinks(envoy_config_bootstrap_v3_Bootstrap *msg, size_t len, upb_arena *arena) { + return (struct envoy_config_metrics_v3_StatsSink**)_upb_array_resize_accessor2(msg, UPB_SIZE(88, 176), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_metrics_v3_StatsSink* envoy_config_bootstrap_v3_Bootstrap_add_stats_sinks(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_metrics_v3_StatsSink* sub = (struct envoy_config_metrics_v3_StatsSink*)_upb_msg_new(&envoy_config_metrics_v3_StatsSink_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(88, 176), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_stats_flush_interval(envoy_config_bootstrap_v3_Bootstrap *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(44, 88), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_bootstrap_v3_Bootstrap_mutable_stats_flush_interval(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_bootstrap_v3_Bootstrap_stats_flush_interval(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_stats_flush_interval(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_watchdog(envoy_config_bootstrap_v3_Bootstrap *msg, envoy_config_bootstrap_v3_Watchdog* value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(48, 96), envoy_config_bootstrap_v3_Watchdog*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Watchdog* envoy_config_bootstrap_v3_Bootstrap_mutable_watchdog(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Watchdog* sub = (struct envoy_config_bootstrap_v3_Watchdog*)envoy_config_bootstrap_v3_Bootstrap_watchdog(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Watchdog*)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdog_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_watchdog(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_tracing(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_trace_v3_Tracing* value) { + _upb_sethas(msg, 7); + *UPB_PTR_AT(msg, UPB_SIZE(52, 104), struct envoy_config_trace_v3_Tracing*) = value; +} +UPB_INLINE struct envoy_config_trace_v3_Tracing* envoy_config_bootstrap_v3_Bootstrap_mutable_tracing(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_trace_v3_Tracing* sub = (struct envoy_config_trace_v3_Tracing*)envoy_config_bootstrap_v3_Bootstrap_tracing(msg); + if (sub == NULL) { + sub = (struct envoy_config_trace_v3_Tracing*)_upb_msg_new(&envoy_config_trace_v3_Tracing_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_tracing(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_admin(envoy_config_bootstrap_v3_Bootstrap *msg, envoy_config_bootstrap_v3_Admin* value) { + _upb_sethas(msg, 8); + *UPB_PTR_AT(msg, UPB_SIZE(56, 112), envoy_config_bootstrap_v3_Admin*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Admin* envoy_config_bootstrap_v3_Bootstrap_mutable_admin(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Admin* sub = (struct envoy_config_bootstrap_v3_Admin*)envoy_config_bootstrap_v3_Bootstrap_admin(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Admin*)_upb_msg_new(&envoy_config_bootstrap_v3_Admin_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_admin(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_stats_config(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_metrics_v3_StatsConfig* value) { + _upb_sethas(msg, 9); + *UPB_PTR_AT(msg, UPB_SIZE(60, 120), struct envoy_config_metrics_v3_StatsConfig*) = value; +} +UPB_INLINE struct envoy_config_metrics_v3_StatsConfig* envoy_config_bootstrap_v3_Bootstrap_mutable_stats_config(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_metrics_v3_StatsConfig* sub = (struct envoy_config_metrics_v3_StatsConfig*)envoy_config_bootstrap_v3_Bootstrap_stats_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_metrics_v3_StatsConfig*)_upb_msg_new(&envoy_config_metrics_v3_StatsConfig_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_stats_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_hds_config(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_core_v3_ApiConfigSource* value) { + _upb_sethas(msg, 10); + *UPB_PTR_AT(msg, UPB_SIZE(64, 128), struct envoy_config_core_v3_ApiConfigSource*) = value; +} +UPB_INLINE struct envoy_config_core_v3_ApiConfigSource* envoy_config_bootstrap_v3_Bootstrap_mutable_hds_config(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_core_v3_ApiConfigSource* sub = (struct envoy_config_core_v3_ApiConfigSource*)envoy_config_bootstrap_v3_Bootstrap_hds_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_ApiConfigSource*)_upb_msg_new(&envoy_config_core_v3_ApiConfigSource_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_hds_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_overload_manager(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_overload_v3_OverloadManager* value) { + _upb_sethas(msg, 11); + *UPB_PTR_AT(msg, UPB_SIZE(68, 136), struct envoy_config_overload_v3_OverloadManager*) = value; +} +UPB_INLINE struct envoy_config_overload_v3_OverloadManager* envoy_config_bootstrap_v3_Bootstrap_mutable_overload_manager(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_overload_v3_OverloadManager* sub = (struct envoy_config_overload_v3_OverloadManager*)envoy_config_bootstrap_v3_Bootstrap_overload_manager(msg); + if (sub == NULL) { + sub = (struct envoy_config_overload_v3_OverloadManager*)_upb_msg_new(&envoy_config_overload_v3_OverloadManager_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_overload_manager(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_enable_dispatcher_stats(envoy_config_bootstrap_v3_Bootstrap *msg, bool value) { + *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_layered_runtime(envoy_config_bootstrap_v3_Bootstrap *msg, envoy_config_bootstrap_v3_LayeredRuntime* value) { + _upb_sethas(msg, 12); + *UPB_PTR_AT(msg, UPB_SIZE(72, 144), envoy_config_bootstrap_v3_LayeredRuntime*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_LayeredRuntime* envoy_config_bootstrap_v3_Bootstrap_mutable_layered_runtime(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_LayeredRuntime* sub = (struct envoy_config_bootstrap_v3_LayeredRuntime*)envoy_config_bootstrap_v3_Bootstrap_layered_runtime(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_LayeredRuntime*)_upb_msg_new(&envoy_config_bootstrap_v3_LayeredRuntime_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_layered_runtime(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_header_prefix(envoy_config_bootstrap_v3_Bootstrap *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_stats_server_version_override(envoy_config_bootstrap_v3_Bootstrap *msg, struct google_protobuf_UInt64Value* value) { + _upb_sethas(msg, 13); + *UPB_PTR_AT(msg, UPB_SIZE(76, 152), struct google_protobuf_UInt64Value*) = value; +} +UPB_INLINE struct google_protobuf_UInt64Value* envoy_config_bootstrap_v3_Bootstrap_mutable_stats_server_version_override(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct google_protobuf_UInt64Value* sub = (struct google_protobuf_UInt64Value*)envoy_config_bootstrap_v3_Bootstrap_stats_server_version_override(msg); + if (sub == NULL) { + sub = (struct google_protobuf_UInt64Value*)_upb_msg_new(&google_protobuf_UInt64Value_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_stats_server_version_override(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_use_tcp_for_dns_lookups(envoy_config_bootstrap_v3_Bootstrap *msg, bool value) { + *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool) = value; +} +UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig** envoy_config_bootstrap_v3_Bootstrap_mutable_bootstrap_extensions(envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { + return (struct envoy_config_core_v3_TypedExtensionConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(92, 184), len); +} +UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig** envoy_config_bootstrap_v3_Bootstrap_resize_bootstrap_extensions(envoy_config_bootstrap_v3_Bootstrap *msg, size_t len, upb_arena *arena) { + return (struct envoy_config_core_v3_TypedExtensionConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(92, 184), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_Bootstrap_add_bootstrap_extensions(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_msg_new(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(92, 184), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE struct envoy_config_core_v3_ConfigSource** envoy_config_bootstrap_v3_Bootstrap_mutable_config_sources(envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { + return (struct envoy_config_core_v3_ConfigSource**)_upb_array_mutable_accessor(msg, UPB_SIZE(96, 192), len); +} +UPB_INLINE struct envoy_config_core_v3_ConfigSource** envoy_config_bootstrap_v3_Bootstrap_resize_config_sources(envoy_config_bootstrap_v3_Bootstrap *msg, size_t len, upb_arena *arena) { + return (struct envoy_config_core_v3_ConfigSource**)_upb_array_resize_accessor2(msg, UPB_SIZE(96, 192), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_Bootstrap_add_config_sources(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_core_v3_ConfigSource* sub = (struct envoy_config_core_v3_ConfigSource*)_upb_msg_new(&envoy_config_core_v3_ConfigSource_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(96, 192), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_default_config_source(envoy_config_bootstrap_v3_Bootstrap *msg, struct envoy_config_core_v3_ConfigSource* value) { + _upb_sethas(msg, 14); + *UPB_PTR_AT(msg, UPB_SIZE(80, 160), struct envoy_config_core_v3_ConfigSource*) = value; +} +UPB_INLINE struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_Bootstrap_mutable_default_config_source(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_core_v3_ConfigSource* sub = (struct envoy_config_core_v3_ConfigSource*)envoy_config_bootstrap_v3_Bootstrap_default_config_source(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_ConfigSource*)_upb_msg_new(&envoy_config_core_v3_ConfigSource_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_default_config_source(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_default_socket_interface(envoy_config_bootstrap_v3_Bootstrap *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_certificate_provider_instances_clear(envoy_config_bootstrap_v3_Bootstrap *msg) { _upb_msg_map_clear(msg, UPB_SIZE(100, 200)); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_certificate_provider_instances_set(envoy_config_bootstrap_v3_Bootstrap *msg, upb_strview key, struct envoy_config_core_v3_TypedExtensionConfig* val, upb_arena *a) { return _upb_msg_map_set(msg, UPB_SIZE(100, 200), &key, 0, &val, sizeof(val), a); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_certificate_provider_instances_delete(envoy_config_bootstrap_v3_Bootstrap *msg, upb_strview key) { return _upb_msg_map_delete(msg, UPB_SIZE(100, 200), &key, 0); } +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry* envoy_config_bootstrap_v3_Bootstrap_certificate_provider_instances_nextmutable(envoy_config_bootstrap_v3_Bootstrap *msg, size_t* iter) { return (envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry*)_upb_msg_map_next(msg, UPB_SIZE(100, 200), iter); } +UPB_INLINE upb_strview* envoy_config_bootstrap_v3_Bootstrap_mutable_node_context_params(envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(104, 208), len); +} +UPB_INLINE upb_strview* envoy_config_bootstrap_v3_Bootstrap_resize_node_context_params(envoy_config_bootstrap_v3_Bootstrap *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(104, 208), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_add_node_context_params(envoy_config_bootstrap_v3_Bootstrap *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(104, 208), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_watchdogs(envoy_config_bootstrap_v3_Bootstrap *msg, envoy_config_bootstrap_v3_Watchdogs* value) { + _upb_sethas(msg, 15); + *UPB_PTR_AT(msg, UPB_SIZE(84, 168), envoy_config_bootstrap_v3_Watchdogs*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Watchdogs* envoy_config_bootstrap_v3_Bootstrap_mutable_watchdogs(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Watchdogs* sub = (struct envoy_config_bootstrap_v3_Watchdogs*)envoy_config_bootstrap_v3_Bootstrap_watchdogs(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Watchdogs*)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdogs_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_set_watchdogs(msg, sub); + } + return sub; +} +UPB_INLINE envoy_config_bootstrap_v3_FatalAction** envoy_config_bootstrap_v3_Bootstrap_mutable_fatal_actions(envoy_config_bootstrap_v3_Bootstrap *msg, size_t *len) { + return (envoy_config_bootstrap_v3_FatalAction**)_upb_array_mutable_accessor(msg, UPB_SIZE(108, 216), len); +} +UPB_INLINE envoy_config_bootstrap_v3_FatalAction** envoy_config_bootstrap_v3_Bootstrap_resize_fatal_actions(envoy_config_bootstrap_v3_Bootstrap *msg, size_t len, upb_arena *arena) { + return (envoy_config_bootstrap_v3_FatalAction**)_upb_array_resize_accessor2(msg, UPB_SIZE(108, 216), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_bootstrap_v3_FatalAction* envoy_config_bootstrap_v3_Bootstrap_add_fatal_actions(envoy_config_bootstrap_v3_Bootstrap *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_FatalAction* sub = (struct envoy_config_bootstrap_v3_FatalAction*)_upb_msg_new(&envoy_config_bootstrap_v3_FatalAction_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(108, 216), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_set_stats_flush_on_admin(envoy_config_bootstrap_v3_Bootstrap *msg, bool value) { + UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(112, 224), value, UPB_SIZE(116, 228), 29); +} + +/* envoy.config.bootstrap.v3.Bootstrap.StaticResources */ + +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_StaticResources *envoy_config_bootstrap_v3_Bootstrap_StaticResources_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Bootstrap_StaticResources *)_upb_msg_new(&envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_StaticResources *envoy_config_bootstrap_v3_Bootstrap_StaticResources_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Bootstrap_StaticResources *ret = envoy_config_bootstrap_v3_Bootstrap_StaticResources_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_StaticResources *envoy_config_bootstrap_v3_Bootstrap_StaticResources_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Bootstrap_StaticResources *ret = envoy_config_bootstrap_v3_Bootstrap_StaticResources_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Bootstrap_StaticResources_serialize(const envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_StaticResources_has_listeners(const envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const struct envoy_config_listener_v3_Listener* const* envoy_config_bootstrap_v3_Bootstrap_StaticResources_listeners(const envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t *len) { return (const struct envoy_config_listener_v3_Listener* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_StaticResources_has_clusters(const envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(4, 8)); } +UPB_INLINE const struct envoy_config_cluster_v3_Cluster* const* envoy_config_bootstrap_v3_Bootstrap_StaticResources_clusters(const envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t *len) { return (const struct envoy_config_cluster_v3_Cluster* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_StaticResources_has_secrets(const envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const struct envoy_extensions_transport_sockets_tls_v3_Secret* const* envoy_config_bootstrap_v3_Bootstrap_StaticResources_secrets(const envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t *len) { return (const struct envoy_extensions_transport_sockets_tls_v3_Secret* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } + +UPB_INLINE struct envoy_config_listener_v3_Listener** envoy_config_bootstrap_v3_Bootstrap_StaticResources_mutable_listeners(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t *len) { + return (struct envoy_config_listener_v3_Listener**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE struct envoy_config_listener_v3_Listener** envoy_config_bootstrap_v3_Bootstrap_StaticResources_resize_listeners(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t len, upb_arena *arena) { + return (struct envoy_config_listener_v3_Listener**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_listener_v3_Listener* envoy_config_bootstrap_v3_Bootstrap_StaticResources_add_listeners(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, upb_arena *arena) { + struct envoy_config_listener_v3_Listener* sub = (struct envoy_config_listener_v3_Listener*)_upb_msg_new(&envoy_config_listener_v3_Listener_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE struct envoy_config_cluster_v3_Cluster** envoy_config_bootstrap_v3_Bootstrap_StaticResources_mutable_clusters(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t *len) { + return (struct envoy_config_cluster_v3_Cluster**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), len); +} +UPB_INLINE struct envoy_config_cluster_v3_Cluster** envoy_config_bootstrap_v3_Bootstrap_StaticResources_resize_clusters(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t len, upb_arena *arena) { + return (struct envoy_config_cluster_v3_Cluster**)_upb_array_resize_accessor2(msg, UPB_SIZE(4, 8), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_cluster_v3_Cluster* envoy_config_bootstrap_v3_Bootstrap_StaticResources_add_clusters(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, upb_arena *arena) { + struct envoy_config_cluster_v3_Cluster* sub = (struct envoy_config_cluster_v3_Cluster*)_upb_msg_new(&envoy_config_cluster_v3_Cluster_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE struct envoy_extensions_transport_sockets_tls_v3_Secret** envoy_config_bootstrap_v3_Bootstrap_StaticResources_mutable_secrets(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t *len) { + return (struct envoy_extensions_transport_sockets_tls_v3_Secret**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE struct envoy_extensions_transport_sockets_tls_v3_Secret** envoy_config_bootstrap_v3_Bootstrap_StaticResources_resize_secrets(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, size_t len, upb_arena *arena) { + return (struct envoy_extensions_transport_sockets_tls_v3_Secret**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_extensions_transport_sockets_tls_v3_Secret* envoy_config_bootstrap_v3_Bootstrap_StaticResources_add_secrets(envoy_config_bootstrap_v3_Bootstrap_StaticResources *msg, upb_arena *arena) { + struct envoy_extensions_transport_sockets_tls_v3_Secret* sub = (struct envoy_extensions_transport_sockets_tls_v3_Secret*)_upb_msg_new(&envoy_extensions_transport_sockets_tls_v3_Secret_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.config.bootstrap.v3.Bootstrap.DynamicResources */ + +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_DynamicResources *envoy_config_bootstrap_v3_Bootstrap_DynamicResources_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Bootstrap_DynamicResources *)_upb_msg_new(&envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_DynamicResources *envoy_config_bootstrap_v3_Bootstrap_DynamicResources_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Bootstrap_DynamicResources *ret = envoy_config_bootstrap_v3_Bootstrap_DynamicResources_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Bootstrap_DynamicResources *envoy_config_bootstrap_v3_Bootstrap_DynamicResources_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Bootstrap_DynamicResources *ret = envoy_config_bootstrap_v3_Bootstrap_DynamicResources_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Bootstrap_DynamicResources_serialize(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_DynamicResources_has_lds_config(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_Bootstrap_DynamicResources_lds_config(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), const struct envoy_config_core_v3_ConfigSource*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_DynamicResources_has_cds_config(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_Bootstrap_DynamicResources_cds_config(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 48), const struct envoy_config_core_v3_ConfigSource*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_DynamicResources_has_ads_config(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const struct envoy_config_core_v3_ApiConfigSource* envoy_config_bootstrap_v3_Bootstrap_DynamicResources_ads_config(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const struct envoy_config_core_v3_ApiConfigSource*); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Bootstrap_DynamicResources_lds_resources_locator(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Bootstrap_DynamicResources_cds_resources_locator(const envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } + +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_lds_config(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, struct envoy_config_core_v3_ConfigSource* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), struct envoy_config_core_v3_ConfigSource*) = value; +} +UPB_INLINE struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_Bootstrap_DynamicResources_mutable_lds_config(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, upb_arena *arena) { + struct envoy_config_core_v3_ConfigSource* sub = (struct envoy_config_core_v3_ConfigSource*)envoy_config_bootstrap_v3_Bootstrap_DynamicResources_lds_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_ConfigSource*)_upb_msg_new(&envoy_config_core_v3_ConfigSource_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_lds_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_cds_config(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, struct envoy_config_core_v3_ConfigSource* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(24, 48), struct envoy_config_core_v3_ConfigSource*) = value; +} +UPB_INLINE struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_Bootstrap_DynamicResources_mutable_cds_config(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, upb_arena *arena) { + struct envoy_config_core_v3_ConfigSource* sub = (struct envoy_config_core_v3_ConfigSource*)envoy_config_bootstrap_v3_Bootstrap_DynamicResources_cds_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_ConfigSource*)_upb_msg_new(&envoy_config_core_v3_ConfigSource_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_cds_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_ads_config(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, struct envoy_config_core_v3_ApiConfigSource* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), struct envoy_config_core_v3_ApiConfigSource*) = value; +} +UPB_INLINE struct envoy_config_core_v3_ApiConfigSource* envoy_config_bootstrap_v3_Bootstrap_DynamicResources_mutable_ads_config(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, upb_arena *arena) { + struct envoy_config_core_v3_ApiConfigSource* sub = (struct envoy_config_core_v3_ApiConfigSource*)envoy_config_bootstrap_v3_Bootstrap_DynamicResources_ads_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_ApiConfigSource*)_upb_msg_new(&envoy_config_core_v3_ApiConfigSource_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_ads_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_lds_resources_locator(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_DynamicResources_set_cds_resources_locator(envoy_config_bootstrap_v3_Bootstrap_DynamicResources *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} + +/* envoy.config.bootstrap.v3.Bootstrap.CertificateProviderInstancesEntry */ + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_key(const envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry *msg) { + upb_strview ret; + _upb_msg_map_key(msg, &ret, 0); + return ret; +} +UPB_INLINE bool envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_has_value(const envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_value(const envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry *msg) { + struct envoy_config_core_v3_TypedExtensionConfig* ret; + _upb_msg_map_value(msg, &ret, sizeof(ret)); + return ret; +} + +UPB_INLINE void envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_set_value(envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry *msg, struct envoy_config_core_v3_TypedExtensionConfig* value) { + _upb_msg_map_set_value(msg, &value, sizeof(struct envoy_config_core_v3_TypedExtensionConfig*)); +} + +/* envoy.config.bootstrap.v3.Admin */ + +UPB_INLINE envoy_config_bootstrap_v3_Admin *envoy_config_bootstrap_v3_Admin_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Admin *)_upb_msg_new(&envoy_config_bootstrap_v3_Admin_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Admin *envoy_config_bootstrap_v3_Admin_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Admin *ret = envoy_config_bootstrap_v3_Admin_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Admin_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Admin *envoy_config_bootstrap_v3_Admin_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Admin *ret = envoy_config_bootstrap_v3_Admin_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Admin_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Admin_serialize(const envoy_config_bootstrap_v3_Admin *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Admin_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Admin_access_log_path(const envoy_config_bootstrap_v3_Admin *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Admin_profile_path(const envoy_config_bootstrap_v3_Admin *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_Admin_has_address(const envoy_config_bootstrap_v3_Admin *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_Address* envoy_config_bootstrap_v3_Admin_address(const envoy_config_bootstrap_v3_Admin *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), const struct envoy_config_core_v3_Address*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Admin_has_socket_options(const envoy_config_bootstrap_v3_Admin *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(24, 48)); } +UPB_INLINE const struct envoy_config_core_v3_SocketOption* const* envoy_config_bootstrap_v3_Admin_socket_options(const envoy_config_bootstrap_v3_Admin *msg, size_t *len) { return (const struct envoy_config_core_v3_SocketOption* const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); } + +UPB_INLINE void envoy_config_bootstrap_v3_Admin_set_access_log_path(envoy_config_bootstrap_v3_Admin *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Admin_set_profile_path(envoy_config_bootstrap_v3_Admin *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Admin_set_address(envoy_config_bootstrap_v3_Admin *msg, struct envoy_config_core_v3_Address* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), struct envoy_config_core_v3_Address*) = value; +} +UPB_INLINE struct envoy_config_core_v3_Address* envoy_config_bootstrap_v3_Admin_mutable_address(envoy_config_bootstrap_v3_Admin *msg, upb_arena *arena) { + struct envoy_config_core_v3_Address* sub = (struct envoy_config_core_v3_Address*)envoy_config_bootstrap_v3_Admin_address(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_Address*)_upb_msg_new(&envoy_config_core_v3_Address_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Admin_set_address(msg, sub); + } + return sub; +} +UPB_INLINE struct envoy_config_core_v3_SocketOption** envoy_config_bootstrap_v3_Admin_mutable_socket_options(envoy_config_bootstrap_v3_Admin *msg, size_t *len) { + return (struct envoy_config_core_v3_SocketOption**)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len); +} +UPB_INLINE struct envoy_config_core_v3_SocketOption** envoy_config_bootstrap_v3_Admin_resize_socket_options(envoy_config_bootstrap_v3_Admin *msg, size_t len, upb_arena *arena) { + return (struct envoy_config_core_v3_SocketOption**)_upb_array_resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_core_v3_SocketOption* envoy_config_bootstrap_v3_Admin_add_socket_options(envoy_config_bootstrap_v3_Admin *msg, upb_arena *arena) { + struct envoy_config_core_v3_SocketOption* sub = (struct envoy_config_core_v3_SocketOption*)_upb_msg_new(&envoy_config_core_v3_SocketOption_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.config.bootstrap.v3.ClusterManager */ + +UPB_INLINE envoy_config_bootstrap_v3_ClusterManager *envoy_config_bootstrap_v3_ClusterManager_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_ClusterManager *)_upb_msg_new(&envoy_config_bootstrap_v3_ClusterManager_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_ClusterManager *envoy_config_bootstrap_v3_ClusterManager_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_ClusterManager *ret = envoy_config_bootstrap_v3_ClusterManager_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_ClusterManager_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_ClusterManager *envoy_config_bootstrap_v3_ClusterManager_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_ClusterManager *ret = envoy_config_bootstrap_v3_ClusterManager_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_ClusterManager_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_ClusterManager_serialize(const envoy_config_bootstrap_v3_ClusterManager *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_ClusterManager_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_ClusterManager_local_cluster_name(const envoy_config_bootstrap_v3_ClusterManager *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_ClusterManager_has_outlier_detection(const envoy_config_bootstrap_v3_ClusterManager *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const envoy_config_bootstrap_v3_ClusterManager_OutlierDetection* envoy_config_bootstrap_v3_ClusterManager_outlier_detection(const envoy_config_bootstrap_v3_ClusterManager *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const envoy_config_bootstrap_v3_ClusterManager_OutlierDetection*); } +UPB_INLINE bool envoy_config_bootstrap_v3_ClusterManager_has_upstream_bind_config(const envoy_config_bootstrap_v3_ClusterManager *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct envoy_config_core_v3_BindConfig* envoy_config_bootstrap_v3_ClusterManager_upstream_bind_config(const envoy_config_bootstrap_v3_ClusterManager *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), const struct envoy_config_core_v3_BindConfig*); } +UPB_INLINE bool envoy_config_bootstrap_v3_ClusterManager_has_load_stats_config(const envoy_config_bootstrap_v3_ClusterManager *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const struct envoy_config_core_v3_ApiConfigSource* envoy_config_bootstrap_v3_ClusterManager_load_stats_config(const envoy_config_bootstrap_v3_ClusterManager *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), const struct envoy_config_core_v3_ApiConfigSource*); } + +UPB_INLINE void envoy_config_bootstrap_v3_ClusterManager_set_local_cluster_name(envoy_config_bootstrap_v3_ClusterManager *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_ClusterManager_set_outlier_detection(envoy_config_bootstrap_v3_ClusterManager *msg, envoy_config_bootstrap_v3_ClusterManager_OutlierDetection* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), envoy_config_bootstrap_v3_ClusterManager_OutlierDetection*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_ClusterManager_OutlierDetection* envoy_config_bootstrap_v3_ClusterManager_mutable_outlier_detection(envoy_config_bootstrap_v3_ClusterManager *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_ClusterManager_OutlierDetection* sub = (struct envoy_config_bootstrap_v3_ClusterManager_OutlierDetection*)envoy_config_bootstrap_v3_ClusterManager_outlier_detection(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_ClusterManager_OutlierDetection*)_upb_msg_new(&envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_ClusterManager_set_outlier_detection(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_ClusterManager_set_upstream_bind_config(envoy_config_bootstrap_v3_ClusterManager *msg, struct envoy_config_core_v3_BindConfig* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(16, 32), struct envoy_config_core_v3_BindConfig*) = value; +} +UPB_INLINE struct envoy_config_core_v3_BindConfig* envoy_config_bootstrap_v3_ClusterManager_mutable_upstream_bind_config(envoy_config_bootstrap_v3_ClusterManager *msg, upb_arena *arena) { + struct envoy_config_core_v3_BindConfig* sub = (struct envoy_config_core_v3_BindConfig*)envoy_config_bootstrap_v3_ClusterManager_upstream_bind_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_BindConfig*)_upb_msg_new(&envoy_config_core_v3_BindConfig_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_ClusterManager_set_upstream_bind_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_ClusterManager_set_load_stats_config(envoy_config_bootstrap_v3_ClusterManager *msg, struct envoy_config_core_v3_ApiConfigSource* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), struct envoy_config_core_v3_ApiConfigSource*) = value; +} +UPB_INLINE struct envoy_config_core_v3_ApiConfigSource* envoy_config_bootstrap_v3_ClusterManager_mutable_load_stats_config(envoy_config_bootstrap_v3_ClusterManager *msg, upb_arena *arena) { + struct envoy_config_core_v3_ApiConfigSource* sub = (struct envoy_config_core_v3_ApiConfigSource*)envoy_config_bootstrap_v3_ClusterManager_load_stats_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_ApiConfigSource*)_upb_msg_new(&envoy_config_core_v3_ApiConfigSource_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_ClusterManager_set_load_stats_config(msg, sub); + } + return sub; +} + +/* envoy.config.bootstrap.v3.ClusterManager.OutlierDetection */ + +UPB_INLINE envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *)_upb_msg_new(&envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *ret = envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *ret = envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_serialize(const envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_event_log_path(const envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_has_event_service(const envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_EventServiceConfig* envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_event_service(const envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct envoy_config_core_v3_EventServiceConfig*); } + +UPB_INLINE void envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_set_event_log_path(envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_set_event_service(envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *msg, struct envoy_config_core_v3_EventServiceConfig* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct envoy_config_core_v3_EventServiceConfig*) = value; +} +UPB_INLINE struct envoy_config_core_v3_EventServiceConfig* envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_mutable_event_service(envoy_config_bootstrap_v3_ClusterManager_OutlierDetection *msg, upb_arena *arena) { + struct envoy_config_core_v3_EventServiceConfig* sub = (struct envoy_config_core_v3_EventServiceConfig*)envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_event_service(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_EventServiceConfig*)_upb_msg_new(&envoy_config_core_v3_EventServiceConfig_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_set_event_service(msg, sub); + } + return sub; +} + +/* envoy.config.bootstrap.v3.Watchdogs */ + +UPB_INLINE envoy_config_bootstrap_v3_Watchdogs *envoy_config_bootstrap_v3_Watchdogs_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Watchdogs *)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdogs_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdogs *envoy_config_bootstrap_v3_Watchdogs_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Watchdogs *ret = envoy_config_bootstrap_v3_Watchdogs_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Watchdogs_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdogs *envoy_config_bootstrap_v3_Watchdogs_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Watchdogs *ret = envoy_config_bootstrap_v3_Watchdogs_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Watchdogs_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Watchdogs_serialize(const envoy_config_bootstrap_v3_Watchdogs *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Watchdogs_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdogs_has_main_thread_watchdog(const envoy_config_bootstrap_v3_Watchdogs *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const envoy_config_bootstrap_v3_Watchdog* envoy_config_bootstrap_v3_Watchdogs_main_thread_watchdog(const envoy_config_bootstrap_v3_Watchdogs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const envoy_config_bootstrap_v3_Watchdog*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdogs_has_worker_watchdog(const envoy_config_bootstrap_v3_Watchdogs *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const envoy_config_bootstrap_v3_Watchdog* envoy_config_bootstrap_v3_Watchdogs_worker_watchdog(const envoy_config_bootstrap_v3_Watchdogs *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const envoy_config_bootstrap_v3_Watchdog*); } + +UPB_INLINE void envoy_config_bootstrap_v3_Watchdogs_set_main_thread_watchdog(envoy_config_bootstrap_v3_Watchdogs *msg, envoy_config_bootstrap_v3_Watchdog* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), envoy_config_bootstrap_v3_Watchdog*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Watchdog* envoy_config_bootstrap_v3_Watchdogs_mutable_main_thread_watchdog(envoy_config_bootstrap_v3_Watchdogs *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Watchdog* sub = (struct envoy_config_bootstrap_v3_Watchdog*)envoy_config_bootstrap_v3_Watchdogs_main_thread_watchdog(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Watchdog*)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdog_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdogs_set_main_thread_watchdog(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Watchdogs_set_worker_watchdog(envoy_config_bootstrap_v3_Watchdogs *msg, envoy_config_bootstrap_v3_Watchdog* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), envoy_config_bootstrap_v3_Watchdog*) = value; +} +UPB_INLINE struct envoy_config_bootstrap_v3_Watchdog* envoy_config_bootstrap_v3_Watchdogs_mutable_worker_watchdog(envoy_config_bootstrap_v3_Watchdogs *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Watchdog* sub = (struct envoy_config_bootstrap_v3_Watchdog*)envoy_config_bootstrap_v3_Watchdogs_worker_watchdog(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_Watchdog*)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdog_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdogs_set_worker_watchdog(msg, sub); + } + return sub; +} + +/* envoy.config.bootstrap.v3.Watchdog */ + +UPB_INLINE envoy_config_bootstrap_v3_Watchdog *envoy_config_bootstrap_v3_Watchdog_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Watchdog *)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdog_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdog *envoy_config_bootstrap_v3_Watchdog_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Watchdog *ret = envoy_config_bootstrap_v3_Watchdog_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Watchdog_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdog *envoy_config_bootstrap_v3_Watchdog_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Watchdog *ret = envoy_config_bootstrap_v3_Watchdog_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Watchdog_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Watchdog_serialize(const envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Watchdog_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_has_miss_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_miss_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_Duration*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_has_megamiss_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_megamiss_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const struct google_protobuf_Duration*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_has_kill_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_kill_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Duration*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_has_multikill_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_multikill_timeout(const envoy_config_bootstrap_v3_Watchdog *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), const struct google_protobuf_Duration*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_has_multikill_threshold(const envoy_config_bootstrap_v3_Watchdog *msg) { return _upb_hasbit(msg, 5); } +UPB_INLINE const struct envoy_type_v3_Percent* envoy_config_bootstrap_v3_Watchdog_multikill_threshold(const envoy_config_bootstrap_v3_Watchdog *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), const struct envoy_type_v3_Percent*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_has_max_kill_timeout_jitter(const envoy_config_bootstrap_v3_Watchdog *msg) { return _upb_hasbit(msg, 6); } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_max_kill_timeout_jitter(const envoy_config_bootstrap_v3_Watchdog *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(24, 48), const struct google_protobuf_Duration*); } +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_has_actions(const envoy_config_bootstrap_v3_Watchdog *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(28, 56)); } +UPB_INLINE const envoy_config_bootstrap_v3_Watchdog_WatchdogAction* const* envoy_config_bootstrap_v3_Watchdog_actions(const envoy_config_bootstrap_v3_Watchdog *msg, size_t *len) { return (const envoy_config_bootstrap_v3_Watchdog_WatchdogAction* const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); } + +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_set_miss_timeout(envoy_config_bootstrap_v3_Watchdog *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_mutable_miss_timeout(envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_bootstrap_v3_Watchdog_miss_timeout(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdog_set_miss_timeout(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_set_megamiss_timeout(envoy_config_bootstrap_v3_Watchdog *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_mutable_megamiss_timeout(envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_bootstrap_v3_Watchdog_megamiss_timeout(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdog_set_megamiss_timeout(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_set_kill_timeout(envoy_config_bootstrap_v3_Watchdog *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_mutable_kill_timeout(envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_bootstrap_v3_Watchdog_kill_timeout(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdog_set_kill_timeout(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_set_multikill_timeout(envoy_config_bootstrap_v3_Watchdog *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(16, 32), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_mutable_multikill_timeout(envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_bootstrap_v3_Watchdog_multikill_timeout(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdog_set_multikill_timeout(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_set_multikill_threshold(envoy_config_bootstrap_v3_Watchdog *msg, struct envoy_type_v3_Percent* value) { + _upb_sethas(msg, 5); + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), struct envoy_type_v3_Percent*) = value; +} +UPB_INLINE struct envoy_type_v3_Percent* envoy_config_bootstrap_v3_Watchdog_mutable_multikill_threshold(envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena) { + struct envoy_type_v3_Percent* sub = (struct envoy_type_v3_Percent*)envoy_config_bootstrap_v3_Watchdog_multikill_threshold(msg); + if (sub == NULL) { + sub = (struct envoy_type_v3_Percent*)_upb_msg_new(&envoy_type_v3_Percent_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdog_set_multikill_threshold(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_set_max_kill_timeout_jitter(envoy_config_bootstrap_v3_Watchdog *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 6); + *UPB_PTR_AT(msg, UPB_SIZE(24, 48), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_bootstrap_v3_Watchdog_mutable_max_kill_timeout_jitter(envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_bootstrap_v3_Watchdog_max_kill_timeout_jitter(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdog_set_max_kill_timeout_jitter(msg, sub); + } + return sub; +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdog_WatchdogAction** envoy_config_bootstrap_v3_Watchdog_mutable_actions(envoy_config_bootstrap_v3_Watchdog *msg, size_t *len) { + return (envoy_config_bootstrap_v3_Watchdog_WatchdogAction**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len); +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdog_WatchdogAction** envoy_config_bootstrap_v3_Watchdog_resize_actions(envoy_config_bootstrap_v3_Watchdog *msg, size_t len, upb_arena *arena) { + return (envoy_config_bootstrap_v3_Watchdog_WatchdogAction**)_upb_array_resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_bootstrap_v3_Watchdog_WatchdogAction* envoy_config_bootstrap_v3_Watchdog_add_actions(envoy_config_bootstrap_v3_Watchdog *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_Watchdog_WatchdogAction* sub = (struct envoy_config_bootstrap_v3_Watchdog_WatchdogAction*)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.config.bootstrap.v3.Watchdog.WatchdogAction */ + +UPB_INLINE envoy_config_bootstrap_v3_Watchdog_WatchdogAction *envoy_config_bootstrap_v3_Watchdog_WatchdogAction_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Watchdog_WatchdogAction *)_upb_msg_new(&envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdog_WatchdogAction *envoy_config_bootstrap_v3_Watchdog_WatchdogAction_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Watchdog_WatchdogAction *ret = envoy_config_bootstrap_v3_Watchdog_WatchdogAction_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Watchdog_WatchdogAction *envoy_config_bootstrap_v3_Watchdog_WatchdogAction_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Watchdog_WatchdogAction *ret = envoy_config_bootstrap_v3_Watchdog_WatchdogAction_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Watchdog_WatchdogAction_serialize(const envoy_config_bootstrap_v3_Watchdog_WatchdogAction *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_bootstrap_v3_Watchdog_WatchdogAction_has_config(const envoy_config_bootstrap_v3_Watchdog_WatchdogAction *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_Watchdog_WatchdogAction_config(const envoy_config_bootstrap_v3_Watchdog_WatchdogAction *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), const struct envoy_config_core_v3_TypedExtensionConfig*); } +UPB_INLINE int32_t envoy_config_bootstrap_v3_Watchdog_WatchdogAction_event(const envoy_config_bootstrap_v3_Watchdog_WatchdogAction *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_WatchdogAction_set_config(envoy_config_bootstrap_v3_Watchdog_WatchdogAction *msg, struct envoy_config_core_v3_TypedExtensionConfig* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), struct envoy_config_core_v3_TypedExtensionConfig*) = value; +} +UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_Watchdog_WatchdogAction_mutable_config(envoy_config_bootstrap_v3_Watchdog_WatchdogAction *msg, upb_arena *arena) { + struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)envoy_config_bootstrap_v3_Watchdog_WatchdogAction_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_msg_new(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Watchdog_WatchdogAction_set_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_Watchdog_WatchdogAction_set_event(envoy_config_bootstrap_v3_Watchdog_WatchdogAction *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +/* envoy.config.bootstrap.v3.FatalAction */ + +UPB_INLINE envoy_config_bootstrap_v3_FatalAction *envoy_config_bootstrap_v3_FatalAction_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_FatalAction *)_upb_msg_new(&envoy_config_bootstrap_v3_FatalAction_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_FatalAction *envoy_config_bootstrap_v3_FatalAction_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_FatalAction *ret = envoy_config_bootstrap_v3_FatalAction_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_FatalAction_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_FatalAction *envoy_config_bootstrap_v3_FatalAction_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_FatalAction *ret = envoy_config_bootstrap_v3_FatalAction_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_FatalAction_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_FatalAction_serialize(const envoy_config_bootstrap_v3_FatalAction *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_FatalAction_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_bootstrap_v3_FatalAction_has_config(const envoy_config_bootstrap_v3_FatalAction *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_FatalAction_config(const envoy_config_bootstrap_v3_FatalAction *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_config_core_v3_TypedExtensionConfig*); } + +UPB_INLINE void envoy_config_bootstrap_v3_FatalAction_set_config(envoy_config_bootstrap_v3_FatalAction *msg, struct envoy_config_core_v3_TypedExtensionConfig* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_config_core_v3_TypedExtensionConfig*) = value; +} +UPB_INLINE struct envoy_config_core_v3_TypedExtensionConfig* envoy_config_bootstrap_v3_FatalAction_mutable_config(envoy_config_bootstrap_v3_FatalAction *msg, upb_arena *arena) { + struct envoy_config_core_v3_TypedExtensionConfig* sub = (struct envoy_config_core_v3_TypedExtensionConfig*)envoy_config_bootstrap_v3_FatalAction_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_TypedExtensionConfig*)_upb_msg_new(&envoy_config_core_v3_TypedExtensionConfig_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_FatalAction_set_config(msg, sub); + } + return sub; +} + +/* envoy.config.bootstrap.v3.Runtime */ + +UPB_INLINE envoy_config_bootstrap_v3_Runtime *envoy_config_bootstrap_v3_Runtime_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_Runtime *)_upb_msg_new(&envoy_config_bootstrap_v3_Runtime_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_Runtime *envoy_config_bootstrap_v3_Runtime_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_Runtime *ret = envoy_config_bootstrap_v3_Runtime_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Runtime_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_Runtime *envoy_config_bootstrap_v3_Runtime_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_Runtime *ret = envoy_config_bootstrap_v3_Runtime_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_Runtime_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_Runtime_serialize(const envoy_config_bootstrap_v3_Runtime *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_Runtime_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Runtime_symlink_root(const envoy_config_bootstrap_v3_Runtime *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Runtime_subdirectory(const envoy_config_bootstrap_v3_Runtime *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_Runtime_override_subdirectory(const envoy_config_bootstrap_v3_Runtime *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_Runtime_has_base(const envoy_config_bootstrap_v3_Runtime *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Struct* envoy_config_bootstrap_v3_Runtime_base(const envoy_config_bootstrap_v3_Runtime *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), const struct google_protobuf_Struct*); } + +UPB_INLINE void envoy_config_bootstrap_v3_Runtime_set_symlink_root(envoy_config_bootstrap_v3_Runtime *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Runtime_set_subdirectory(envoy_config_bootstrap_v3_Runtime *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Runtime_set_override_subdirectory(envoy_config_bootstrap_v3_Runtime *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_Runtime_set_base(envoy_config_bootstrap_v3_Runtime *msg, struct google_protobuf_Struct* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), struct google_protobuf_Struct*) = value; +} +UPB_INLINE struct google_protobuf_Struct* envoy_config_bootstrap_v3_Runtime_mutable_base(envoy_config_bootstrap_v3_Runtime *msg, upb_arena *arena) { + struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)envoy_config_bootstrap_v3_Runtime_base(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Struct*)_upb_msg_new(&google_protobuf_Struct_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_Runtime_set_base(msg, sub); + } + return sub; +} + +/* envoy.config.bootstrap.v3.RuntimeLayer */ + +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer *envoy_config_bootstrap_v3_RuntimeLayer_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_RuntimeLayer *)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer *envoy_config_bootstrap_v3_RuntimeLayer_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_RuntimeLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer *envoy_config_bootstrap_v3_RuntimeLayer_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_RuntimeLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_RuntimeLayer_serialize(const envoy_config_bootstrap_v3_RuntimeLayer *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_RuntimeLayer_msginit, arena, len); +} + +typedef enum { + envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_static_layer = 2, + envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_disk_layer = 3, + envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_admin_layer = 4, + envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_rtds_layer = 5, + envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_NOT_SET = 0 +} envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_oneofcases; +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_oneofcases envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_case(const envoy_config_bootstrap_v3_RuntimeLayer* msg) { return (envoy_config_bootstrap_v3_RuntimeLayer_layer_specifier_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 24), int32_t); } + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_RuntimeLayer_name(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_RuntimeLayer_has_static_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 2; } +UPB_INLINE const struct google_protobuf_Struct* envoy_config_bootstrap_v3_RuntimeLayer_static_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Struct*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, NULL); } +UPB_INLINE bool envoy_config_bootstrap_v3_RuntimeLayer_has_disk_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 3; } +UPB_INLINE const envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer* envoy_config_bootstrap_v3_RuntimeLayer_disk_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return UPB_READ_ONEOF(msg, const envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); } +UPB_INLINE bool envoy_config_bootstrap_v3_RuntimeLayer_has_admin_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 4; } +UPB_INLINE const envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer* envoy_config_bootstrap_v3_RuntimeLayer_admin_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return UPB_READ_ONEOF(msg, const envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 4, NULL); } +UPB_INLINE bool envoy_config_bootstrap_v3_RuntimeLayer_has_rtds_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 5; } +UPB_INLINE const envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer* envoy_config_bootstrap_v3_RuntimeLayer_rtds_layer(const envoy_config_bootstrap_v3_RuntimeLayer *msg) { return UPB_READ_ONEOF(msg, const envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 5, NULL); } + +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_set_name(envoy_config_bootstrap_v3_RuntimeLayer *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_set_static_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, struct google_protobuf_Struct* value) { + UPB_WRITE_ONEOF(msg, struct google_protobuf_Struct*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2); +} +UPB_INLINE struct google_protobuf_Struct* envoy_config_bootstrap_v3_RuntimeLayer_mutable_static_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, upb_arena *arena) { + struct google_protobuf_Struct* sub = (struct google_protobuf_Struct*)envoy_config_bootstrap_v3_RuntimeLayer_static_layer(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Struct*)_upb_msg_new(&google_protobuf_Struct_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_RuntimeLayer_set_static_layer(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_set_disk_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer* value) { + UPB_WRITE_ONEOF(msg, envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3); +} +UPB_INLINE struct envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer* envoy_config_bootstrap_v3_RuntimeLayer_mutable_disk_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer* sub = (struct envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer*)envoy_config_bootstrap_v3_RuntimeLayer_disk_layer(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer*)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_RuntimeLayer_set_disk_layer(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_set_admin_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer* value) { + UPB_WRITE_ONEOF(msg, envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 4); +} +UPB_INLINE struct envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer* envoy_config_bootstrap_v3_RuntimeLayer_mutable_admin_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer* sub = (struct envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer*)envoy_config_bootstrap_v3_RuntimeLayer_admin_layer(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer*)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_RuntimeLayer_set_admin_layer(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_set_rtds_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer* value) { + UPB_WRITE_ONEOF(msg, envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 5); +} +UPB_INLINE struct envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer* envoy_config_bootstrap_v3_RuntimeLayer_mutable_rtds_layer(envoy_config_bootstrap_v3_RuntimeLayer *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer* sub = (struct envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer*)envoy_config_bootstrap_v3_RuntimeLayer_rtds_layer(msg); + if (sub == NULL) { + sub = (struct envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer*)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_RuntimeLayer_set_rtds_layer(msg, sub); + } + return sub; +} + +/* envoy.config.bootstrap.v3.RuntimeLayer.DiskLayer */ + +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_serialize(const envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_symlink_root(const envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_append_service_cluster(const envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool); } +UPB_INLINE upb_strview envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_subdirectory(const envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } + +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_set_symlink_root(envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_set_append_service_cluster(envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *msg, bool value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), bool) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_set_subdirectory(envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} + +/* envoy.config.bootstrap.v3.RuntimeLayer.AdminLayer */ + +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer *envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer *)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer *envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer *envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_serialize(const envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit, arena, len); +} + + + +/* envoy.config.bootstrap.v3.RuntimeLayer.RtdsLayer */ + +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *ret = envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_serialize(const envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_name(const envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_has_rtds_config(const envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_rtds_config(const envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct envoy_config_core_v3_ConfigSource*); } + +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_set_name(envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_set_rtds_config(envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *msg, struct envoy_config_core_v3_ConfigSource* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct envoy_config_core_v3_ConfigSource*) = value; +} +UPB_INLINE struct envoy_config_core_v3_ConfigSource* envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_mutable_rtds_config(envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer *msg, upb_arena *arena) { + struct envoy_config_core_v3_ConfigSource* sub = (struct envoy_config_core_v3_ConfigSource*)envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_rtds_config(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_ConfigSource*)_upb_msg_new(&envoy_config_core_v3_ConfigSource_msginit, arena); + if (!sub) return NULL; + envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_set_rtds_config(msg, sub); + } + return sub; +} + +/* envoy.config.bootstrap.v3.LayeredRuntime */ + +UPB_INLINE envoy_config_bootstrap_v3_LayeredRuntime *envoy_config_bootstrap_v3_LayeredRuntime_new(upb_arena *arena) { + return (envoy_config_bootstrap_v3_LayeredRuntime *)_upb_msg_new(&envoy_config_bootstrap_v3_LayeredRuntime_msginit, arena); +} +UPB_INLINE envoy_config_bootstrap_v3_LayeredRuntime *envoy_config_bootstrap_v3_LayeredRuntime_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_bootstrap_v3_LayeredRuntime *ret = envoy_config_bootstrap_v3_LayeredRuntime_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_LayeredRuntime_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_bootstrap_v3_LayeredRuntime *envoy_config_bootstrap_v3_LayeredRuntime_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_bootstrap_v3_LayeredRuntime *ret = envoy_config_bootstrap_v3_LayeredRuntime_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_bootstrap_v3_LayeredRuntime_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_bootstrap_v3_LayeredRuntime_serialize(const envoy_config_bootstrap_v3_LayeredRuntime *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_bootstrap_v3_LayeredRuntime_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_bootstrap_v3_LayeredRuntime_has_layers(const envoy_config_bootstrap_v3_LayeredRuntime *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const envoy_config_bootstrap_v3_RuntimeLayer* const* envoy_config_bootstrap_v3_LayeredRuntime_layers(const envoy_config_bootstrap_v3_LayeredRuntime *msg, size_t *len) { return (const envoy_config_bootstrap_v3_RuntimeLayer* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer** envoy_config_bootstrap_v3_LayeredRuntime_mutable_layers(envoy_config_bootstrap_v3_LayeredRuntime *msg, size_t *len) { + return (envoy_config_bootstrap_v3_RuntimeLayer**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE envoy_config_bootstrap_v3_RuntimeLayer** envoy_config_bootstrap_v3_LayeredRuntime_resize_layers(envoy_config_bootstrap_v3_LayeredRuntime *msg, size_t len, upb_arena *arena) { + return (envoy_config_bootstrap_v3_RuntimeLayer**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_bootstrap_v3_RuntimeLayer* envoy_config_bootstrap_v3_LayeredRuntime_add_layers(envoy_config_bootstrap_v3_LayeredRuntime *msg, upb_arena *arena) { + struct envoy_config_bootstrap_v3_RuntimeLayer* sub = (struct envoy_config_bootstrap_v3_RuntimeLayer*)_upb_msg_new(&envoy_config_bootstrap_v3_RuntimeLayer_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_CONFIG_BOOTSTRAP_V3_BOOTSTRAP_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c b/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c new file mode 100644 index 00000000000..26d00f14ea8 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c @@ -0,0 +1,144 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/metrics/v3/stats.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/config/metrics/v3/stats.upb.h" +#include "envoy/config/core/v3/address.upb.h" +#include "envoy/type/matcher/v3/string.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_config_metrics_v3_StatsSink_submsgs[1] = { + &google_protobuf_Any_msginit, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_StatsSink__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1}, +}; + +const upb_msglayout envoy_config_metrics_v3_StatsSink_msginit = { + &envoy_config_metrics_v3_StatsSink_submsgs[0], + &envoy_config_metrics_v3_StatsSink__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_metrics_v3_StatsConfig_submsgs[4] = { + &envoy_config_metrics_v3_HistogramBucketSettings_msginit, + &envoy_config_metrics_v3_StatsMatcher_msginit, + &envoy_config_metrics_v3_TagSpecifier_msginit, + &google_protobuf_BoolValue_msginit, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_StatsConfig__fields[4] = { + {1, UPB_SIZE(12, 24), 0, 2, 11, 3}, + {2, UPB_SIZE(4, 8), 1, 3, 11, 1}, + {3, UPB_SIZE(8, 16), 2, 1, 11, 1}, + {4, UPB_SIZE(16, 32), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_config_metrics_v3_StatsConfig_msginit = { + &envoy_config_metrics_v3_StatsConfig_submsgs[0], + &envoy_config_metrics_v3_StatsConfig__fields[0], + UPB_SIZE(24, 40), 4, false, 255, +}; + +static const upb_msglayout *const envoy_config_metrics_v3_StatsMatcher_submsgs[1] = { + &envoy_type_matcher_v3_ListStringMatcher_msginit, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_StatsMatcher__fields[3] = { + {1, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 0, 8, 1}, + {2, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 0, 11, 1}, + {3, UPB_SIZE(0, 0), UPB_SIZE(-5, -9), 0, 11, 1}, +}; + +const upb_msglayout envoy_config_metrics_v3_StatsMatcher_msginit = { + &envoy_config_metrics_v3_StatsMatcher_submsgs[0], + &envoy_config_metrics_v3_StatsMatcher__fields[0], + UPB_SIZE(8, 16), 3, false, 255, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_TagSpecifier__fields[3] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {2, UPB_SIZE(8, 16), UPB_SIZE(-17, -33), 0, 9, 1}, + {3, UPB_SIZE(8, 16), UPB_SIZE(-17, -33), 0, 9, 1}, +}; + +const upb_msglayout envoy_config_metrics_v3_TagSpecifier_msginit = { + NULL, + &envoy_config_metrics_v3_TagSpecifier__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const envoy_config_metrics_v3_HistogramBucketSettings_submsgs[1] = { + &envoy_type_matcher_v3_StringMatcher_msginit, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_HistogramBucketSettings__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 0, 0, 1, _UPB_LABEL_PACKED}, +}; + +const upb_msglayout envoy_config_metrics_v3_HistogramBucketSettings_msginit = { + &envoy_config_metrics_v3_HistogramBucketSettings_submsgs[0], + &envoy_config_metrics_v3_HistogramBucketSettings__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_metrics_v3_StatsdSink_submsgs[1] = { + &envoy_config_core_v3_Address_msginit, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_StatsdSink__fields[3] = { + {1, UPB_SIZE(8, 16), UPB_SIZE(-17, -33), 0, 11, 1}, + {2, UPB_SIZE(8, 16), UPB_SIZE(-17, -33), 0, 9, 1}, + {3, UPB_SIZE(0, 0), 0, 0, 9, 1}, +}; + +const upb_msglayout envoy_config_metrics_v3_StatsdSink_msginit = { + &envoy_config_metrics_v3_StatsdSink_submsgs[0], + &envoy_config_metrics_v3_StatsdSink__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const envoy_config_metrics_v3_DogStatsdSink_submsgs[2] = { + &envoy_config_core_v3_Address_msginit, + &google_protobuf_UInt64Value_msginit, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_DogStatsdSink__fields[3] = { + {1, UPB_SIZE(16, 32), UPB_SIZE(-21, -41), 0, 11, 1}, + {3, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {4, UPB_SIZE(12, 24), 1, 1, 11, 1}, +}; + +const upb_msglayout envoy_config_metrics_v3_DogStatsdSink_msginit = { + &envoy_config_metrics_v3_DogStatsdSink_submsgs[0], + &envoy_config_metrics_v3_DogStatsdSink__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout_field envoy_config_metrics_v3_HystrixSink__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 3, 1}, +}; + +const upb_msglayout envoy_config_metrics_v3_HystrixSink_msginit = { + NULL, + &envoy_config_metrics_v3_HystrixSink__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h b/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h new file mode 100644 index 00000000000..dab0415ed60 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h @@ -0,0 +1,488 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/metrics/v3/stats.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_CONFIG_METRICS_V3_STATS_PROTO_UPB_H_ +#define ENVOY_CONFIG_METRICS_V3_STATS_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_config_metrics_v3_StatsSink; +struct envoy_config_metrics_v3_StatsConfig; +struct envoy_config_metrics_v3_StatsMatcher; +struct envoy_config_metrics_v3_TagSpecifier; +struct envoy_config_metrics_v3_HistogramBucketSettings; +struct envoy_config_metrics_v3_StatsdSink; +struct envoy_config_metrics_v3_DogStatsdSink; +struct envoy_config_metrics_v3_HystrixSink; +typedef struct envoy_config_metrics_v3_StatsSink envoy_config_metrics_v3_StatsSink; +typedef struct envoy_config_metrics_v3_StatsConfig envoy_config_metrics_v3_StatsConfig; +typedef struct envoy_config_metrics_v3_StatsMatcher envoy_config_metrics_v3_StatsMatcher; +typedef struct envoy_config_metrics_v3_TagSpecifier envoy_config_metrics_v3_TagSpecifier; +typedef struct envoy_config_metrics_v3_HistogramBucketSettings envoy_config_metrics_v3_HistogramBucketSettings; +typedef struct envoy_config_metrics_v3_StatsdSink envoy_config_metrics_v3_StatsdSink; +typedef struct envoy_config_metrics_v3_DogStatsdSink envoy_config_metrics_v3_DogStatsdSink; +typedef struct envoy_config_metrics_v3_HystrixSink envoy_config_metrics_v3_HystrixSink; +extern const upb_msglayout envoy_config_metrics_v3_StatsSink_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsConfig_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsMatcher_msginit; +extern const upb_msglayout envoy_config_metrics_v3_TagSpecifier_msginit; +extern const upb_msglayout envoy_config_metrics_v3_HistogramBucketSettings_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsdSink_msginit; +extern const upb_msglayout envoy_config_metrics_v3_DogStatsdSink_msginit; +extern const upb_msglayout envoy_config_metrics_v3_HystrixSink_msginit; +struct envoy_config_core_v3_Address; +struct envoy_type_matcher_v3_ListStringMatcher; +struct envoy_type_matcher_v3_StringMatcher; +struct google_protobuf_Any; +struct google_protobuf_BoolValue; +struct google_protobuf_UInt64Value; +extern const upb_msglayout envoy_config_core_v3_Address_msginit; +extern const upb_msglayout envoy_type_matcher_v3_ListStringMatcher_msginit; +extern const upb_msglayout envoy_type_matcher_v3_StringMatcher_msginit; +extern const upb_msglayout google_protobuf_Any_msginit; +extern const upb_msglayout google_protobuf_BoolValue_msginit; +extern const upb_msglayout google_protobuf_UInt64Value_msginit; + + +/* envoy.config.metrics.v3.StatsSink */ + +UPB_INLINE envoy_config_metrics_v3_StatsSink *envoy_config_metrics_v3_StatsSink_new(upb_arena *arena) { + return (envoy_config_metrics_v3_StatsSink *)_upb_msg_new(&envoy_config_metrics_v3_StatsSink_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_StatsSink *envoy_config_metrics_v3_StatsSink_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_StatsSink *ret = envoy_config_metrics_v3_StatsSink_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsSink_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_StatsSink *envoy_config_metrics_v3_StatsSink_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_StatsSink *ret = envoy_config_metrics_v3_StatsSink_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsSink_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_StatsSink_serialize(const envoy_config_metrics_v3_StatsSink *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_StatsSink_msginit, arena, len); +} + +typedef enum { + envoy_config_metrics_v3_StatsSink_config_type_typed_config = 3, + envoy_config_metrics_v3_StatsSink_config_type_NOT_SET = 0 +} envoy_config_metrics_v3_StatsSink_config_type_oneofcases; +UPB_INLINE envoy_config_metrics_v3_StatsSink_config_type_oneofcases envoy_config_metrics_v3_StatsSink_config_type_case(const envoy_config_metrics_v3_StatsSink* msg) { return (envoy_config_metrics_v3_StatsSink_config_type_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 24), int32_t); } + +UPB_INLINE upb_strview envoy_config_metrics_v3_StatsSink_name(const envoy_config_metrics_v3_StatsSink *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } +UPB_INLINE bool envoy_config_metrics_v3_StatsSink_has_typed_config(const envoy_config_metrics_v3_StatsSink *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 3; } +UPB_INLINE const struct google_protobuf_Any* envoy_config_metrics_v3_StatsSink_typed_config(const envoy_config_metrics_v3_StatsSink *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Any*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); } + +UPB_INLINE void envoy_config_metrics_v3_StatsSink_set_name(envoy_config_metrics_v3_StatsSink *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} +UPB_INLINE void envoy_config_metrics_v3_StatsSink_set_typed_config(envoy_config_metrics_v3_StatsSink *msg, struct google_protobuf_Any* value) { + UPB_WRITE_ONEOF(msg, struct google_protobuf_Any*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3); +} +UPB_INLINE struct google_protobuf_Any* envoy_config_metrics_v3_StatsSink_mutable_typed_config(envoy_config_metrics_v3_StatsSink *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_config_metrics_v3_StatsSink_typed_config(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_StatsSink_set_typed_config(msg, sub); + } + return sub; +} + +/* envoy.config.metrics.v3.StatsConfig */ + +UPB_INLINE envoy_config_metrics_v3_StatsConfig *envoy_config_metrics_v3_StatsConfig_new(upb_arena *arena) { + return (envoy_config_metrics_v3_StatsConfig *)_upb_msg_new(&envoy_config_metrics_v3_StatsConfig_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_StatsConfig *envoy_config_metrics_v3_StatsConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_StatsConfig *ret = envoy_config_metrics_v3_StatsConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_StatsConfig *envoy_config_metrics_v3_StatsConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_StatsConfig *ret = envoy_config_metrics_v3_StatsConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_StatsConfig_serialize(const envoy_config_metrics_v3_StatsConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_StatsConfig_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_metrics_v3_StatsConfig_has_stats_tags(const envoy_config_metrics_v3_StatsConfig *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 24)); } +UPB_INLINE const envoy_config_metrics_v3_TagSpecifier* const* envoy_config_metrics_v3_StatsConfig_stats_tags(const envoy_config_metrics_v3_StatsConfig *msg, size_t *len) { return (const envoy_config_metrics_v3_TagSpecifier* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); } +UPB_INLINE bool envoy_config_metrics_v3_StatsConfig_has_use_all_default_tags(const envoy_config_metrics_v3_StatsConfig *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_BoolValue* envoy_config_metrics_v3_StatsConfig_use_all_default_tags(const envoy_config_metrics_v3_StatsConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_BoolValue*); } +UPB_INLINE bool envoy_config_metrics_v3_StatsConfig_has_stats_matcher(const envoy_config_metrics_v3_StatsConfig *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const envoy_config_metrics_v3_StatsMatcher* envoy_config_metrics_v3_StatsConfig_stats_matcher(const envoy_config_metrics_v3_StatsConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 16), const envoy_config_metrics_v3_StatsMatcher*); } +UPB_INLINE bool envoy_config_metrics_v3_StatsConfig_has_histogram_bucket_settings(const envoy_config_metrics_v3_StatsConfig *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const envoy_config_metrics_v3_HistogramBucketSettings* const* envoy_config_metrics_v3_StatsConfig_histogram_bucket_settings(const envoy_config_metrics_v3_StatsConfig *msg, size_t *len) { return (const envoy_config_metrics_v3_HistogramBucketSettings* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } + +UPB_INLINE envoy_config_metrics_v3_TagSpecifier** envoy_config_metrics_v3_StatsConfig_mutable_stats_tags(envoy_config_metrics_v3_StatsConfig *msg, size_t *len) { + return (envoy_config_metrics_v3_TagSpecifier**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len); +} +UPB_INLINE envoy_config_metrics_v3_TagSpecifier** envoy_config_metrics_v3_StatsConfig_resize_stats_tags(envoy_config_metrics_v3_StatsConfig *msg, size_t len, upb_arena *arena) { + return (envoy_config_metrics_v3_TagSpecifier**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_metrics_v3_TagSpecifier* envoy_config_metrics_v3_StatsConfig_add_stats_tags(envoy_config_metrics_v3_StatsConfig *msg, upb_arena *arena) { + struct envoy_config_metrics_v3_TagSpecifier* sub = (struct envoy_config_metrics_v3_TagSpecifier*)_upb_msg_new(&envoy_config_metrics_v3_TagSpecifier_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(12, 24), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_config_metrics_v3_StatsConfig_set_use_all_default_tags(envoy_config_metrics_v3_StatsConfig *msg, struct google_protobuf_BoolValue* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_BoolValue*) = value; +} +UPB_INLINE struct google_protobuf_BoolValue* envoy_config_metrics_v3_StatsConfig_mutable_use_all_default_tags(envoy_config_metrics_v3_StatsConfig *msg, upb_arena *arena) { + struct google_protobuf_BoolValue* sub = (struct google_protobuf_BoolValue*)envoy_config_metrics_v3_StatsConfig_use_all_default_tags(msg); + if (sub == NULL) { + sub = (struct google_protobuf_BoolValue*)_upb_msg_new(&google_protobuf_BoolValue_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_StatsConfig_set_use_all_default_tags(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_metrics_v3_StatsConfig_set_stats_matcher(envoy_config_metrics_v3_StatsConfig *msg, envoy_config_metrics_v3_StatsMatcher* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(8, 16), envoy_config_metrics_v3_StatsMatcher*) = value; +} +UPB_INLINE struct envoy_config_metrics_v3_StatsMatcher* envoy_config_metrics_v3_StatsConfig_mutable_stats_matcher(envoy_config_metrics_v3_StatsConfig *msg, upb_arena *arena) { + struct envoy_config_metrics_v3_StatsMatcher* sub = (struct envoy_config_metrics_v3_StatsMatcher*)envoy_config_metrics_v3_StatsConfig_stats_matcher(msg); + if (sub == NULL) { + sub = (struct envoy_config_metrics_v3_StatsMatcher*)_upb_msg_new(&envoy_config_metrics_v3_StatsMatcher_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_StatsConfig_set_stats_matcher(msg, sub); + } + return sub; +} +UPB_INLINE envoy_config_metrics_v3_HistogramBucketSettings** envoy_config_metrics_v3_StatsConfig_mutable_histogram_bucket_settings(envoy_config_metrics_v3_StatsConfig *msg, size_t *len) { + return (envoy_config_metrics_v3_HistogramBucketSettings**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE envoy_config_metrics_v3_HistogramBucketSettings** envoy_config_metrics_v3_StatsConfig_resize_histogram_bucket_settings(envoy_config_metrics_v3_StatsConfig *msg, size_t len, upb_arena *arena) { + return (envoy_config_metrics_v3_HistogramBucketSettings**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_metrics_v3_HistogramBucketSettings* envoy_config_metrics_v3_StatsConfig_add_histogram_bucket_settings(envoy_config_metrics_v3_StatsConfig *msg, upb_arena *arena) { + struct envoy_config_metrics_v3_HistogramBucketSettings* sub = (struct envoy_config_metrics_v3_HistogramBucketSettings*)_upb_msg_new(&envoy_config_metrics_v3_HistogramBucketSettings_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.config.metrics.v3.StatsMatcher */ + +UPB_INLINE envoy_config_metrics_v3_StatsMatcher *envoy_config_metrics_v3_StatsMatcher_new(upb_arena *arena) { + return (envoy_config_metrics_v3_StatsMatcher *)_upb_msg_new(&envoy_config_metrics_v3_StatsMatcher_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_StatsMatcher *envoy_config_metrics_v3_StatsMatcher_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_StatsMatcher *ret = envoy_config_metrics_v3_StatsMatcher_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsMatcher_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_StatsMatcher *envoy_config_metrics_v3_StatsMatcher_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_StatsMatcher *ret = envoy_config_metrics_v3_StatsMatcher_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsMatcher_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_StatsMatcher_serialize(const envoy_config_metrics_v3_StatsMatcher *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_StatsMatcher_msginit, arena, len); +} + +typedef enum { + envoy_config_metrics_v3_StatsMatcher_stats_matcher_reject_all = 1, + envoy_config_metrics_v3_StatsMatcher_stats_matcher_exclusion_list = 2, + envoy_config_metrics_v3_StatsMatcher_stats_matcher_inclusion_list = 3, + envoy_config_metrics_v3_StatsMatcher_stats_matcher_NOT_SET = 0 +} envoy_config_metrics_v3_StatsMatcher_stats_matcher_oneofcases; +UPB_INLINE envoy_config_metrics_v3_StatsMatcher_stats_matcher_oneofcases envoy_config_metrics_v3_StatsMatcher_stats_matcher_case(const envoy_config_metrics_v3_StatsMatcher* msg) { return (envoy_config_metrics_v3_StatsMatcher_stats_matcher_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(4, 8), int32_t); } + +UPB_INLINE bool envoy_config_metrics_v3_StatsMatcher_has_reject_all(const envoy_config_metrics_v3_StatsMatcher *msg) { return _upb_getoneofcase(msg, UPB_SIZE(4, 8)) == 1; } +UPB_INLINE bool envoy_config_metrics_v3_StatsMatcher_reject_all(const envoy_config_metrics_v3_StatsMatcher *msg) { return UPB_READ_ONEOF(msg, bool, UPB_SIZE(0, 0), UPB_SIZE(4, 8), 1, false); } +UPB_INLINE bool envoy_config_metrics_v3_StatsMatcher_has_exclusion_list(const envoy_config_metrics_v3_StatsMatcher *msg) { return _upb_getoneofcase(msg, UPB_SIZE(4, 8)) == 2; } +UPB_INLINE const struct envoy_type_matcher_v3_ListStringMatcher* envoy_config_metrics_v3_StatsMatcher_exclusion_list(const envoy_config_metrics_v3_StatsMatcher *msg) { return UPB_READ_ONEOF(msg, const struct envoy_type_matcher_v3_ListStringMatcher*, UPB_SIZE(0, 0), UPB_SIZE(4, 8), 2, NULL); } +UPB_INLINE bool envoy_config_metrics_v3_StatsMatcher_has_inclusion_list(const envoy_config_metrics_v3_StatsMatcher *msg) { return _upb_getoneofcase(msg, UPB_SIZE(4, 8)) == 3; } +UPB_INLINE const struct envoy_type_matcher_v3_ListStringMatcher* envoy_config_metrics_v3_StatsMatcher_inclusion_list(const envoy_config_metrics_v3_StatsMatcher *msg) { return UPB_READ_ONEOF(msg, const struct envoy_type_matcher_v3_ListStringMatcher*, UPB_SIZE(0, 0), UPB_SIZE(4, 8), 3, NULL); } + +UPB_INLINE void envoy_config_metrics_v3_StatsMatcher_set_reject_all(envoy_config_metrics_v3_StatsMatcher *msg, bool value) { + UPB_WRITE_ONEOF(msg, bool, UPB_SIZE(0, 0), value, UPB_SIZE(4, 8), 1); +} +UPB_INLINE void envoy_config_metrics_v3_StatsMatcher_set_exclusion_list(envoy_config_metrics_v3_StatsMatcher *msg, struct envoy_type_matcher_v3_ListStringMatcher* value) { + UPB_WRITE_ONEOF(msg, struct envoy_type_matcher_v3_ListStringMatcher*, UPB_SIZE(0, 0), value, UPB_SIZE(4, 8), 2); +} +UPB_INLINE struct envoy_type_matcher_v3_ListStringMatcher* envoy_config_metrics_v3_StatsMatcher_mutable_exclusion_list(envoy_config_metrics_v3_StatsMatcher *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_ListStringMatcher* sub = (struct envoy_type_matcher_v3_ListStringMatcher*)envoy_config_metrics_v3_StatsMatcher_exclusion_list(msg); + if (sub == NULL) { + sub = (struct envoy_type_matcher_v3_ListStringMatcher*)_upb_msg_new(&envoy_type_matcher_v3_ListStringMatcher_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_StatsMatcher_set_exclusion_list(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_metrics_v3_StatsMatcher_set_inclusion_list(envoy_config_metrics_v3_StatsMatcher *msg, struct envoy_type_matcher_v3_ListStringMatcher* value) { + UPB_WRITE_ONEOF(msg, struct envoy_type_matcher_v3_ListStringMatcher*, UPB_SIZE(0, 0), value, UPB_SIZE(4, 8), 3); +} +UPB_INLINE struct envoy_type_matcher_v3_ListStringMatcher* envoy_config_metrics_v3_StatsMatcher_mutable_inclusion_list(envoy_config_metrics_v3_StatsMatcher *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_ListStringMatcher* sub = (struct envoy_type_matcher_v3_ListStringMatcher*)envoy_config_metrics_v3_StatsMatcher_inclusion_list(msg); + if (sub == NULL) { + sub = (struct envoy_type_matcher_v3_ListStringMatcher*)_upb_msg_new(&envoy_type_matcher_v3_ListStringMatcher_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_StatsMatcher_set_inclusion_list(msg, sub); + } + return sub; +} + +/* envoy.config.metrics.v3.TagSpecifier */ + +UPB_INLINE envoy_config_metrics_v3_TagSpecifier *envoy_config_metrics_v3_TagSpecifier_new(upb_arena *arena) { + return (envoy_config_metrics_v3_TagSpecifier *)_upb_msg_new(&envoy_config_metrics_v3_TagSpecifier_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_TagSpecifier *envoy_config_metrics_v3_TagSpecifier_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_TagSpecifier *ret = envoy_config_metrics_v3_TagSpecifier_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_TagSpecifier_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_TagSpecifier *envoy_config_metrics_v3_TagSpecifier_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_TagSpecifier *ret = envoy_config_metrics_v3_TagSpecifier_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_TagSpecifier_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_TagSpecifier_serialize(const envoy_config_metrics_v3_TagSpecifier *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_TagSpecifier_msginit, arena, len); +} + +typedef enum { + envoy_config_metrics_v3_TagSpecifier_tag_value_regex = 2, + envoy_config_metrics_v3_TagSpecifier_tag_value_fixed_value = 3, + envoy_config_metrics_v3_TagSpecifier_tag_value_NOT_SET = 0 +} envoy_config_metrics_v3_TagSpecifier_tag_value_oneofcases; +UPB_INLINE envoy_config_metrics_v3_TagSpecifier_tag_value_oneofcases envoy_config_metrics_v3_TagSpecifier_tag_value_case(const envoy_config_metrics_v3_TagSpecifier* msg) { return (envoy_config_metrics_v3_TagSpecifier_tag_value_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(16, 32), int32_t); } + +UPB_INLINE upb_strview envoy_config_metrics_v3_TagSpecifier_tag_name(const envoy_config_metrics_v3_TagSpecifier *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } +UPB_INLINE bool envoy_config_metrics_v3_TagSpecifier_has_regex(const envoy_config_metrics_v3_TagSpecifier *msg) { return _upb_getoneofcase(msg, UPB_SIZE(16, 32)) == 2; } +UPB_INLINE upb_strview envoy_config_metrics_v3_TagSpecifier_regex(const envoy_config_metrics_v3_TagSpecifier *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(8, 16), UPB_SIZE(16, 32), 2, upb_strview_make("", strlen(""))); } +UPB_INLINE bool envoy_config_metrics_v3_TagSpecifier_has_fixed_value(const envoy_config_metrics_v3_TagSpecifier *msg) { return _upb_getoneofcase(msg, UPB_SIZE(16, 32)) == 3; } +UPB_INLINE upb_strview envoy_config_metrics_v3_TagSpecifier_fixed_value(const envoy_config_metrics_v3_TagSpecifier *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(8, 16), UPB_SIZE(16, 32), 3, upb_strview_make("", strlen(""))); } + +UPB_INLINE void envoy_config_metrics_v3_TagSpecifier_set_tag_name(envoy_config_metrics_v3_TagSpecifier *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} +UPB_INLINE void envoy_config_metrics_v3_TagSpecifier_set_regex(envoy_config_metrics_v3_TagSpecifier *msg, upb_strview value) { + UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(8, 16), value, UPB_SIZE(16, 32), 2); +} +UPB_INLINE void envoy_config_metrics_v3_TagSpecifier_set_fixed_value(envoy_config_metrics_v3_TagSpecifier *msg, upb_strview value) { + UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(8, 16), value, UPB_SIZE(16, 32), 3); +} + +/* envoy.config.metrics.v3.HistogramBucketSettings */ + +UPB_INLINE envoy_config_metrics_v3_HistogramBucketSettings *envoy_config_metrics_v3_HistogramBucketSettings_new(upb_arena *arena) { + return (envoy_config_metrics_v3_HistogramBucketSettings *)_upb_msg_new(&envoy_config_metrics_v3_HistogramBucketSettings_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_HistogramBucketSettings *envoy_config_metrics_v3_HistogramBucketSettings_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_HistogramBucketSettings *ret = envoy_config_metrics_v3_HistogramBucketSettings_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_HistogramBucketSettings_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_HistogramBucketSettings *envoy_config_metrics_v3_HistogramBucketSettings_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_HistogramBucketSettings *ret = envoy_config_metrics_v3_HistogramBucketSettings_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_HistogramBucketSettings_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_HistogramBucketSettings_serialize(const envoy_config_metrics_v3_HistogramBucketSettings *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_HistogramBucketSettings_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_metrics_v3_HistogramBucketSettings_has_match(const envoy_config_metrics_v3_HistogramBucketSettings *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_type_matcher_v3_StringMatcher* envoy_config_metrics_v3_HistogramBucketSettings_match(const envoy_config_metrics_v3_HistogramBucketSettings *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_type_matcher_v3_StringMatcher*); } +UPB_INLINE double const* envoy_config_metrics_v3_HistogramBucketSettings_buckets(const envoy_config_metrics_v3_HistogramBucketSettings *msg, size_t *len) { return (double const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } + +UPB_INLINE void envoy_config_metrics_v3_HistogramBucketSettings_set_match(envoy_config_metrics_v3_HistogramBucketSettings *msg, struct envoy_type_matcher_v3_StringMatcher* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_type_matcher_v3_StringMatcher*) = value; +} +UPB_INLINE struct envoy_type_matcher_v3_StringMatcher* envoy_config_metrics_v3_HistogramBucketSettings_mutable_match(envoy_config_metrics_v3_HistogramBucketSettings *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_StringMatcher* sub = (struct envoy_type_matcher_v3_StringMatcher*)envoy_config_metrics_v3_HistogramBucketSettings_match(msg); + if (sub == NULL) { + sub = (struct envoy_type_matcher_v3_StringMatcher*)_upb_msg_new(&envoy_type_matcher_v3_StringMatcher_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_HistogramBucketSettings_set_match(msg, sub); + } + return sub; +} +UPB_INLINE double* envoy_config_metrics_v3_HistogramBucketSettings_mutable_buckets(envoy_config_metrics_v3_HistogramBucketSettings *msg, size_t *len) { + return (double*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE double* envoy_config_metrics_v3_HistogramBucketSettings_resize_buckets(envoy_config_metrics_v3_HistogramBucketSettings *msg, size_t len, upb_arena *arena) { + return (double*)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, 3, arena); +} +UPB_INLINE bool envoy_config_metrics_v3_HistogramBucketSettings_add_buckets(envoy_config_metrics_v3_HistogramBucketSettings *msg, double val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(8, 16), 3, &val, + arena); +} + +/* envoy.config.metrics.v3.StatsdSink */ + +UPB_INLINE envoy_config_metrics_v3_StatsdSink *envoy_config_metrics_v3_StatsdSink_new(upb_arena *arena) { + return (envoy_config_metrics_v3_StatsdSink *)_upb_msg_new(&envoy_config_metrics_v3_StatsdSink_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_StatsdSink *envoy_config_metrics_v3_StatsdSink_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_StatsdSink *ret = envoy_config_metrics_v3_StatsdSink_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsdSink_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_StatsdSink *envoy_config_metrics_v3_StatsdSink_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_StatsdSink *ret = envoy_config_metrics_v3_StatsdSink_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_StatsdSink_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_StatsdSink_serialize(const envoy_config_metrics_v3_StatsdSink *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_StatsdSink_msginit, arena, len); +} + +typedef enum { + envoy_config_metrics_v3_StatsdSink_statsd_specifier_address = 1, + envoy_config_metrics_v3_StatsdSink_statsd_specifier_tcp_cluster_name = 2, + envoy_config_metrics_v3_StatsdSink_statsd_specifier_NOT_SET = 0 +} envoy_config_metrics_v3_StatsdSink_statsd_specifier_oneofcases; +UPB_INLINE envoy_config_metrics_v3_StatsdSink_statsd_specifier_oneofcases envoy_config_metrics_v3_StatsdSink_statsd_specifier_case(const envoy_config_metrics_v3_StatsdSink* msg) { return (envoy_config_metrics_v3_StatsdSink_statsd_specifier_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(16, 32), int32_t); } + +UPB_INLINE bool envoy_config_metrics_v3_StatsdSink_has_address(const envoy_config_metrics_v3_StatsdSink *msg) { return _upb_getoneofcase(msg, UPB_SIZE(16, 32)) == 1; } +UPB_INLINE const struct envoy_config_core_v3_Address* envoy_config_metrics_v3_StatsdSink_address(const envoy_config_metrics_v3_StatsdSink *msg) { return UPB_READ_ONEOF(msg, const struct envoy_config_core_v3_Address*, UPB_SIZE(8, 16), UPB_SIZE(16, 32), 1, NULL); } +UPB_INLINE bool envoy_config_metrics_v3_StatsdSink_has_tcp_cluster_name(const envoy_config_metrics_v3_StatsdSink *msg) { return _upb_getoneofcase(msg, UPB_SIZE(16, 32)) == 2; } +UPB_INLINE upb_strview envoy_config_metrics_v3_StatsdSink_tcp_cluster_name(const envoy_config_metrics_v3_StatsdSink *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(8, 16), UPB_SIZE(16, 32), 2, upb_strview_make("", strlen(""))); } +UPB_INLINE upb_strview envoy_config_metrics_v3_StatsdSink_prefix(const envoy_config_metrics_v3_StatsdSink *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } + +UPB_INLINE void envoy_config_metrics_v3_StatsdSink_set_address(envoy_config_metrics_v3_StatsdSink *msg, struct envoy_config_core_v3_Address* value) { + UPB_WRITE_ONEOF(msg, struct envoy_config_core_v3_Address*, UPB_SIZE(8, 16), value, UPB_SIZE(16, 32), 1); +} +UPB_INLINE struct envoy_config_core_v3_Address* envoy_config_metrics_v3_StatsdSink_mutable_address(envoy_config_metrics_v3_StatsdSink *msg, upb_arena *arena) { + struct envoy_config_core_v3_Address* sub = (struct envoy_config_core_v3_Address*)envoy_config_metrics_v3_StatsdSink_address(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_Address*)_upb_msg_new(&envoy_config_core_v3_Address_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_StatsdSink_set_address(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_metrics_v3_StatsdSink_set_tcp_cluster_name(envoy_config_metrics_v3_StatsdSink *msg, upb_strview value) { + UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(8, 16), value, UPB_SIZE(16, 32), 2); +} +UPB_INLINE void envoy_config_metrics_v3_StatsdSink_set_prefix(envoy_config_metrics_v3_StatsdSink *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} + +/* envoy.config.metrics.v3.DogStatsdSink */ + +UPB_INLINE envoy_config_metrics_v3_DogStatsdSink *envoy_config_metrics_v3_DogStatsdSink_new(upb_arena *arena) { + return (envoy_config_metrics_v3_DogStatsdSink *)_upb_msg_new(&envoy_config_metrics_v3_DogStatsdSink_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_DogStatsdSink *envoy_config_metrics_v3_DogStatsdSink_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_DogStatsdSink *ret = envoy_config_metrics_v3_DogStatsdSink_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_DogStatsdSink_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_DogStatsdSink *envoy_config_metrics_v3_DogStatsdSink_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_DogStatsdSink *ret = envoy_config_metrics_v3_DogStatsdSink_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_DogStatsdSink_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_DogStatsdSink_serialize(const envoy_config_metrics_v3_DogStatsdSink *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_DogStatsdSink_msginit, arena, len); +} + +typedef enum { + envoy_config_metrics_v3_DogStatsdSink_dog_statsd_specifier_address = 1, + envoy_config_metrics_v3_DogStatsdSink_dog_statsd_specifier_NOT_SET = 0 +} envoy_config_metrics_v3_DogStatsdSink_dog_statsd_specifier_oneofcases; +UPB_INLINE envoy_config_metrics_v3_DogStatsdSink_dog_statsd_specifier_oneofcases envoy_config_metrics_v3_DogStatsdSink_dog_statsd_specifier_case(const envoy_config_metrics_v3_DogStatsdSink* msg) { return (envoy_config_metrics_v3_DogStatsdSink_dog_statsd_specifier_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(20, 40), int32_t); } + +UPB_INLINE bool envoy_config_metrics_v3_DogStatsdSink_has_address(const envoy_config_metrics_v3_DogStatsdSink *msg) { return _upb_getoneofcase(msg, UPB_SIZE(20, 40)) == 1; } +UPB_INLINE const struct envoy_config_core_v3_Address* envoy_config_metrics_v3_DogStatsdSink_address(const envoy_config_metrics_v3_DogStatsdSink *msg) { return UPB_READ_ONEOF(msg, const struct envoy_config_core_v3_Address*, UPB_SIZE(16, 32), UPB_SIZE(20, 40), 1, NULL); } +UPB_INLINE upb_strview envoy_config_metrics_v3_DogStatsdSink_prefix(const envoy_config_metrics_v3_DogStatsdSink *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_config_metrics_v3_DogStatsdSink_has_max_bytes_per_datagram(const envoy_config_metrics_v3_DogStatsdSink *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_UInt64Value* envoy_config_metrics_v3_DogStatsdSink_max_bytes_per_datagram(const envoy_config_metrics_v3_DogStatsdSink *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_UInt64Value*); } + +UPB_INLINE void envoy_config_metrics_v3_DogStatsdSink_set_address(envoy_config_metrics_v3_DogStatsdSink *msg, struct envoy_config_core_v3_Address* value) { + UPB_WRITE_ONEOF(msg, struct envoy_config_core_v3_Address*, UPB_SIZE(16, 32), value, UPB_SIZE(20, 40), 1); +} +UPB_INLINE struct envoy_config_core_v3_Address* envoy_config_metrics_v3_DogStatsdSink_mutable_address(envoy_config_metrics_v3_DogStatsdSink *msg, upb_arena *arena) { + struct envoy_config_core_v3_Address* sub = (struct envoy_config_core_v3_Address*)envoy_config_metrics_v3_DogStatsdSink_address(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_Address*)_upb_msg_new(&envoy_config_core_v3_Address_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_DogStatsdSink_set_address(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_metrics_v3_DogStatsdSink_set_prefix(envoy_config_metrics_v3_DogStatsdSink *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE void envoy_config_metrics_v3_DogStatsdSink_set_max_bytes_per_datagram(envoy_config_metrics_v3_DogStatsdSink *msg, struct google_protobuf_UInt64Value* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_UInt64Value*) = value; +} +UPB_INLINE struct google_protobuf_UInt64Value* envoy_config_metrics_v3_DogStatsdSink_mutable_max_bytes_per_datagram(envoy_config_metrics_v3_DogStatsdSink *msg, upb_arena *arena) { + struct google_protobuf_UInt64Value* sub = (struct google_protobuf_UInt64Value*)envoy_config_metrics_v3_DogStatsdSink_max_bytes_per_datagram(msg); + if (sub == NULL) { + sub = (struct google_protobuf_UInt64Value*)_upb_msg_new(&google_protobuf_UInt64Value_msginit, arena); + if (!sub) return NULL; + envoy_config_metrics_v3_DogStatsdSink_set_max_bytes_per_datagram(msg, sub); + } + return sub; +} + +/* envoy.config.metrics.v3.HystrixSink */ + +UPB_INLINE envoy_config_metrics_v3_HystrixSink *envoy_config_metrics_v3_HystrixSink_new(upb_arena *arena) { + return (envoy_config_metrics_v3_HystrixSink *)_upb_msg_new(&envoy_config_metrics_v3_HystrixSink_msginit, arena); +} +UPB_INLINE envoy_config_metrics_v3_HystrixSink *envoy_config_metrics_v3_HystrixSink_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_metrics_v3_HystrixSink *ret = envoy_config_metrics_v3_HystrixSink_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_metrics_v3_HystrixSink_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_metrics_v3_HystrixSink *envoy_config_metrics_v3_HystrixSink_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_metrics_v3_HystrixSink *ret = envoy_config_metrics_v3_HystrixSink_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_metrics_v3_HystrixSink_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_metrics_v3_HystrixSink_serialize(const envoy_config_metrics_v3_HystrixSink *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_metrics_v3_HystrixSink_msginit, arena, len); +} + +UPB_INLINE int64_t envoy_config_metrics_v3_HystrixSink_num_buckets(const envoy_config_metrics_v3_HystrixSink *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int64_t); } + +UPB_INLINE void envoy_config_metrics_v3_HystrixSink_set_num_buckets(envoy_config_metrics_v3_HystrixSink *msg, int64_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int64_t) = value; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_CONFIG_METRICS_V3_STATS_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c b/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c new file mode 100644 index 00000000000..a306e71e8ac --- /dev/null +++ b/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c @@ -0,0 +1,141 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/overload/v3/overload.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/config/overload/v3/overload.upb.h" +#include "envoy/type/v3/percent.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/duration.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_config_overload_v3_ResourceMonitor_submsgs[1] = { + &google_protobuf_Any_msginit, +}; + +static const upb_msglayout_field envoy_config_overload_v3_ResourceMonitor__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1}, +}; + +const upb_msglayout envoy_config_overload_v3_ResourceMonitor_msginit = { + &envoy_config_overload_v3_ResourceMonitor_submsgs[0], + &envoy_config_overload_v3_ResourceMonitor__fields[0], + UPB_SIZE(16, 32), 2, false, 255, +}; + +static const upb_msglayout_field envoy_config_overload_v3_ThresholdTrigger__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 1, 1}, +}; + +const upb_msglayout envoy_config_overload_v3_ThresholdTrigger_msginit = { + NULL, + &envoy_config_overload_v3_ThresholdTrigger__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout_field envoy_config_overload_v3_ScaledTrigger__fields[2] = { + {1, UPB_SIZE(0, 0), 0, 0, 1, 1}, + {2, UPB_SIZE(8, 8), 0, 0, 1, 1}, +}; + +const upb_msglayout envoy_config_overload_v3_ScaledTrigger_msginit = { + NULL, + &envoy_config_overload_v3_ScaledTrigger__fields[0], + UPB_SIZE(16, 16), 2, false, 255, +}; + +static const upb_msglayout *const envoy_config_overload_v3_Trigger_submsgs[2] = { + &envoy_config_overload_v3_ScaledTrigger_msginit, + &envoy_config_overload_v3_ThresholdTrigger_msginit, +}; + +static const upb_msglayout_field envoy_config_overload_v3_Trigger__fields[3] = { + {1, UPB_SIZE(0, 0), 0, 0, 9, 1}, + {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1}, + {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1}, +}; + +const upb_msglayout envoy_config_overload_v3_Trigger_msginit = { + &envoy_config_overload_v3_Trigger_submsgs[0], + &envoy_config_overload_v3_Trigger__fields[0], + UPB_SIZE(16, 32), 3, false, 255, +}; + +static const upb_msglayout *const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_submsgs[1] = { + &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit, +}; + +static const upb_msglayout_field envoy_config_overload_v3_ScaleTimersOverloadActionConfig__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit = { + &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_submsgs[0], + &envoy_config_overload_v3_ScaleTimersOverloadActionConfig__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +static const upb_msglayout *const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_submsgs[2] = { + &envoy_type_v3_Percent_msginit, + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer__fields[3] = { + {1, UPB_SIZE(0, 0), 0, 0, 14, 1}, + {2, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 1, 11, 1}, + {3, UPB_SIZE(4, 8), UPB_SIZE(-9, -17), 0, 11, 1}, +}; + +const upb_msglayout envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit = { + &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_submsgs[0], + &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer__fields[0], + UPB_SIZE(16, 24), 3, false, 255, +}; + +static const upb_msglayout *const envoy_config_overload_v3_OverloadAction_submsgs[2] = { + &envoy_config_overload_v3_Trigger_msginit, + &google_protobuf_Any_msginit, +}; + +static const upb_msglayout_field envoy_config_overload_v3_OverloadAction__fields[3] = { + {1, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {2, UPB_SIZE(16, 32), 0, 0, 11, 3}, + {3, UPB_SIZE(12, 24), 1, 1, 11, 1}, +}; + +const upb_msglayout envoy_config_overload_v3_OverloadAction_msginit = { + &envoy_config_overload_v3_OverloadAction_submsgs[0], + &envoy_config_overload_v3_OverloadAction__fields[0], + UPB_SIZE(24, 48), 3, false, 255, +}; + +static const upb_msglayout *const envoy_config_overload_v3_OverloadManager_submsgs[3] = { + &envoy_config_overload_v3_OverloadAction_msginit, + &envoy_config_overload_v3_ResourceMonitor_msginit, + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_config_overload_v3_OverloadManager__fields[3] = { + {1, UPB_SIZE(4, 8), 1, 2, 11, 1}, + {2, UPB_SIZE(8, 16), 0, 1, 11, 3}, + {3, UPB_SIZE(12, 24), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_config_overload_v3_OverloadManager_msginit = { + &envoy_config_overload_v3_OverloadManager_submsgs[0], + &envoy_config_overload_v3_OverloadManager__fields[0], + UPB_SIZE(16, 32), 3, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h b/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h new file mode 100644 index 00000000000..d800aa9736f --- /dev/null +++ b/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h @@ -0,0 +1,452 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/overload/v3/overload.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_CONFIG_OVERLOAD_V3_OVERLOAD_PROTO_UPB_H_ +#define ENVOY_CONFIG_OVERLOAD_V3_OVERLOAD_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_config_overload_v3_ResourceMonitor; +struct envoy_config_overload_v3_ThresholdTrigger; +struct envoy_config_overload_v3_ScaledTrigger; +struct envoy_config_overload_v3_Trigger; +struct envoy_config_overload_v3_ScaleTimersOverloadActionConfig; +struct envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer; +struct envoy_config_overload_v3_OverloadAction; +struct envoy_config_overload_v3_OverloadManager; +typedef struct envoy_config_overload_v3_ResourceMonitor envoy_config_overload_v3_ResourceMonitor; +typedef struct envoy_config_overload_v3_ThresholdTrigger envoy_config_overload_v3_ThresholdTrigger; +typedef struct envoy_config_overload_v3_ScaledTrigger envoy_config_overload_v3_ScaledTrigger; +typedef struct envoy_config_overload_v3_Trigger envoy_config_overload_v3_Trigger; +typedef struct envoy_config_overload_v3_ScaleTimersOverloadActionConfig envoy_config_overload_v3_ScaleTimersOverloadActionConfig; +typedef struct envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer; +typedef struct envoy_config_overload_v3_OverloadAction envoy_config_overload_v3_OverloadAction; +typedef struct envoy_config_overload_v3_OverloadManager envoy_config_overload_v3_OverloadManager; +extern const upb_msglayout envoy_config_overload_v3_ResourceMonitor_msginit; +extern const upb_msglayout envoy_config_overload_v3_ThresholdTrigger_msginit; +extern const upb_msglayout envoy_config_overload_v3_ScaledTrigger_msginit; +extern const upb_msglayout envoy_config_overload_v3_Trigger_msginit; +extern const upb_msglayout envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit; +extern const upb_msglayout envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit; +extern const upb_msglayout envoy_config_overload_v3_OverloadAction_msginit; +extern const upb_msglayout envoy_config_overload_v3_OverloadManager_msginit; +struct envoy_type_v3_Percent; +struct google_protobuf_Any; +struct google_protobuf_Duration; +extern const upb_msglayout envoy_type_v3_Percent_msginit; +extern const upb_msglayout google_protobuf_Any_msginit; +extern const upb_msglayout google_protobuf_Duration_msginit; + +typedef enum { + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_UNSPECIFIED = 0, + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_HTTP_DOWNSTREAM_CONNECTION_IDLE = 1, + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_HTTP_DOWNSTREAM_STREAM_IDLE = 2, + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_TRANSPORT_SOCKET_CONNECT = 3 +} envoy_config_overload_v3_ScaleTimersOverloadActionConfig_TimerType; + + +/* envoy.config.overload.v3.ResourceMonitor */ + +UPB_INLINE envoy_config_overload_v3_ResourceMonitor *envoy_config_overload_v3_ResourceMonitor_new(upb_arena *arena) { + return (envoy_config_overload_v3_ResourceMonitor *)_upb_msg_new(&envoy_config_overload_v3_ResourceMonitor_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_ResourceMonitor *envoy_config_overload_v3_ResourceMonitor_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_ResourceMonitor *ret = envoy_config_overload_v3_ResourceMonitor_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_ResourceMonitor_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_ResourceMonitor *envoy_config_overload_v3_ResourceMonitor_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_ResourceMonitor *ret = envoy_config_overload_v3_ResourceMonitor_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_ResourceMonitor_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_ResourceMonitor_serialize(const envoy_config_overload_v3_ResourceMonitor *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_ResourceMonitor_msginit, arena, len); +} + +typedef enum { + envoy_config_overload_v3_ResourceMonitor_config_type_typed_config = 3, + envoy_config_overload_v3_ResourceMonitor_config_type_NOT_SET = 0 +} envoy_config_overload_v3_ResourceMonitor_config_type_oneofcases; +UPB_INLINE envoy_config_overload_v3_ResourceMonitor_config_type_oneofcases envoy_config_overload_v3_ResourceMonitor_config_type_case(const envoy_config_overload_v3_ResourceMonitor* msg) { return (envoy_config_overload_v3_ResourceMonitor_config_type_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 24), int32_t); } + +UPB_INLINE upb_strview envoy_config_overload_v3_ResourceMonitor_name(const envoy_config_overload_v3_ResourceMonitor *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } +UPB_INLINE bool envoy_config_overload_v3_ResourceMonitor_has_typed_config(const envoy_config_overload_v3_ResourceMonitor *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 3; } +UPB_INLINE const struct google_protobuf_Any* envoy_config_overload_v3_ResourceMonitor_typed_config(const envoy_config_overload_v3_ResourceMonitor *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Any*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); } + +UPB_INLINE void envoy_config_overload_v3_ResourceMonitor_set_name(envoy_config_overload_v3_ResourceMonitor *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} +UPB_INLINE void envoy_config_overload_v3_ResourceMonitor_set_typed_config(envoy_config_overload_v3_ResourceMonitor *msg, struct google_protobuf_Any* value) { + UPB_WRITE_ONEOF(msg, struct google_protobuf_Any*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3); +} +UPB_INLINE struct google_protobuf_Any* envoy_config_overload_v3_ResourceMonitor_mutable_typed_config(envoy_config_overload_v3_ResourceMonitor *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_config_overload_v3_ResourceMonitor_typed_config(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_config_overload_v3_ResourceMonitor_set_typed_config(msg, sub); + } + return sub; +} + +/* envoy.config.overload.v3.ThresholdTrigger */ + +UPB_INLINE envoy_config_overload_v3_ThresholdTrigger *envoy_config_overload_v3_ThresholdTrigger_new(upb_arena *arena) { + return (envoy_config_overload_v3_ThresholdTrigger *)_upb_msg_new(&envoy_config_overload_v3_ThresholdTrigger_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_ThresholdTrigger *envoy_config_overload_v3_ThresholdTrigger_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_ThresholdTrigger *ret = envoy_config_overload_v3_ThresholdTrigger_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_ThresholdTrigger_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_ThresholdTrigger *envoy_config_overload_v3_ThresholdTrigger_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_ThresholdTrigger *ret = envoy_config_overload_v3_ThresholdTrigger_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_ThresholdTrigger_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_ThresholdTrigger_serialize(const envoy_config_overload_v3_ThresholdTrigger *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_ThresholdTrigger_msginit, arena, len); +} + +UPB_INLINE double envoy_config_overload_v3_ThresholdTrigger_value(const envoy_config_overload_v3_ThresholdTrigger *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double); } + +UPB_INLINE void envoy_config_overload_v3_ThresholdTrigger_set_value(envoy_config_overload_v3_ThresholdTrigger *msg, double value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double) = value; +} + +/* envoy.config.overload.v3.ScaledTrigger */ + +UPB_INLINE envoy_config_overload_v3_ScaledTrigger *envoy_config_overload_v3_ScaledTrigger_new(upb_arena *arena) { + return (envoy_config_overload_v3_ScaledTrigger *)_upb_msg_new(&envoy_config_overload_v3_ScaledTrigger_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_ScaledTrigger *envoy_config_overload_v3_ScaledTrigger_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_ScaledTrigger *ret = envoy_config_overload_v3_ScaledTrigger_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_ScaledTrigger_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_ScaledTrigger *envoy_config_overload_v3_ScaledTrigger_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_ScaledTrigger *ret = envoy_config_overload_v3_ScaledTrigger_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_ScaledTrigger_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_ScaledTrigger_serialize(const envoy_config_overload_v3_ScaledTrigger *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_ScaledTrigger_msginit, arena, len); +} + +UPB_INLINE double envoy_config_overload_v3_ScaledTrigger_scaling_threshold(const envoy_config_overload_v3_ScaledTrigger *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double); } +UPB_INLINE double envoy_config_overload_v3_ScaledTrigger_saturation_threshold(const envoy_config_overload_v3_ScaledTrigger *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), double); } + +UPB_INLINE void envoy_config_overload_v3_ScaledTrigger_set_scaling_threshold(envoy_config_overload_v3_ScaledTrigger *msg, double value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), double) = value; +} +UPB_INLINE void envoy_config_overload_v3_ScaledTrigger_set_saturation_threshold(envoy_config_overload_v3_ScaledTrigger *msg, double value) { + *UPB_PTR_AT(msg, UPB_SIZE(8, 8), double) = value; +} + +/* envoy.config.overload.v3.Trigger */ + +UPB_INLINE envoy_config_overload_v3_Trigger *envoy_config_overload_v3_Trigger_new(upb_arena *arena) { + return (envoy_config_overload_v3_Trigger *)_upb_msg_new(&envoy_config_overload_v3_Trigger_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_Trigger *envoy_config_overload_v3_Trigger_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_Trigger *ret = envoy_config_overload_v3_Trigger_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_Trigger_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_Trigger *envoy_config_overload_v3_Trigger_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_Trigger *ret = envoy_config_overload_v3_Trigger_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_Trigger_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_Trigger_serialize(const envoy_config_overload_v3_Trigger *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_Trigger_msginit, arena, len); +} + +typedef enum { + envoy_config_overload_v3_Trigger_trigger_oneof_threshold = 2, + envoy_config_overload_v3_Trigger_trigger_oneof_scaled = 3, + envoy_config_overload_v3_Trigger_trigger_oneof_NOT_SET = 0 +} envoy_config_overload_v3_Trigger_trigger_oneof_oneofcases; +UPB_INLINE envoy_config_overload_v3_Trigger_trigger_oneof_oneofcases envoy_config_overload_v3_Trigger_trigger_oneof_case(const envoy_config_overload_v3_Trigger* msg) { return (envoy_config_overload_v3_Trigger_trigger_oneof_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 24), int32_t); } + +UPB_INLINE upb_strview envoy_config_overload_v3_Trigger_name(const envoy_config_overload_v3_Trigger *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview); } +UPB_INLINE bool envoy_config_overload_v3_Trigger_has_threshold(const envoy_config_overload_v3_Trigger *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 2; } +UPB_INLINE const envoy_config_overload_v3_ThresholdTrigger* envoy_config_overload_v3_Trigger_threshold(const envoy_config_overload_v3_Trigger *msg) { return UPB_READ_ONEOF(msg, const envoy_config_overload_v3_ThresholdTrigger*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, NULL); } +UPB_INLINE bool envoy_config_overload_v3_Trigger_has_scaled(const envoy_config_overload_v3_Trigger *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 3; } +UPB_INLINE const envoy_config_overload_v3_ScaledTrigger* envoy_config_overload_v3_Trigger_scaled(const envoy_config_overload_v3_Trigger *msg) { return UPB_READ_ONEOF(msg, const envoy_config_overload_v3_ScaledTrigger*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); } + +UPB_INLINE void envoy_config_overload_v3_Trigger_set_name(envoy_config_overload_v3_Trigger *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), upb_strview) = value; +} +UPB_INLINE void envoy_config_overload_v3_Trigger_set_threshold(envoy_config_overload_v3_Trigger *msg, envoy_config_overload_v3_ThresholdTrigger* value) { + UPB_WRITE_ONEOF(msg, envoy_config_overload_v3_ThresholdTrigger*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2); +} +UPB_INLINE struct envoy_config_overload_v3_ThresholdTrigger* envoy_config_overload_v3_Trigger_mutable_threshold(envoy_config_overload_v3_Trigger *msg, upb_arena *arena) { + struct envoy_config_overload_v3_ThresholdTrigger* sub = (struct envoy_config_overload_v3_ThresholdTrigger*)envoy_config_overload_v3_Trigger_threshold(msg); + if (sub == NULL) { + sub = (struct envoy_config_overload_v3_ThresholdTrigger*)_upb_msg_new(&envoy_config_overload_v3_ThresholdTrigger_msginit, arena); + if (!sub) return NULL; + envoy_config_overload_v3_Trigger_set_threshold(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_overload_v3_Trigger_set_scaled(envoy_config_overload_v3_Trigger *msg, envoy_config_overload_v3_ScaledTrigger* value) { + UPB_WRITE_ONEOF(msg, envoy_config_overload_v3_ScaledTrigger*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3); +} +UPB_INLINE struct envoy_config_overload_v3_ScaledTrigger* envoy_config_overload_v3_Trigger_mutable_scaled(envoy_config_overload_v3_Trigger *msg, upb_arena *arena) { + struct envoy_config_overload_v3_ScaledTrigger* sub = (struct envoy_config_overload_v3_ScaledTrigger*)envoy_config_overload_v3_Trigger_scaled(msg); + if (sub == NULL) { + sub = (struct envoy_config_overload_v3_ScaledTrigger*)_upb_msg_new(&envoy_config_overload_v3_ScaledTrigger_msginit, arena); + if (!sub) return NULL; + envoy_config_overload_v3_Trigger_set_scaled(msg, sub); + } + return sub; +} + +/* envoy.config.overload.v3.ScaleTimersOverloadActionConfig */ + +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_new(upb_arena *arena) { + return (envoy_config_overload_v3_ScaleTimersOverloadActionConfig *)_upb_msg_new(&envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_ScaleTimersOverloadActionConfig *ret = envoy_config_overload_v3_ScaleTimersOverloadActionConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_ScaleTimersOverloadActionConfig *ret = envoy_config_overload_v3_ScaleTimersOverloadActionConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_serialize(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_overload_v3_ScaleTimersOverloadActionConfig_has_timer_scale_factors(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer* const* envoy_config_overload_v3_ScaleTimersOverloadActionConfig_timer_scale_factors(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig *msg, size_t *len) { return (const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer** envoy_config_overload_v3_ScaleTimersOverloadActionConfig_mutable_timer_scale_factors(envoy_config_overload_v3_ScaleTimersOverloadActionConfig *msg, size_t *len) { + return (envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer** envoy_config_overload_v3_ScaleTimersOverloadActionConfig_resize_timer_scale_factors(envoy_config_overload_v3_ScaleTimersOverloadActionConfig *msg, size_t len, upb_arena *arena) { + return (envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer* envoy_config_overload_v3_ScaleTimersOverloadActionConfig_add_timer_scale_factors(envoy_config_overload_v3_ScaleTimersOverloadActionConfig *msg, upb_arena *arena) { + struct envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer* sub = (struct envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer*)_upb_msg_new(&envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.config.overload.v3.ScaleTimersOverloadActionConfig.ScaleTimer */ + +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_new(upb_arena *arena) { + return (envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *)_upb_msg_new(&envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *ret = envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *ret = envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_serialize(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit, arena, len); +} + +typedef enum { + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_overload_adjust_min_timeout = 2, + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_overload_adjust_min_scale = 3, + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_overload_adjust_NOT_SET = 0 +} envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_overload_adjust_oneofcases; +UPB_INLINE envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_overload_adjust_oneofcases envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_overload_adjust_case(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer* msg) { return (envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_overload_adjust_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(8, 16), int32_t); } + +UPB_INLINE int32_t envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_timer(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t); } +UPB_INLINE bool envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_has_min_timeout(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg) { return _upb_getoneofcase(msg, UPB_SIZE(8, 16)) == 2; } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_min_timeout(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Duration*, UPB_SIZE(4, 8), UPB_SIZE(8, 16), 2, NULL); } +UPB_INLINE bool envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_has_min_scale(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg) { return _upb_getoneofcase(msg, UPB_SIZE(8, 16)) == 3; } +UPB_INLINE const struct envoy_type_v3_Percent* envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_min_scale(const envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg) { return UPB_READ_ONEOF(msg, const struct envoy_type_v3_Percent*, UPB_SIZE(4, 8), UPB_SIZE(8, 16), 3, NULL); } + +UPB_INLINE void envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_set_timer(envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value; +} +UPB_INLINE void envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_set_min_timeout(envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg, struct google_protobuf_Duration* value) { + UPB_WRITE_ONEOF(msg, struct google_protobuf_Duration*, UPB_SIZE(4, 8), value, UPB_SIZE(8, 16), 2); +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_mutable_min_timeout(envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_min_timeout(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_set_min_timeout(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_set_min_scale(envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg, struct envoy_type_v3_Percent* value) { + UPB_WRITE_ONEOF(msg, struct envoy_type_v3_Percent*, UPB_SIZE(4, 8), value, UPB_SIZE(8, 16), 3); +} +UPB_INLINE struct envoy_type_v3_Percent* envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_mutable_min_scale(envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer *msg, upb_arena *arena) { + struct envoy_type_v3_Percent* sub = (struct envoy_type_v3_Percent*)envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_min_scale(msg); + if (sub == NULL) { + sub = (struct envoy_type_v3_Percent*)_upb_msg_new(&envoy_type_v3_Percent_msginit, arena); + if (!sub) return NULL; + envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_set_min_scale(msg, sub); + } + return sub; +} + +/* envoy.config.overload.v3.OverloadAction */ + +UPB_INLINE envoy_config_overload_v3_OverloadAction *envoy_config_overload_v3_OverloadAction_new(upb_arena *arena) { + return (envoy_config_overload_v3_OverloadAction *)_upb_msg_new(&envoy_config_overload_v3_OverloadAction_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_OverloadAction *envoy_config_overload_v3_OverloadAction_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_OverloadAction *ret = envoy_config_overload_v3_OverloadAction_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_OverloadAction_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_OverloadAction *envoy_config_overload_v3_OverloadAction_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_OverloadAction *ret = envoy_config_overload_v3_OverloadAction_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_OverloadAction_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_OverloadAction_serialize(const envoy_config_overload_v3_OverloadAction *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_OverloadAction_msginit, arena, len); +} + +UPB_INLINE upb_strview envoy_config_overload_v3_OverloadAction_name(const envoy_config_overload_v3_OverloadAction *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_config_overload_v3_OverloadAction_has_triggers(const envoy_config_overload_v3_OverloadAction *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(16, 32)); } +UPB_INLINE const envoy_config_overload_v3_Trigger* const* envoy_config_overload_v3_OverloadAction_triggers(const envoy_config_overload_v3_OverloadAction *msg, size_t *len) { return (const envoy_config_overload_v3_Trigger* const*)_upb_array_accessor(msg, UPB_SIZE(16, 32), len); } +UPB_INLINE bool envoy_config_overload_v3_OverloadAction_has_typed_config(const envoy_config_overload_v3_OverloadAction *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Any* envoy_config_overload_v3_OverloadAction_typed_config(const envoy_config_overload_v3_OverloadAction *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct google_protobuf_Any*); } + +UPB_INLINE void envoy_config_overload_v3_OverloadAction_set_name(envoy_config_overload_v3_OverloadAction *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE envoy_config_overload_v3_Trigger** envoy_config_overload_v3_OverloadAction_mutable_triggers(envoy_config_overload_v3_OverloadAction *msg, size_t *len) { + return (envoy_config_overload_v3_Trigger**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 32), len); +} +UPB_INLINE envoy_config_overload_v3_Trigger** envoy_config_overload_v3_OverloadAction_resize_triggers(envoy_config_overload_v3_OverloadAction *msg, size_t len, upb_arena *arena) { + return (envoy_config_overload_v3_Trigger**)_upb_array_resize_accessor2(msg, UPB_SIZE(16, 32), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_overload_v3_Trigger* envoy_config_overload_v3_OverloadAction_add_triggers(envoy_config_overload_v3_OverloadAction *msg, upb_arena *arena) { + struct envoy_config_overload_v3_Trigger* sub = (struct envoy_config_overload_v3_Trigger*)_upb_msg_new(&envoy_config_overload_v3_Trigger_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_config_overload_v3_OverloadAction_set_typed_config(envoy_config_overload_v3_OverloadAction *msg, struct google_protobuf_Any* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct google_protobuf_Any*) = value; +} +UPB_INLINE struct google_protobuf_Any* envoy_config_overload_v3_OverloadAction_mutable_typed_config(envoy_config_overload_v3_OverloadAction *msg, upb_arena *arena) { + struct google_protobuf_Any* sub = (struct google_protobuf_Any*)envoy_config_overload_v3_OverloadAction_typed_config(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Any*)_upb_msg_new(&google_protobuf_Any_msginit, arena); + if (!sub) return NULL; + envoy_config_overload_v3_OverloadAction_set_typed_config(msg, sub); + } + return sub; +} + +/* envoy.config.overload.v3.OverloadManager */ + +UPB_INLINE envoy_config_overload_v3_OverloadManager *envoy_config_overload_v3_OverloadManager_new(upb_arena *arena) { + return (envoy_config_overload_v3_OverloadManager *)_upb_msg_new(&envoy_config_overload_v3_OverloadManager_msginit, arena); +} +UPB_INLINE envoy_config_overload_v3_OverloadManager *envoy_config_overload_v3_OverloadManager_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_config_overload_v3_OverloadManager *ret = envoy_config_overload_v3_OverloadManager_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_config_overload_v3_OverloadManager_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_config_overload_v3_OverloadManager *envoy_config_overload_v3_OverloadManager_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_config_overload_v3_OverloadManager *ret = envoy_config_overload_v3_OverloadManager_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_config_overload_v3_OverloadManager_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_config_overload_v3_OverloadManager_serialize(const envoy_config_overload_v3_OverloadManager *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_config_overload_v3_OverloadManager_msginit, arena, len); +} + +UPB_INLINE bool envoy_config_overload_v3_OverloadManager_has_refresh_interval(const envoy_config_overload_v3_OverloadManager *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct google_protobuf_Duration* envoy_config_overload_v3_OverloadManager_refresh_interval(const envoy_config_overload_v3_OverloadManager *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct google_protobuf_Duration*); } +UPB_INLINE bool envoy_config_overload_v3_OverloadManager_has_resource_monitors(const envoy_config_overload_v3_OverloadManager *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const envoy_config_overload_v3_ResourceMonitor* const* envoy_config_overload_v3_OverloadManager_resource_monitors(const envoy_config_overload_v3_OverloadManager *msg, size_t *len) { return (const envoy_config_overload_v3_ResourceMonitor* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE bool envoy_config_overload_v3_OverloadManager_has_actions(const envoy_config_overload_v3_OverloadManager *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(12, 24)); } +UPB_INLINE const envoy_config_overload_v3_OverloadAction* const* envoy_config_overload_v3_OverloadManager_actions(const envoy_config_overload_v3_OverloadManager *msg, size_t *len) { return (const envoy_config_overload_v3_OverloadAction* const*)_upb_array_accessor(msg, UPB_SIZE(12, 24), len); } + +UPB_INLINE void envoy_config_overload_v3_OverloadManager_set_refresh_interval(envoy_config_overload_v3_OverloadManager *msg, struct google_protobuf_Duration* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct google_protobuf_Duration*) = value; +} +UPB_INLINE struct google_protobuf_Duration* envoy_config_overload_v3_OverloadManager_mutable_refresh_interval(envoy_config_overload_v3_OverloadManager *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_config_overload_v3_OverloadManager_refresh_interval(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_config_overload_v3_OverloadManager_set_refresh_interval(msg, sub); + } + return sub; +} +UPB_INLINE envoy_config_overload_v3_ResourceMonitor** envoy_config_overload_v3_OverloadManager_mutable_resource_monitors(envoy_config_overload_v3_OverloadManager *msg, size_t *len) { + return (envoy_config_overload_v3_ResourceMonitor**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE envoy_config_overload_v3_ResourceMonitor** envoy_config_overload_v3_OverloadManager_resize_resource_monitors(envoy_config_overload_v3_OverloadManager *msg, size_t len, upb_arena *arena) { + return (envoy_config_overload_v3_ResourceMonitor**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_overload_v3_ResourceMonitor* envoy_config_overload_v3_OverloadManager_add_resource_monitors(envoy_config_overload_v3_OverloadManager *msg, upb_arena *arena) { + struct envoy_config_overload_v3_ResourceMonitor* sub = (struct envoy_config_overload_v3_ResourceMonitor*)_upb_msg_new(&envoy_config_overload_v3_ResourceMonitor_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE envoy_config_overload_v3_OverloadAction** envoy_config_overload_v3_OverloadManager_mutable_actions(envoy_config_overload_v3_OverloadManager *msg, size_t *len) { + return (envoy_config_overload_v3_OverloadAction**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 24), len); +} +UPB_INLINE envoy_config_overload_v3_OverloadAction** envoy_config_overload_v3_OverloadManager_resize_actions(envoy_config_overload_v3_OverloadManager *msg, size_t len, upb_arena *arena) { + return (envoy_config_overload_v3_OverloadAction**)_upb_array_resize_accessor2(msg, UPB_SIZE(12, 24), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_overload_v3_OverloadAction* envoy_config_overload_v3_OverloadManager_add_actions(envoy_config_overload_v3_OverloadManager *msg, upb_arena *arena) { + struct envoy_config_overload_v3_OverloadAction* sub = (struct envoy_config_overload_v3_OverloadAction*)_upb_msg_new(&envoy_config_overload_v3_OverloadAction_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(12, 24), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_CONFIG_OVERLOAD_V3_OVERLOAD_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c b/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c new file mode 100644 index 00000000000..5f92b8d00b2 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c @@ -0,0 +1,79 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/common/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/extensions/filters/common/fault/v3/fault.upb.h" +#include "envoy/type/v3/percent.upb.h" +#include "google/protobuf/duration.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_extensions_filters_common_fault_v3_FaultDelay_submsgs[3] = { + &envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit, + &envoy_type_v3_FractionalPercent_msginit, + &google_protobuf_Duration_msginit, +}; + +static const upb_msglayout_field envoy_extensions_filters_common_fault_v3_FaultDelay__fields[3] = { + {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 2, 11, 1}, + {4, UPB_SIZE(4, 8), 1, 1, 11, 1}, + {5, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1}, +}; + +const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultDelay_msginit = { + &envoy_extensions_filters_common_fault_v3_FaultDelay_submsgs[0], + &envoy_extensions_filters_common_fault_v3_FaultDelay__fields[0], + UPB_SIZE(16, 32), 3, false, 255, +}; + +const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit = { + NULL, + NULL, + UPB_SIZE(0, 0), 0, false, 255, +}; + +static const upb_msglayout *const envoy_extensions_filters_common_fault_v3_FaultRateLimit_submsgs[3] = { + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit, + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit, + &envoy_type_v3_FractionalPercent_msginit, +}; + +static const upb_msglayout_field envoy_extensions_filters_common_fault_v3_FaultRateLimit__fields[3] = { + {1, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1}, + {2, UPB_SIZE(4, 8), 1, 2, 11, 1}, + {3, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 1, 11, 1}, +}; + +const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit = { + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_submsgs[0], + &envoy_extensions_filters_common_fault_v3_FaultRateLimit__fields[0], + UPB_SIZE(16, 32), 3, false, 255, +}; + +static const upb_msglayout_field envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 4, 1}, +}; + +const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit = { + NULL, + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit = { + NULL, + NULL, + UPB_SIZE(0, 0), 0, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h b/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h new file mode 100644 index 00000000000..8c609170d4e --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h @@ -0,0 +1,268 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/common/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_FILTERS_COMMON_FAULT_V3_FAULT_PROTO_UPB_H_ +#define ENVOY_EXTENSIONS_FILTERS_COMMON_FAULT_V3_FAULT_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_extensions_filters_common_fault_v3_FaultDelay; +struct envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay; +struct envoy_extensions_filters_common_fault_v3_FaultRateLimit; +struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit; +struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit; +typedef struct envoy_extensions_filters_common_fault_v3_FaultDelay envoy_extensions_filters_common_fault_v3_FaultDelay; +typedef struct envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay; +typedef struct envoy_extensions_filters_common_fault_v3_FaultRateLimit envoy_extensions_filters_common_fault_v3_FaultRateLimit; +typedef struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit; +typedef struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultDelay_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit; +struct envoy_type_v3_FractionalPercent; +struct google_protobuf_Duration; +extern const upb_msglayout envoy_type_v3_FractionalPercent_msginit; +extern const upb_msglayout google_protobuf_Duration_msginit; + +typedef enum { + envoy_extensions_filters_common_fault_v3_FaultDelay_FIXED = 0 +} envoy_extensions_filters_common_fault_v3_FaultDelay_FaultDelayType; + + +/* envoy.extensions.filters.common.fault.v3.FaultDelay */ + +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultDelay *envoy_extensions_filters_common_fault_v3_FaultDelay_new(upb_arena *arena) { + return (envoy_extensions_filters_common_fault_v3_FaultDelay *)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultDelay_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultDelay *envoy_extensions_filters_common_fault_v3_FaultDelay_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_common_fault_v3_FaultDelay *ret = envoy_extensions_filters_common_fault_v3_FaultDelay_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultDelay_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultDelay *envoy_extensions_filters_common_fault_v3_FaultDelay_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_common_fault_v3_FaultDelay *ret = envoy_extensions_filters_common_fault_v3_FaultDelay_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultDelay_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_common_fault_v3_FaultDelay_serialize(const envoy_extensions_filters_common_fault_v3_FaultDelay *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_common_fault_v3_FaultDelay_msginit, arena, len); +} + +typedef enum { + envoy_extensions_filters_common_fault_v3_FaultDelay_fault_delay_secifier_fixed_delay = 3, + envoy_extensions_filters_common_fault_v3_FaultDelay_fault_delay_secifier_header_delay = 5, + envoy_extensions_filters_common_fault_v3_FaultDelay_fault_delay_secifier_NOT_SET = 0 +} envoy_extensions_filters_common_fault_v3_FaultDelay_fault_delay_secifier_oneofcases; +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultDelay_fault_delay_secifier_oneofcases envoy_extensions_filters_common_fault_v3_FaultDelay_fault_delay_secifier_case(const envoy_extensions_filters_common_fault_v3_FaultDelay* msg) { return (envoy_extensions_filters_common_fault_v3_FaultDelay_fault_delay_secifier_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 24), int32_t); } + +UPB_INLINE bool envoy_extensions_filters_common_fault_v3_FaultDelay_has_fixed_delay(const envoy_extensions_filters_common_fault_v3_FaultDelay *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 3; } +UPB_INLINE const struct google_protobuf_Duration* envoy_extensions_filters_common_fault_v3_FaultDelay_fixed_delay(const envoy_extensions_filters_common_fault_v3_FaultDelay *msg) { return UPB_READ_ONEOF(msg, const struct google_protobuf_Duration*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); } +UPB_INLINE bool envoy_extensions_filters_common_fault_v3_FaultDelay_has_percentage(const envoy_extensions_filters_common_fault_v3_FaultDelay *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_type_v3_FractionalPercent* envoy_extensions_filters_common_fault_v3_FaultDelay_percentage(const envoy_extensions_filters_common_fault_v3_FaultDelay *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_type_v3_FractionalPercent*); } +UPB_INLINE bool envoy_extensions_filters_common_fault_v3_FaultDelay_has_header_delay(const envoy_extensions_filters_common_fault_v3_FaultDelay *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 5; } +UPB_INLINE const envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay* envoy_extensions_filters_common_fault_v3_FaultDelay_header_delay(const envoy_extensions_filters_common_fault_v3_FaultDelay *msg) { return UPB_READ_ONEOF(msg, const envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 5, NULL); } + +UPB_INLINE void envoy_extensions_filters_common_fault_v3_FaultDelay_set_fixed_delay(envoy_extensions_filters_common_fault_v3_FaultDelay *msg, struct google_protobuf_Duration* value) { + UPB_WRITE_ONEOF(msg, struct google_protobuf_Duration*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3); +} +UPB_INLINE struct google_protobuf_Duration* envoy_extensions_filters_common_fault_v3_FaultDelay_mutable_fixed_delay(envoy_extensions_filters_common_fault_v3_FaultDelay *msg, upb_arena *arena) { + struct google_protobuf_Duration* sub = (struct google_protobuf_Duration*)envoy_extensions_filters_common_fault_v3_FaultDelay_fixed_delay(msg); + if (sub == NULL) { + sub = (struct google_protobuf_Duration*)_upb_msg_new(&google_protobuf_Duration_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_common_fault_v3_FaultDelay_set_fixed_delay(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_common_fault_v3_FaultDelay_set_percentage(envoy_extensions_filters_common_fault_v3_FaultDelay *msg, struct envoy_type_v3_FractionalPercent* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_type_v3_FractionalPercent*) = value; +} +UPB_INLINE struct envoy_type_v3_FractionalPercent* envoy_extensions_filters_common_fault_v3_FaultDelay_mutable_percentage(envoy_extensions_filters_common_fault_v3_FaultDelay *msg, upb_arena *arena) { + struct envoy_type_v3_FractionalPercent* sub = (struct envoy_type_v3_FractionalPercent*)envoy_extensions_filters_common_fault_v3_FaultDelay_percentage(msg); + if (sub == NULL) { + sub = (struct envoy_type_v3_FractionalPercent*)_upb_msg_new(&envoy_type_v3_FractionalPercent_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_common_fault_v3_FaultDelay_set_percentage(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_common_fault_v3_FaultDelay_set_header_delay(envoy_extensions_filters_common_fault_v3_FaultDelay *msg, envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay* value) { + UPB_WRITE_ONEOF(msg, envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 5); +} +UPB_INLINE struct envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay* envoy_extensions_filters_common_fault_v3_FaultDelay_mutable_header_delay(envoy_extensions_filters_common_fault_v3_FaultDelay *msg, upb_arena *arena) { + struct envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay* sub = (struct envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay*)envoy_extensions_filters_common_fault_v3_FaultDelay_header_delay(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay*)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_common_fault_v3_FaultDelay_set_header_delay(msg, sub); + } + return sub; +} + +/* envoy.extensions.filters.common.fault.v3.FaultDelay.HeaderDelay */ + +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay *envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_new(upb_arena *arena) { + return (envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay *)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay *envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay *ret = envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay *envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay *ret = envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_serialize(const envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit, arena, len); +} + + + +/* envoy.extensions.filters.common.fault.v3.FaultRateLimit */ + +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_new(upb_arena *arena) { + return (envoy_extensions_filters_common_fault_v3_FaultRateLimit *)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_common_fault_v3_FaultRateLimit *ret = envoy_extensions_filters_common_fault_v3_FaultRateLimit_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_common_fault_v3_FaultRateLimit *ret = envoy_extensions_filters_common_fault_v3_FaultRateLimit_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_common_fault_v3_FaultRateLimit_serialize(const envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit, arena, len); +} + +typedef enum { + envoy_extensions_filters_common_fault_v3_FaultRateLimit_limit_type_fixed_limit = 1, + envoy_extensions_filters_common_fault_v3_FaultRateLimit_limit_type_header_limit = 3, + envoy_extensions_filters_common_fault_v3_FaultRateLimit_limit_type_NOT_SET = 0 +} envoy_extensions_filters_common_fault_v3_FaultRateLimit_limit_type_oneofcases; +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit_limit_type_oneofcases envoy_extensions_filters_common_fault_v3_FaultRateLimit_limit_type_case(const envoy_extensions_filters_common_fault_v3_FaultRateLimit* msg) { return (envoy_extensions_filters_common_fault_v3_FaultRateLimit_limit_type_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 24), int32_t); } + +UPB_INLINE bool envoy_extensions_filters_common_fault_v3_FaultRateLimit_has_fixed_limit(const envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 1; } +UPB_INLINE const envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit* envoy_extensions_filters_common_fault_v3_FaultRateLimit_fixed_limit(const envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg) { return UPB_READ_ONEOF(msg, const envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 1, NULL); } +UPB_INLINE bool envoy_extensions_filters_common_fault_v3_FaultRateLimit_has_percentage(const envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_type_v3_FractionalPercent* envoy_extensions_filters_common_fault_v3_FaultRateLimit_percentage(const envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_type_v3_FractionalPercent*); } +UPB_INLINE bool envoy_extensions_filters_common_fault_v3_FaultRateLimit_has_header_limit(const envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 3; } +UPB_INLINE const envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit* envoy_extensions_filters_common_fault_v3_FaultRateLimit_header_limit(const envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg) { return UPB_READ_ONEOF(msg, const envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 3, NULL); } + +UPB_INLINE void envoy_extensions_filters_common_fault_v3_FaultRateLimit_set_fixed_limit(envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg, envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit* value) { + UPB_WRITE_ONEOF(msg, envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 1); +} +UPB_INLINE struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit* envoy_extensions_filters_common_fault_v3_FaultRateLimit_mutable_fixed_limit(envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg, upb_arena *arena) { + struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit* sub = (struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit*)envoy_extensions_filters_common_fault_v3_FaultRateLimit_fixed_limit(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit*)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_common_fault_v3_FaultRateLimit_set_fixed_limit(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_common_fault_v3_FaultRateLimit_set_percentage(envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg, struct envoy_type_v3_FractionalPercent* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_type_v3_FractionalPercent*) = value; +} +UPB_INLINE struct envoy_type_v3_FractionalPercent* envoy_extensions_filters_common_fault_v3_FaultRateLimit_mutable_percentage(envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg, upb_arena *arena) { + struct envoy_type_v3_FractionalPercent* sub = (struct envoy_type_v3_FractionalPercent*)envoy_extensions_filters_common_fault_v3_FaultRateLimit_percentage(msg); + if (sub == NULL) { + sub = (struct envoy_type_v3_FractionalPercent*)_upb_msg_new(&envoy_type_v3_FractionalPercent_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_common_fault_v3_FaultRateLimit_set_percentage(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_common_fault_v3_FaultRateLimit_set_header_limit(envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg, envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit* value) { + UPB_WRITE_ONEOF(msg, envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 3); +} +UPB_INLINE struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit* envoy_extensions_filters_common_fault_v3_FaultRateLimit_mutable_header_limit(envoy_extensions_filters_common_fault_v3_FaultRateLimit *msg, upb_arena *arena) { + struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit* sub = (struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit*)envoy_extensions_filters_common_fault_v3_FaultRateLimit_header_limit(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit*)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_common_fault_v3_FaultRateLimit_set_header_limit(msg, sub); + } + return sub; +} + +/* envoy.extensions.filters.common.fault.v3.FaultRateLimit.FixedLimit */ + +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_new(upb_arena *arena) { + return (envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *ret = envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *ret = envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_serialize(const envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit, arena, len); +} + +UPB_INLINE uint64_t envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_limit_kbps(const envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), uint64_t); } + +UPB_INLINE void envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_set_limit_kbps(envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit *msg, uint64_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), uint64_t) = value; +} + +/* envoy.extensions.filters.common.fault.v3.FaultRateLimit.HeaderLimit */ + +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_new(upb_arena *arena) { + return (envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit *)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit *ret = envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit *envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit *ret = envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_serialize(const envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit, arena, len); +} + + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_FILTERS_COMMON_FAULT_V3_FAULT_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c b/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c new file mode 100644 index 00000000000..ca5144c5dcf --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c @@ -0,0 +1,78 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/extensions/filters/http/fault/v3/fault.upb.h" +#include "envoy/config/route/v3/route_components.upb.h" +#include "envoy/extensions/filters/common/fault/v3/fault.upb.h" +#include "envoy/type/v3/percent.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_extensions_filters_http_fault_v3_FaultAbort_submsgs[2] = { + &envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit, + &envoy_type_v3_FractionalPercent_msginit, +}; + +static const upb_msglayout_field envoy_extensions_filters_http_fault_v3_FaultAbort__fields[4] = { + {2, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 13, 1}, + {3, UPB_SIZE(4, 8), 1, 1, 11, 1}, + {4, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 11, 1}, + {5, UPB_SIZE(8, 16), UPB_SIZE(-13, -25), 0, 13, 1}, +}; + +const upb_msglayout envoy_extensions_filters_http_fault_v3_FaultAbort_msginit = { + &envoy_extensions_filters_http_fault_v3_FaultAbort_submsgs[0], + &envoy_extensions_filters_http_fault_v3_FaultAbort__fields[0], + UPB_SIZE(16, 32), 4, false, 255, +}; + +const upb_msglayout envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit = { + NULL, + NULL, + UPB_SIZE(0, 0), 0, false, 255, +}; + +static const upb_msglayout *const envoy_extensions_filters_http_fault_v3_HTTPFault_submsgs[5] = { + &envoy_config_route_v3_HeaderMatcher_msginit, + &envoy_extensions_filters_common_fault_v3_FaultDelay_msginit, + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit, + &envoy_extensions_filters_http_fault_v3_FaultAbort_msginit, + &google_protobuf_UInt32Value_msginit, +}; + +static const upb_msglayout_field envoy_extensions_filters_http_fault_v3_HTTPFault__fields[14] = { + {1, UPB_SIZE(68, 136), 1, 1, 11, 1}, + {2, UPB_SIZE(72, 144), 2, 3, 11, 1}, + {3, UPB_SIZE(4, 8), 0, 0, 9, 1}, + {4, UPB_SIZE(84, 168), 0, 0, 11, 3}, + {5, UPB_SIZE(88, 176), 0, 0, 9, 3}, + {6, UPB_SIZE(76, 152), 3, 4, 11, 1}, + {7, UPB_SIZE(80, 160), 4, 2, 11, 1}, + {8, UPB_SIZE(12, 24), 0, 0, 9, 1}, + {9, UPB_SIZE(20, 40), 0, 0, 9, 1}, + {10, UPB_SIZE(28, 56), 0, 0, 9, 1}, + {11, UPB_SIZE(36, 72), 0, 0, 9, 1}, + {12, UPB_SIZE(44, 88), 0, 0, 9, 1}, + {13, UPB_SIZE(52, 104), 0, 0, 9, 1}, + {14, UPB_SIZE(60, 120), 0, 0, 9, 1}, +}; + +const upb_msglayout envoy_extensions_filters_http_fault_v3_HTTPFault_msginit = { + &envoy_extensions_filters_http_fault_v3_HTTPFault_submsgs[0], + &envoy_extensions_filters_http_fault_v3_HTTPFault__fields[0], + UPB_SIZE(96, 192), 14, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h b/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h new file mode 100644 index 00000000000..fc618c9a53e --- /dev/null +++ b/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h @@ -0,0 +1,281 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_FILTERS_HTTP_FAULT_V3_FAULT_PROTO_UPB_H_ +#define ENVOY_EXTENSIONS_FILTERS_HTTP_FAULT_V3_FAULT_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_extensions_filters_http_fault_v3_FaultAbort; +struct envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort; +struct envoy_extensions_filters_http_fault_v3_HTTPFault; +typedef struct envoy_extensions_filters_http_fault_v3_FaultAbort envoy_extensions_filters_http_fault_v3_FaultAbort; +typedef struct envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort; +typedef struct envoy_extensions_filters_http_fault_v3_HTTPFault envoy_extensions_filters_http_fault_v3_HTTPFault; +extern const upb_msglayout envoy_extensions_filters_http_fault_v3_FaultAbort_msginit; +extern const upb_msglayout envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit; +extern const upb_msglayout envoy_extensions_filters_http_fault_v3_HTTPFault_msginit; +struct envoy_config_route_v3_HeaderMatcher; +struct envoy_extensions_filters_common_fault_v3_FaultDelay; +struct envoy_extensions_filters_common_fault_v3_FaultRateLimit; +struct envoy_type_v3_FractionalPercent; +struct google_protobuf_UInt32Value; +extern const upb_msglayout envoy_config_route_v3_HeaderMatcher_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultDelay_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit; +extern const upb_msglayout envoy_type_v3_FractionalPercent_msginit; +extern const upb_msglayout google_protobuf_UInt32Value_msginit; + + +/* envoy.extensions.filters.http.fault.v3.FaultAbort */ + +UPB_INLINE envoy_extensions_filters_http_fault_v3_FaultAbort *envoy_extensions_filters_http_fault_v3_FaultAbort_new(upb_arena *arena) { + return (envoy_extensions_filters_http_fault_v3_FaultAbort *)_upb_msg_new(&envoy_extensions_filters_http_fault_v3_FaultAbort_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_http_fault_v3_FaultAbort *envoy_extensions_filters_http_fault_v3_FaultAbort_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_http_fault_v3_FaultAbort *ret = envoy_extensions_filters_http_fault_v3_FaultAbort_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_http_fault_v3_FaultAbort_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_http_fault_v3_FaultAbort *envoy_extensions_filters_http_fault_v3_FaultAbort_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_http_fault_v3_FaultAbort *ret = envoy_extensions_filters_http_fault_v3_FaultAbort_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_http_fault_v3_FaultAbort_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_http_fault_v3_FaultAbort_serialize(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_http_fault_v3_FaultAbort_msginit, arena, len); +} + +typedef enum { + envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_http_status = 2, + envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_grpc_status = 5, + envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_header_abort = 4, + envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_NOT_SET = 0 +} envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_oneofcases; +UPB_INLINE envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_oneofcases envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_case(const envoy_extensions_filters_http_fault_v3_FaultAbort* msg) { return (envoy_extensions_filters_http_fault_v3_FaultAbort_error_type_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 24), int32_t); } + +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_FaultAbort_has_http_status(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 2; } +UPB_INLINE uint32_t envoy_extensions_filters_http_fault_v3_FaultAbort_http_status(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return UPB_READ_ONEOF(msg, uint32_t, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 2, 0); } +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_FaultAbort_has_percentage(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_type_v3_FractionalPercent* envoy_extensions_filters_http_fault_v3_FaultAbort_percentage(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_type_v3_FractionalPercent*); } +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_FaultAbort_has_header_abort(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 4; } +UPB_INLINE const envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort* envoy_extensions_filters_http_fault_v3_FaultAbort_header_abort(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return UPB_READ_ONEOF(msg, const envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort*, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 4, NULL); } +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_FaultAbort_has_grpc_status(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 24)) == 5; } +UPB_INLINE uint32_t envoy_extensions_filters_http_fault_v3_FaultAbort_grpc_status(const envoy_extensions_filters_http_fault_v3_FaultAbort *msg) { return UPB_READ_ONEOF(msg, uint32_t, UPB_SIZE(8, 16), UPB_SIZE(12, 24), 5, 0); } + +UPB_INLINE void envoy_extensions_filters_http_fault_v3_FaultAbort_set_http_status(envoy_extensions_filters_http_fault_v3_FaultAbort *msg, uint32_t value) { + UPB_WRITE_ONEOF(msg, uint32_t, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 2); +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_FaultAbort_set_percentage(envoy_extensions_filters_http_fault_v3_FaultAbort *msg, struct envoy_type_v3_FractionalPercent* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_type_v3_FractionalPercent*) = value; +} +UPB_INLINE struct envoy_type_v3_FractionalPercent* envoy_extensions_filters_http_fault_v3_FaultAbort_mutable_percentage(envoy_extensions_filters_http_fault_v3_FaultAbort *msg, upb_arena *arena) { + struct envoy_type_v3_FractionalPercent* sub = (struct envoy_type_v3_FractionalPercent*)envoy_extensions_filters_http_fault_v3_FaultAbort_percentage(msg); + if (sub == NULL) { + sub = (struct envoy_type_v3_FractionalPercent*)_upb_msg_new(&envoy_type_v3_FractionalPercent_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_fault_v3_FaultAbort_set_percentage(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_FaultAbort_set_header_abort(envoy_extensions_filters_http_fault_v3_FaultAbort *msg, envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort* value) { + UPB_WRITE_ONEOF(msg, envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort*, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 4); +} +UPB_INLINE struct envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort* envoy_extensions_filters_http_fault_v3_FaultAbort_mutable_header_abort(envoy_extensions_filters_http_fault_v3_FaultAbort *msg, upb_arena *arena) { + struct envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort* sub = (struct envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort*)envoy_extensions_filters_http_fault_v3_FaultAbort_header_abort(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort*)_upb_msg_new(&envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_fault_v3_FaultAbort_set_header_abort(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_FaultAbort_set_grpc_status(envoy_extensions_filters_http_fault_v3_FaultAbort *msg, uint32_t value) { + UPB_WRITE_ONEOF(msg, uint32_t, UPB_SIZE(8, 16), value, UPB_SIZE(12, 24), 5); +} + +/* envoy.extensions.filters.http.fault.v3.FaultAbort.HeaderAbort */ + +UPB_INLINE envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort *envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_new(upb_arena *arena) { + return (envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort *)_upb_msg_new(&envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort *envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort *ret = envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort *envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort *ret = envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_serialize(const envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit, arena, len); +} + + + +/* envoy.extensions.filters.http.fault.v3.HTTPFault */ + +UPB_INLINE envoy_extensions_filters_http_fault_v3_HTTPFault *envoy_extensions_filters_http_fault_v3_HTTPFault_new(upb_arena *arena) { + return (envoy_extensions_filters_http_fault_v3_HTTPFault *)_upb_msg_new(&envoy_extensions_filters_http_fault_v3_HTTPFault_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_http_fault_v3_HTTPFault *envoy_extensions_filters_http_fault_v3_HTTPFault_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_http_fault_v3_HTTPFault *ret = envoy_extensions_filters_http_fault_v3_HTTPFault_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_extensions_filters_http_fault_v3_HTTPFault_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_extensions_filters_http_fault_v3_HTTPFault *envoy_extensions_filters_http_fault_v3_HTTPFault_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_extensions_filters_http_fault_v3_HTTPFault *ret = envoy_extensions_filters_http_fault_v3_HTTPFault_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_extensions_filters_http_fault_v3_HTTPFault_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_extensions_filters_http_fault_v3_HTTPFault_serialize(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_http_fault_v3_HTTPFault_msginit, arena, len); +} + +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_HTTPFault_has_delay(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_extensions_filters_common_fault_v3_FaultDelay* envoy_extensions_filters_http_fault_v3_HTTPFault_delay(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(68, 136), const struct envoy_extensions_filters_common_fault_v3_FaultDelay*); } +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_HTTPFault_has_abort(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const envoy_extensions_filters_http_fault_v3_FaultAbort* envoy_extensions_filters_http_fault_v3_HTTPFault_abort(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(72, 144), const envoy_extensions_filters_http_fault_v3_FaultAbort*); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_upstream_cluster(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_HTTPFault_has_headers(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(84, 168)); } +UPB_INLINE const struct envoy_config_route_v3_HeaderMatcher* const* envoy_extensions_filters_http_fault_v3_HTTPFault_headers(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg, size_t *len) { return (const struct envoy_config_route_v3_HeaderMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(84, 168), len); } +UPB_INLINE upb_strview const* envoy_extensions_filters_http_fault_v3_HTTPFault_downstream_nodes(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg, size_t *len) { return (upb_strview const*)_upb_array_accessor(msg, UPB_SIZE(88, 176), len); } +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_HTTPFault_has_max_active_faults(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return _upb_hasbit(msg, 3); } +UPB_INLINE const struct google_protobuf_UInt32Value* envoy_extensions_filters_http_fault_v3_HTTPFault_max_active_faults(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(76, 152), const struct google_protobuf_UInt32Value*); } +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_HTTPFault_has_response_rate_limit(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return _upb_hasbit(msg, 4); } +UPB_INLINE const struct envoy_extensions_filters_common_fault_v3_FaultRateLimit* envoy_extensions_filters_http_fault_v3_HTTPFault_response_rate_limit(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(80, 160), const struct envoy_extensions_filters_common_fault_v3_FaultRateLimit*); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_delay_percent_runtime(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_abort_percent_runtime(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_delay_duration_runtime(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(28, 56), upb_strview); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_abort_http_status_runtime(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(36, 72), upb_strview); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_max_active_faults_runtime(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(44, 88), upb_strview); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_response_rate_limit_percent_runtime(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(52, 104), upb_strview); } +UPB_INLINE upb_strview envoy_extensions_filters_http_fault_v3_HTTPFault_abort_grpc_status_runtime(const envoy_extensions_filters_http_fault_v3_HTTPFault *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(60, 120), upb_strview); } + +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_delay(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, struct envoy_extensions_filters_common_fault_v3_FaultDelay* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(68, 136), struct envoy_extensions_filters_common_fault_v3_FaultDelay*) = value; +} +UPB_INLINE struct envoy_extensions_filters_common_fault_v3_FaultDelay* envoy_extensions_filters_http_fault_v3_HTTPFault_mutable_delay(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_arena *arena) { + struct envoy_extensions_filters_common_fault_v3_FaultDelay* sub = (struct envoy_extensions_filters_common_fault_v3_FaultDelay*)envoy_extensions_filters_http_fault_v3_HTTPFault_delay(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_common_fault_v3_FaultDelay*)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultDelay_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_fault_v3_HTTPFault_set_delay(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_abort(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, envoy_extensions_filters_http_fault_v3_FaultAbort* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(72, 144), envoy_extensions_filters_http_fault_v3_FaultAbort*) = value; +} +UPB_INLINE struct envoy_extensions_filters_http_fault_v3_FaultAbort* envoy_extensions_filters_http_fault_v3_HTTPFault_mutable_abort(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_arena *arena) { + struct envoy_extensions_filters_http_fault_v3_FaultAbort* sub = (struct envoy_extensions_filters_http_fault_v3_FaultAbort*)envoy_extensions_filters_http_fault_v3_HTTPFault_abort(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_http_fault_v3_FaultAbort*)_upb_msg_new(&envoy_extensions_filters_http_fault_v3_FaultAbort_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_fault_v3_HTTPFault_set_abort(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_upstream_cluster(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} +UPB_INLINE struct envoy_config_route_v3_HeaderMatcher** envoy_extensions_filters_http_fault_v3_HTTPFault_mutable_headers(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, size_t *len) { + return (struct envoy_config_route_v3_HeaderMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(84, 168), len); +} +UPB_INLINE struct envoy_config_route_v3_HeaderMatcher** envoy_extensions_filters_http_fault_v3_HTTPFault_resize_headers(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, size_t len, upb_arena *arena) { + return (struct envoy_config_route_v3_HeaderMatcher**)_upb_array_resize_accessor2(msg, UPB_SIZE(84, 168), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_config_route_v3_HeaderMatcher* envoy_extensions_filters_http_fault_v3_HTTPFault_add_headers(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_arena *arena) { + struct envoy_config_route_v3_HeaderMatcher* sub = (struct envoy_config_route_v3_HeaderMatcher*)_upb_msg_new(&envoy_config_route_v3_HeaderMatcher_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(84, 168), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE upb_strview* envoy_extensions_filters_http_fault_v3_HTTPFault_mutable_downstream_nodes(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, size_t *len) { + return (upb_strview*)_upb_array_mutable_accessor(msg, UPB_SIZE(88, 176), len); +} +UPB_INLINE upb_strview* envoy_extensions_filters_http_fault_v3_HTTPFault_resize_downstream_nodes(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, size_t len, upb_arena *arena) { + return (upb_strview*)_upb_array_resize_accessor2(msg, UPB_SIZE(88, 176), len, UPB_SIZE(3, 4), arena); +} +UPB_INLINE bool envoy_extensions_filters_http_fault_v3_HTTPFault_add_downstream_nodes(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview val, upb_arena *arena) { + return _upb_array_append_accessor2(msg, UPB_SIZE(88, 176), UPB_SIZE(3, 4), &val, + arena); +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_max_active_faults(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, struct google_protobuf_UInt32Value* value) { + _upb_sethas(msg, 3); + *UPB_PTR_AT(msg, UPB_SIZE(76, 152), struct google_protobuf_UInt32Value*) = value; +} +UPB_INLINE struct google_protobuf_UInt32Value* envoy_extensions_filters_http_fault_v3_HTTPFault_mutable_max_active_faults(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_arena *arena) { + struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_extensions_filters_http_fault_v3_HTTPFault_max_active_faults(msg); + if (sub == NULL) { + sub = (struct google_protobuf_UInt32Value*)_upb_msg_new(&google_protobuf_UInt32Value_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_fault_v3_HTTPFault_set_max_active_faults(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_response_rate_limit(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, struct envoy_extensions_filters_common_fault_v3_FaultRateLimit* value) { + _upb_sethas(msg, 4); + *UPB_PTR_AT(msg, UPB_SIZE(80, 160), struct envoy_extensions_filters_common_fault_v3_FaultRateLimit*) = value; +} +UPB_INLINE struct envoy_extensions_filters_common_fault_v3_FaultRateLimit* envoy_extensions_filters_http_fault_v3_HTTPFault_mutable_response_rate_limit(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_arena *arena) { + struct envoy_extensions_filters_common_fault_v3_FaultRateLimit* sub = (struct envoy_extensions_filters_common_fault_v3_FaultRateLimit*)envoy_extensions_filters_http_fault_v3_HTTPFault_response_rate_limit(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_common_fault_v3_FaultRateLimit*)_upb_msg_new(&envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_fault_v3_HTTPFault_set_response_rate_limit(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_delay_percent_runtime(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_strview) = value; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_abort_percent_runtime(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_strview) = value; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_delay_duration_runtime(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(28, 56), upb_strview) = value; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_abort_http_status_runtime(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(36, 72), upb_strview) = value; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_max_active_faults_runtime(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(44, 88), upb_strview) = value; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_response_rate_limit_percent_runtime(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(52, 104), upb_strview) = value; +} +UPB_INLINE void envoy_extensions_filters_http_fault_v3_HTTPFault_set_abort_grpc_status_runtime(envoy_extensions_filters_http_fault_v3_HTTPFault *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(60, 120), upb_strview) = value; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_FILTERS_HTTP_FAULT_V3_FAULT_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c b/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c new file mode 100644 index 00000000000..40e086cba51 --- /dev/null +++ b/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c @@ -0,0 +1,93 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/status/v3/csds.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/service/status/v3/csds.upb.h" +#include "envoy/admin/v3/config_dump.upb.h" +#include "envoy/config/core/v3/base.upb.h" +#include "envoy/type/matcher/v3/node.upb.h" +#include "google/api/annotations.upb.h" +#include "udpa/annotations/migrate.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_service_status_v3_ClientStatusRequest_submsgs[2] = { + &envoy_config_core_v3_Node_msginit, + &envoy_type_matcher_v3_NodeMatcher_msginit, +}; + +static const upb_msglayout_field envoy_service_status_v3_ClientStatusRequest__fields[2] = { + {1, UPB_SIZE(8, 16), 0, 1, 11, 3}, + {2, UPB_SIZE(4, 8), 1, 0, 11, 1}, +}; + +const upb_msglayout envoy_service_status_v3_ClientStatusRequest_msginit = { + &envoy_service_status_v3_ClientStatusRequest_submsgs[0], + &envoy_service_status_v3_ClientStatusRequest__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_service_status_v3_PerXdsConfig_submsgs[5] = { + &envoy_admin_v3_ClustersConfigDump_msginit, + &envoy_admin_v3_EndpointsConfigDump_msginit, + &envoy_admin_v3_ListenersConfigDump_msginit, + &envoy_admin_v3_RoutesConfigDump_msginit, + &envoy_admin_v3_ScopedRoutesConfigDump_msginit, +}; + +static const upb_msglayout_field envoy_service_status_v3_PerXdsConfig__fields[7] = { + {1, UPB_SIZE(0, 0), 0, 0, 14, 1}, + {2, UPB_SIZE(8, 8), UPB_SIZE(-13, -17), 2, 11, 1}, + {3, UPB_SIZE(8, 8), UPB_SIZE(-13, -17), 0, 11, 1}, + {4, UPB_SIZE(8, 8), UPB_SIZE(-13, -17), 3, 11, 1}, + {5, UPB_SIZE(8, 8), UPB_SIZE(-13, -17), 4, 11, 1}, + {6, UPB_SIZE(8, 8), UPB_SIZE(-13, -17), 1, 11, 1}, + {7, UPB_SIZE(4, 4), 0, 0, 14, 1}, +}; + +const upb_msglayout envoy_service_status_v3_PerXdsConfig_msginit = { + &envoy_service_status_v3_PerXdsConfig_submsgs[0], + &envoy_service_status_v3_PerXdsConfig__fields[0], + UPB_SIZE(16, 24), 7, false, 255, +}; + +static const upb_msglayout *const envoy_service_status_v3_ClientConfig_submsgs[2] = { + &envoy_config_core_v3_Node_msginit, + &envoy_service_status_v3_PerXdsConfig_msginit, +}; + +static const upb_msglayout_field envoy_service_status_v3_ClientConfig__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 0, 1, 11, 3}, +}; + +const upb_msglayout envoy_service_status_v3_ClientConfig_msginit = { + &envoy_service_status_v3_ClientConfig_submsgs[0], + &envoy_service_status_v3_ClientConfig__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout *const envoy_service_status_v3_ClientStatusResponse_submsgs[1] = { + &envoy_service_status_v3_ClientConfig_msginit, +}; + +static const upb_msglayout_field envoy_service_status_v3_ClientStatusResponse__fields[1] = { + {1, UPB_SIZE(0, 0), 0, 0, 11, 3}, +}; + +const upb_msglayout envoy_service_status_v3_ClientStatusResponse_msginit = { + &envoy_service_status_v3_ClientStatusResponse_submsgs[0], + &envoy_service_status_v3_ClientStatusResponse__fields[0], + UPB_SIZE(8, 8), 1, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h b/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h new file mode 100644 index 00000000000..87f807cdf1a --- /dev/null +++ b/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h @@ -0,0 +1,323 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/status/v3/csds.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_SERVICE_STATUS_V3_CSDS_PROTO_UPB_H_ +#define ENVOY_SERVICE_STATUS_V3_CSDS_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_service_status_v3_ClientStatusRequest; +struct envoy_service_status_v3_PerXdsConfig; +struct envoy_service_status_v3_ClientConfig; +struct envoy_service_status_v3_ClientStatusResponse; +typedef struct envoy_service_status_v3_ClientStatusRequest envoy_service_status_v3_ClientStatusRequest; +typedef struct envoy_service_status_v3_PerXdsConfig envoy_service_status_v3_PerXdsConfig; +typedef struct envoy_service_status_v3_ClientConfig envoy_service_status_v3_ClientConfig; +typedef struct envoy_service_status_v3_ClientStatusResponse envoy_service_status_v3_ClientStatusResponse; +extern const upb_msglayout envoy_service_status_v3_ClientStatusRequest_msginit; +extern const upb_msglayout envoy_service_status_v3_PerXdsConfig_msginit; +extern const upb_msglayout envoy_service_status_v3_ClientConfig_msginit; +extern const upb_msglayout envoy_service_status_v3_ClientStatusResponse_msginit; +struct envoy_admin_v3_ClustersConfigDump; +struct envoy_admin_v3_EndpointsConfigDump; +struct envoy_admin_v3_ListenersConfigDump; +struct envoy_admin_v3_RoutesConfigDump; +struct envoy_admin_v3_ScopedRoutesConfigDump; +struct envoy_config_core_v3_Node; +struct envoy_type_matcher_v3_NodeMatcher; +extern const upb_msglayout envoy_admin_v3_ClustersConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_EndpointsConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_RoutesConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_msginit; +extern const upb_msglayout envoy_config_core_v3_Node_msginit; +extern const upb_msglayout envoy_type_matcher_v3_NodeMatcher_msginit; + +typedef enum { + envoy_service_status_v3_CLIENT_UNKNOWN = 0, + envoy_service_status_v3_CLIENT_REQUESTED = 1, + envoy_service_status_v3_CLIENT_ACKED = 2, + envoy_service_status_v3_CLIENT_NACKED = 3 +} envoy_service_status_v3_ClientConfigStatus; + +typedef enum { + envoy_service_status_v3_UNKNOWN = 0, + envoy_service_status_v3_SYNCED = 1, + envoy_service_status_v3_NOT_SENT = 2, + envoy_service_status_v3_STALE = 3, + envoy_service_status_v3_ERROR = 4 +} envoy_service_status_v3_ConfigStatus; + + +/* envoy.service.status.v3.ClientStatusRequest */ + +UPB_INLINE envoy_service_status_v3_ClientStatusRequest *envoy_service_status_v3_ClientStatusRequest_new(upb_arena *arena) { + return (envoy_service_status_v3_ClientStatusRequest *)_upb_msg_new(&envoy_service_status_v3_ClientStatusRequest_msginit, arena); +} +UPB_INLINE envoy_service_status_v3_ClientStatusRequest *envoy_service_status_v3_ClientStatusRequest_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_service_status_v3_ClientStatusRequest *ret = envoy_service_status_v3_ClientStatusRequest_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_service_status_v3_ClientStatusRequest_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_service_status_v3_ClientStatusRequest *envoy_service_status_v3_ClientStatusRequest_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_service_status_v3_ClientStatusRequest *ret = envoy_service_status_v3_ClientStatusRequest_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_service_status_v3_ClientStatusRequest_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_service_status_v3_ClientStatusRequest_serialize(const envoy_service_status_v3_ClientStatusRequest *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_status_v3_ClientStatusRequest_msginit, arena, len); +} + +UPB_INLINE bool envoy_service_status_v3_ClientStatusRequest_has_node_matchers(const envoy_service_status_v3_ClientStatusRequest *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const struct envoy_type_matcher_v3_NodeMatcher* const* envoy_service_status_v3_ClientStatusRequest_node_matchers(const envoy_service_status_v3_ClientStatusRequest *msg, size_t *len) { return (const struct envoy_type_matcher_v3_NodeMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE bool envoy_service_status_v3_ClientStatusRequest_has_node(const envoy_service_status_v3_ClientStatusRequest *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_Node* envoy_service_status_v3_ClientStatusRequest_node(const envoy_service_status_v3_ClientStatusRequest *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_config_core_v3_Node*); } + +UPB_INLINE struct envoy_type_matcher_v3_NodeMatcher** envoy_service_status_v3_ClientStatusRequest_mutable_node_matchers(envoy_service_status_v3_ClientStatusRequest *msg, size_t *len) { + return (struct envoy_type_matcher_v3_NodeMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE struct envoy_type_matcher_v3_NodeMatcher** envoy_service_status_v3_ClientStatusRequest_resize_node_matchers(envoy_service_status_v3_ClientStatusRequest *msg, size_t len, upb_arena *arena) { + return (struct envoy_type_matcher_v3_NodeMatcher**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_type_matcher_v3_NodeMatcher* envoy_service_status_v3_ClientStatusRequest_add_node_matchers(envoy_service_status_v3_ClientStatusRequest *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_NodeMatcher* sub = (struct envoy_type_matcher_v3_NodeMatcher*)_upb_msg_new(&envoy_type_matcher_v3_NodeMatcher_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_service_status_v3_ClientStatusRequest_set_node(envoy_service_status_v3_ClientStatusRequest *msg, struct envoy_config_core_v3_Node* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_config_core_v3_Node*) = value; +} +UPB_INLINE struct envoy_config_core_v3_Node* envoy_service_status_v3_ClientStatusRequest_mutable_node(envoy_service_status_v3_ClientStatusRequest *msg, upb_arena *arena) { + struct envoy_config_core_v3_Node* sub = (struct envoy_config_core_v3_Node*)envoy_service_status_v3_ClientStatusRequest_node(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_Node*)_upb_msg_new(&envoy_config_core_v3_Node_msginit, arena); + if (!sub) return NULL; + envoy_service_status_v3_ClientStatusRequest_set_node(msg, sub); + } + return sub; +} + +/* envoy.service.status.v3.PerXdsConfig */ + +UPB_INLINE envoy_service_status_v3_PerXdsConfig *envoy_service_status_v3_PerXdsConfig_new(upb_arena *arena) { + return (envoy_service_status_v3_PerXdsConfig *)_upb_msg_new(&envoy_service_status_v3_PerXdsConfig_msginit, arena); +} +UPB_INLINE envoy_service_status_v3_PerXdsConfig *envoy_service_status_v3_PerXdsConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_service_status_v3_PerXdsConfig *ret = envoy_service_status_v3_PerXdsConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_service_status_v3_PerXdsConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_service_status_v3_PerXdsConfig *envoy_service_status_v3_PerXdsConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_service_status_v3_PerXdsConfig *ret = envoy_service_status_v3_PerXdsConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_service_status_v3_PerXdsConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_service_status_v3_PerXdsConfig_serialize(const envoy_service_status_v3_PerXdsConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_status_v3_PerXdsConfig_msginit, arena, len); +} + +typedef enum { + envoy_service_status_v3_PerXdsConfig_per_xds_config_listener_config = 2, + envoy_service_status_v3_PerXdsConfig_per_xds_config_cluster_config = 3, + envoy_service_status_v3_PerXdsConfig_per_xds_config_route_config = 4, + envoy_service_status_v3_PerXdsConfig_per_xds_config_scoped_route_config = 5, + envoy_service_status_v3_PerXdsConfig_per_xds_config_endpoint_config = 6, + envoy_service_status_v3_PerXdsConfig_per_xds_config_NOT_SET = 0 +} envoy_service_status_v3_PerXdsConfig_per_xds_config_oneofcases; +UPB_INLINE envoy_service_status_v3_PerXdsConfig_per_xds_config_oneofcases envoy_service_status_v3_PerXdsConfig_per_xds_config_case(const envoy_service_status_v3_PerXdsConfig* msg) { return (envoy_service_status_v3_PerXdsConfig_per_xds_config_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(12, 16), int32_t); } + +UPB_INLINE int32_t envoy_service_status_v3_PerXdsConfig_status(const envoy_service_status_v3_PerXdsConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t); } +UPB_INLINE bool envoy_service_status_v3_PerXdsConfig_has_listener_config(const envoy_service_status_v3_PerXdsConfig *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 16)) == 2; } +UPB_INLINE const struct envoy_admin_v3_ListenersConfigDump* envoy_service_status_v3_PerXdsConfig_listener_config(const envoy_service_status_v3_PerXdsConfig *msg) { return UPB_READ_ONEOF(msg, const struct envoy_admin_v3_ListenersConfigDump*, UPB_SIZE(8, 8), UPB_SIZE(12, 16), 2, NULL); } +UPB_INLINE bool envoy_service_status_v3_PerXdsConfig_has_cluster_config(const envoy_service_status_v3_PerXdsConfig *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 16)) == 3; } +UPB_INLINE const struct envoy_admin_v3_ClustersConfigDump* envoy_service_status_v3_PerXdsConfig_cluster_config(const envoy_service_status_v3_PerXdsConfig *msg) { return UPB_READ_ONEOF(msg, const struct envoy_admin_v3_ClustersConfigDump*, UPB_SIZE(8, 8), UPB_SIZE(12, 16), 3, NULL); } +UPB_INLINE bool envoy_service_status_v3_PerXdsConfig_has_route_config(const envoy_service_status_v3_PerXdsConfig *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 16)) == 4; } +UPB_INLINE const struct envoy_admin_v3_RoutesConfigDump* envoy_service_status_v3_PerXdsConfig_route_config(const envoy_service_status_v3_PerXdsConfig *msg) { return UPB_READ_ONEOF(msg, const struct envoy_admin_v3_RoutesConfigDump*, UPB_SIZE(8, 8), UPB_SIZE(12, 16), 4, NULL); } +UPB_INLINE bool envoy_service_status_v3_PerXdsConfig_has_scoped_route_config(const envoy_service_status_v3_PerXdsConfig *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 16)) == 5; } +UPB_INLINE const struct envoy_admin_v3_ScopedRoutesConfigDump* envoy_service_status_v3_PerXdsConfig_scoped_route_config(const envoy_service_status_v3_PerXdsConfig *msg) { return UPB_READ_ONEOF(msg, const struct envoy_admin_v3_ScopedRoutesConfigDump*, UPB_SIZE(8, 8), UPB_SIZE(12, 16), 5, NULL); } +UPB_INLINE bool envoy_service_status_v3_PerXdsConfig_has_endpoint_config(const envoy_service_status_v3_PerXdsConfig *msg) { return _upb_getoneofcase(msg, UPB_SIZE(12, 16)) == 6; } +UPB_INLINE const struct envoy_admin_v3_EndpointsConfigDump* envoy_service_status_v3_PerXdsConfig_endpoint_config(const envoy_service_status_v3_PerXdsConfig *msg) { return UPB_READ_ONEOF(msg, const struct envoy_admin_v3_EndpointsConfigDump*, UPB_SIZE(8, 8), UPB_SIZE(12, 16), 6, NULL); } +UPB_INLINE int32_t envoy_service_status_v3_PerXdsConfig_client_status(const envoy_service_status_v3_PerXdsConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); } + +UPB_INLINE void envoy_service_status_v3_PerXdsConfig_set_status(envoy_service_status_v3_PerXdsConfig *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(0, 0), int32_t) = value; +} +UPB_INLINE void envoy_service_status_v3_PerXdsConfig_set_listener_config(envoy_service_status_v3_PerXdsConfig *msg, struct envoy_admin_v3_ListenersConfigDump* value) { + UPB_WRITE_ONEOF(msg, struct envoy_admin_v3_ListenersConfigDump*, UPB_SIZE(8, 8), value, UPB_SIZE(12, 16), 2); +} +UPB_INLINE struct envoy_admin_v3_ListenersConfigDump* envoy_service_status_v3_PerXdsConfig_mutable_listener_config(envoy_service_status_v3_PerXdsConfig *msg, upb_arena *arena) { + struct envoy_admin_v3_ListenersConfigDump* sub = (struct envoy_admin_v3_ListenersConfigDump*)envoy_service_status_v3_PerXdsConfig_listener_config(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_ListenersConfigDump*)_upb_msg_new(&envoy_admin_v3_ListenersConfigDump_msginit, arena); + if (!sub) return NULL; + envoy_service_status_v3_PerXdsConfig_set_listener_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_service_status_v3_PerXdsConfig_set_cluster_config(envoy_service_status_v3_PerXdsConfig *msg, struct envoy_admin_v3_ClustersConfigDump* value) { + UPB_WRITE_ONEOF(msg, struct envoy_admin_v3_ClustersConfigDump*, UPB_SIZE(8, 8), value, UPB_SIZE(12, 16), 3); +} +UPB_INLINE struct envoy_admin_v3_ClustersConfigDump* envoy_service_status_v3_PerXdsConfig_mutable_cluster_config(envoy_service_status_v3_PerXdsConfig *msg, upb_arena *arena) { + struct envoy_admin_v3_ClustersConfigDump* sub = (struct envoy_admin_v3_ClustersConfigDump*)envoy_service_status_v3_PerXdsConfig_cluster_config(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_ClustersConfigDump*)_upb_msg_new(&envoy_admin_v3_ClustersConfigDump_msginit, arena); + if (!sub) return NULL; + envoy_service_status_v3_PerXdsConfig_set_cluster_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_service_status_v3_PerXdsConfig_set_route_config(envoy_service_status_v3_PerXdsConfig *msg, struct envoy_admin_v3_RoutesConfigDump* value) { + UPB_WRITE_ONEOF(msg, struct envoy_admin_v3_RoutesConfigDump*, UPB_SIZE(8, 8), value, UPB_SIZE(12, 16), 4); +} +UPB_INLINE struct envoy_admin_v3_RoutesConfigDump* envoy_service_status_v3_PerXdsConfig_mutable_route_config(envoy_service_status_v3_PerXdsConfig *msg, upb_arena *arena) { + struct envoy_admin_v3_RoutesConfigDump* sub = (struct envoy_admin_v3_RoutesConfigDump*)envoy_service_status_v3_PerXdsConfig_route_config(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_RoutesConfigDump*)_upb_msg_new(&envoy_admin_v3_RoutesConfigDump_msginit, arena); + if (!sub) return NULL; + envoy_service_status_v3_PerXdsConfig_set_route_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_service_status_v3_PerXdsConfig_set_scoped_route_config(envoy_service_status_v3_PerXdsConfig *msg, struct envoy_admin_v3_ScopedRoutesConfigDump* value) { + UPB_WRITE_ONEOF(msg, struct envoy_admin_v3_ScopedRoutesConfigDump*, UPB_SIZE(8, 8), value, UPB_SIZE(12, 16), 5); +} +UPB_INLINE struct envoy_admin_v3_ScopedRoutesConfigDump* envoy_service_status_v3_PerXdsConfig_mutable_scoped_route_config(envoy_service_status_v3_PerXdsConfig *msg, upb_arena *arena) { + struct envoy_admin_v3_ScopedRoutesConfigDump* sub = (struct envoy_admin_v3_ScopedRoutesConfigDump*)envoy_service_status_v3_PerXdsConfig_scoped_route_config(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_ScopedRoutesConfigDump*)_upb_msg_new(&envoy_admin_v3_ScopedRoutesConfigDump_msginit, arena); + if (!sub) return NULL; + envoy_service_status_v3_PerXdsConfig_set_scoped_route_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_service_status_v3_PerXdsConfig_set_endpoint_config(envoy_service_status_v3_PerXdsConfig *msg, struct envoy_admin_v3_EndpointsConfigDump* value) { + UPB_WRITE_ONEOF(msg, struct envoy_admin_v3_EndpointsConfigDump*, UPB_SIZE(8, 8), value, UPB_SIZE(12, 16), 6); +} +UPB_INLINE struct envoy_admin_v3_EndpointsConfigDump* envoy_service_status_v3_PerXdsConfig_mutable_endpoint_config(envoy_service_status_v3_PerXdsConfig *msg, upb_arena *arena) { + struct envoy_admin_v3_EndpointsConfigDump* sub = (struct envoy_admin_v3_EndpointsConfigDump*)envoy_service_status_v3_PerXdsConfig_endpoint_config(msg); + if (sub == NULL) { + sub = (struct envoy_admin_v3_EndpointsConfigDump*)_upb_msg_new(&envoy_admin_v3_EndpointsConfigDump_msginit, arena); + if (!sub) return NULL; + envoy_service_status_v3_PerXdsConfig_set_endpoint_config(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_service_status_v3_PerXdsConfig_set_client_status(envoy_service_status_v3_PerXdsConfig *msg, int32_t value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; +} + +/* envoy.service.status.v3.ClientConfig */ + +UPB_INLINE envoy_service_status_v3_ClientConfig *envoy_service_status_v3_ClientConfig_new(upb_arena *arena) { + return (envoy_service_status_v3_ClientConfig *)_upb_msg_new(&envoy_service_status_v3_ClientConfig_msginit, arena); +} +UPB_INLINE envoy_service_status_v3_ClientConfig *envoy_service_status_v3_ClientConfig_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_service_status_v3_ClientConfig *ret = envoy_service_status_v3_ClientConfig_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_service_status_v3_ClientConfig_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_service_status_v3_ClientConfig *envoy_service_status_v3_ClientConfig_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_service_status_v3_ClientConfig *ret = envoy_service_status_v3_ClientConfig_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_service_status_v3_ClientConfig_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_service_status_v3_ClientConfig_serialize(const envoy_service_status_v3_ClientConfig *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_status_v3_ClientConfig_msginit, arena, len); +} + +UPB_INLINE bool envoy_service_status_v3_ClientConfig_has_node(const envoy_service_status_v3_ClientConfig *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_core_v3_Node* envoy_service_status_v3_ClientConfig_node(const envoy_service_status_v3_ClientConfig *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_config_core_v3_Node*); } +UPB_INLINE bool envoy_service_status_v3_ClientConfig_has_xds_config(const envoy_service_status_v3_ClientConfig *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const envoy_service_status_v3_PerXdsConfig* const* envoy_service_status_v3_ClientConfig_xds_config(const envoy_service_status_v3_ClientConfig *msg, size_t *len) { return (const envoy_service_status_v3_PerXdsConfig* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } + +UPB_INLINE void envoy_service_status_v3_ClientConfig_set_node(envoy_service_status_v3_ClientConfig *msg, struct envoy_config_core_v3_Node* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_config_core_v3_Node*) = value; +} +UPB_INLINE struct envoy_config_core_v3_Node* envoy_service_status_v3_ClientConfig_mutable_node(envoy_service_status_v3_ClientConfig *msg, upb_arena *arena) { + struct envoy_config_core_v3_Node* sub = (struct envoy_config_core_v3_Node*)envoy_service_status_v3_ClientConfig_node(msg); + if (sub == NULL) { + sub = (struct envoy_config_core_v3_Node*)_upb_msg_new(&envoy_config_core_v3_Node_msginit, arena); + if (!sub) return NULL; + envoy_service_status_v3_ClientConfig_set_node(msg, sub); + } + return sub; +} +UPB_INLINE envoy_service_status_v3_PerXdsConfig** envoy_service_status_v3_ClientConfig_mutable_xds_config(envoy_service_status_v3_ClientConfig *msg, size_t *len) { + return (envoy_service_status_v3_PerXdsConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE envoy_service_status_v3_PerXdsConfig** envoy_service_status_v3_ClientConfig_resize_xds_config(envoy_service_status_v3_ClientConfig *msg, size_t len, upb_arena *arena) { + return (envoy_service_status_v3_PerXdsConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_service_status_v3_PerXdsConfig* envoy_service_status_v3_ClientConfig_add_xds_config(envoy_service_status_v3_ClientConfig *msg, upb_arena *arena) { + struct envoy_service_status_v3_PerXdsConfig* sub = (struct envoy_service_status_v3_PerXdsConfig*)_upb_msg_new(&envoy_service_status_v3_PerXdsConfig_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +/* envoy.service.status.v3.ClientStatusResponse */ + +UPB_INLINE envoy_service_status_v3_ClientStatusResponse *envoy_service_status_v3_ClientStatusResponse_new(upb_arena *arena) { + return (envoy_service_status_v3_ClientStatusResponse *)_upb_msg_new(&envoy_service_status_v3_ClientStatusResponse_msginit, arena); +} +UPB_INLINE envoy_service_status_v3_ClientStatusResponse *envoy_service_status_v3_ClientStatusResponse_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_service_status_v3_ClientStatusResponse *ret = envoy_service_status_v3_ClientStatusResponse_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_service_status_v3_ClientStatusResponse_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_service_status_v3_ClientStatusResponse *envoy_service_status_v3_ClientStatusResponse_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_service_status_v3_ClientStatusResponse *ret = envoy_service_status_v3_ClientStatusResponse_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_service_status_v3_ClientStatusResponse_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_service_status_v3_ClientStatusResponse_serialize(const envoy_service_status_v3_ClientStatusResponse *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_service_status_v3_ClientStatusResponse_msginit, arena, len); +} + +UPB_INLINE bool envoy_service_status_v3_ClientStatusResponse_has_config(const envoy_service_status_v3_ClientStatusResponse *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(0, 0)); } +UPB_INLINE const envoy_service_status_v3_ClientConfig* const* envoy_service_status_v3_ClientStatusResponse_config(const envoy_service_status_v3_ClientStatusResponse *msg, size_t *len) { return (const envoy_service_status_v3_ClientConfig* const*)_upb_array_accessor(msg, UPB_SIZE(0, 0), len); } + +UPB_INLINE envoy_service_status_v3_ClientConfig** envoy_service_status_v3_ClientStatusResponse_mutable_config(envoy_service_status_v3_ClientStatusResponse *msg, size_t *len) { + return (envoy_service_status_v3_ClientConfig**)_upb_array_mutable_accessor(msg, UPB_SIZE(0, 0), len); +} +UPB_INLINE envoy_service_status_v3_ClientConfig** envoy_service_status_v3_ClientStatusResponse_resize_config(envoy_service_status_v3_ClientStatusResponse *msg, size_t len, upb_arena *arena) { + return (envoy_service_status_v3_ClientConfig**)_upb_array_resize_accessor2(msg, UPB_SIZE(0, 0), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_service_status_v3_ClientConfig* envoy_service_status_v3_ClientStatusResponse_add_config(envoy_service_status_v3_ClientStatusResponse *msg, upb_arena *arena) { + struct envoy_service_status_v3_ClientConfig* sub = (struct envoy_service_status_v3_ClientConfig*)_upb_msg_new(&envoy_service_status_v3_ClientConfig_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_SERVICE_STATUS_V3_CSDS_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c b/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c new file mode 100644 index 00000000000..8ef51fb91ec --- /dev/null +++ b/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c @@ -0,0 +1,36 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/node.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/type/matcher/v3/node.upb.h" +#include "envoy/type/matcher/v3/string.upb.h" +#include "envoy/type/matcher/v3/struct.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_type_matcher_v3_NodeMatcher_submsgs[2] = { + &envoy_type_matcher_v3_StringMatcher_msginit, + &envoy_type_matcher_v3_StructMatcher_msginit, +}; + +static const upb_msglayout_field envoy_type_matcher_v3_NodeMatcher__fields[2] = { + {1, UPB_SIZE(4, 8), 1, 0, 11, 1}, + {2, UPB_SIZE(8, 16), 0, 1, 11, 3}, +}; + +const upb_msglayout envoy_type_matcher_v3_NodeMatcher_msginit = { + &envoy_type_matcher_v3_NodeMatcher_submsgs[0], + &envoy_type_matcher_v3_NodeMatcher__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h b/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h new file mode 100644 index 00000000000..94e2257fdfc --- /dev/null +++ b/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h @@ -0,0 +1,90 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/node.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_TYPE_MATCHER_V3_NODE_PROTO_UPB_H_ +#define ENVOY_TYPE_MATCHER_V3_NODE_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_type_matcher_v3_NodeMatcher; +typedef struct envoy_type_matcher_v3_NodeMatcher envoy_type_matcher_v3_NodeMatcher; +extern const upb_msglayout envoy_type_matcher_v3_NodeMatcher_msginit; +struct envoy_type_matcher_v3_StringMatcher; +struct envoy_type_matcher_v3_StructMatcher; +extern const upb_msglayout envoy_type_matcher_v3_StringMatcher_msginit; +extern const upb_msglayout envoy_type_matcher_v3_StructMatcher_msginit; + + +/* envoy.type.matcher.v3.NodeMatcher */ + +UPB_INLINE envoy_type_matcher_v3_NodeMatcher *envoy_type_matcher_v3_NodeMatcher_new(upb_arena *arena) { + return (envoy_type_matcher_v3_NodeMatcher *)_upb_msg_new(&envoy_type_matcher_v3_NodeMatcher_msginit, arena); +} +UPB_INLINE envoy_type_matcher_v3_NodeMatcher *envoy_type_matcher_v3_NodeMatcher_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_type_matcher_v3_NodeMatcher *ret = envoy_type_matcher_v3_NodeMatcher_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_type_matcher_v3_NodeMatcher_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_type_matcher_v3_NodeMatcher *envoy_type_matcher_v3_NodeMatcher_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_type_matcher_v3_NodeMatcher *ret = envoy_type_matcher_v3_NodeMatcher_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_type_matcher_v3_NodeMatcher_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_type_matcher_v3_NodeMatcher_serialize(const envoy_type_matcher_v3_NodeMatcher *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_type_matcher_v3_NodeMatcher_msginit, arena, len); +} + +UPB_INLINE bool envoy_type_matcher_v3_NodeMatcher_has_node_id(const envoy_type_matcher_v3_NodeMatcher *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_type_matcher_v3_StringMatcher* envoy_type_matcher_v3_NodeMatcher_node_id(const envoy_type_matcher_v3_NodeMatcher *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_type_matcher_v3_StringMatcher*); } +UPB_INLINE bool envoy_type_matcher_v3_NodeMatcher_has_node_metadatas(const envoy_type_matcher_v3_NodeMatcher *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const struct envoy_type_matcher_v3_StructMatcher* const* envoy_type_matcher_v3_NodeMatcher_node_metadatas(const envoy_type_matcher_v3_NodeMatcher *msg, size_t *len) { return (const struct envoy_type_matcher_v3_StructMatcher* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } + +UPB_INLINE void envoy_type_matcher_v3_NodeMatcher_set_node_id(envoy_type_matcher_v3_NodeMatcher *msg, struct envoy_type_matcher_v3_StringMatcher* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_type_matcher_v3_StringMatcher*) = value; +} +UPB_INLINE struct envoy_type_matcher_v3_StringMatcher* envoy_type_matcher_v3_NodeMatcher_mutable_node_id(envoy_type_matcher_v3_NodeMatcher *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_StringMatcher* sub = (struct envoy_type_matcher_v3_StringMatcher*)envoy_type_matcher_v3_NodeMatcher_node_id(msg); + if (sub == NULL) { + sub = (struct envoy_type_matcher_v3_StringMatcher*)_upb_msg_new(&envoy_type_matcher_v3_StringMatcher_msginit, arena); + if (!sub) return NULL; + envoy_type_matcher_v3_NodeMatcher_set_node_id(msg, sub); + } + return sub; +} +UPB_INLINE struct envoy_type_matcher_v3_StructMatcher** envoy_type_matcher_v3_NodeMatcher_mutable_node_metadatas(envoy_type_matcher_v3_NodeMatcher *msg, size_t *len) { + return (struct envoy_type_matcher_v3_StructMatcher**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE struct envoy_type_matcher_v3_StructMatcher** envoy_type_matcher_v3_NodeMatcher_resize_node_metadatas(envoy_type_matcher_v3_NodeMatcher *msg, size_t len, upb_arena *arena) { + return (struct envoy_type_matcher_v3_StructMatcher**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_type_matcher_v3_StructMatcher* envoy_type_matcher_v3_NodeMatcher_add_node_metadatas(envoy_type_matcher_v3_NodeMatcher *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_StructMatcher* sub = (struct envoy_type_matcher_v3_StructMatcher*)_upb_msg_new(&envoy_type_matcher_v3_StructMatcher_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_TYPE_MATCHER_V3_NODE_PROTO_UPB_H_ */ diff --git a/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c b/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c new file mode 100644 index 00000000000..05ea6a3ffcb --- /dev/null +++ b/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c @@ -0,0 +1,46 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/struct.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include +#include "upb/msg.h" +#include "envoy/type/matcher/v3/struct.upb.h" +#include "envoy/type/matcher/v3/value.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" +#include "validate/validate.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout *const envoy_type_matcher_v3_StructMatcher_submsgs[2] = { + &envoy_type_matcher_v3_StructMatcher_PathSegment_msginit, + &envoy_type_matcher_v3_ValueMatcher_msginit, +}; + +static const upb_msglayout_field envoy_type_matcher_v3_StructMatcher__fields[2] = { + {2, UPB_SIZE(8, 16), 0, 0, 11, 3}, + {3, UPB_SIZE(4, 8), 1, 1, 11, 1}, +}; + +const upb_msglayout envoy_type_matcher_v3_StructMatcher_msginit = { + &envoy_type_matcher_v3_StructMatcher_submsgs[0], + &envoy_type_matcher_v3_StructMatcher__fields[0], + UPB_SIZE(16, 24), 2, false, 255, +}; + +static const upb_msglayout_field envoy_type_matcher_v3_StructMatcher_PathSegment__fields[1] = { + {1, UPB_SIZE(0, 0), UPB_SIZE(-9, -17), 0, 9, 1}, +}; + +const upb_msglayout envoy_type_matcher_v3_StructMatcher_PathSegment_msginit = { + NULL, + &envoy_type_matcher_v3_StructMatcher_PathSegment__fields[0], + UPB_SIZE(16, 32), 1, false, 255, +}; + +#include "upb/port_undef.inc" + diff --git a/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h b/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h new file mode 100644 index 00000000000..53e521385de --- /dev/null +++ b/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h @@ -0,0 +1,124 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/struct.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_TYPE_MATCHER_V3_STRUCT_PROTO_UPB_H_ +#define ENVOY_TYPE_MATCHER_V3_STRUCT_PROTO_UPB_H_ + +#include "upb/msg.h" +#include "upb/decode.h" +#include "upb/decode_fast.h" +#include "upb/encode.h" + +#include "upb/port_def.inc" + +#ifdef __cplusplus +extern "C" { +#endif + +struct envoy_type_matcher_v3_StructMatcher; +struct envoy_type_matcher_v3_StructMatcher_PathSegment; +typedef struct envoy_type_matcher_v3_StructMatcher envoy_type_matcher_v3_StructMatcher; +typedef struct envoy_type_matcher_v3_StructMatcher_PathSegment envoy_type_matcher_v3_StructMatcher_PathSegment; +extern const upb_msglayout envoy_type_matcher_v3_StructMatcher_msginit; +extern const upb_msglayout envoy_type_matcher_v3_StructMatcher_PathSegment_msginit; +struct envoy_type_matcher_v3_ValueMatcher; +extern const upb_msglayout envoy_type_matcher_v3_ValueMatcher_msginit; + + +/* envoy.type.matcher.v3.StructMatcher */ + +UPB_INLINE envoy_type_matcher_v3_StructMatcher *envoy_type_matcher_v3_StructMatcher_new(upb_arena *arena) { + return (envoy_type_matcher_v3_StructMatcher *)_upb_msg_new(&envoy_type_matcher_v3_StructMatcher_msginit, arena); +} +UPB_INLINE envoy_type_matcher_v3_StructMatcher *envoy_type_matcher_v3_StructMatcher_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_type_matcher_v3_StructMatcher *ret = envoy_type_matcher_v3_StructMatcher_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_type_matcher_v3_StructMatcher_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_type_matcher_v3_StructMatcher *envoy_type_matcher_v3_StructMatcher_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_type_matcher_v3_StructMatcher *ret = envoy_type_matcher_v3_StructMatcher_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_type_matcher_v3_StructMatcher_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_type_matcher_v3_StructMatcher_serialize(const envoy_type_matcher_v3_StructMatcher *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_type_matcher_v3_StructMatcher_msginit, arena, len); +} + +UPB_INLINE bool envoy_type_matcher_v3_StructMatcher_has_path(const envoy_type_matcher_v3_StructMatcher *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(8, 16)); } +UPB_INLINE const envoy_type_matcher_v3_StructMatcher_PathSegment* const* envoy_type_matcher_v3_StructMatcher_path(const envoy_type_matcher_v3_StructMatcher *msg, size_t *len) { return (const envoy_type_matcher_v3_StructMatcher_PathSegment* const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len); } +UPB_INLINE bool envoy_type_matcher_v3_StructMatcher_has_value(const envoy_type_matcher_v3_StructMatcher *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_type_matcher_v3_ValueMatcher* envoy_type_matcher_v3_StructMatcher_value(const envoy_type_matcher_v3_StructMatcher *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_type_matcher_v3_ValueMatcher*); } + +UPB_INLINE envoy_type_matcher_v3_StructMatcher_PathSegment** envoy_type_matcher_v3_StructMatcher_mutable_path(envoy_type_matcher_v3_StructMatcher *msg, size_t *len) { + return (envoy_type_matcher_v3_StructMatcher_PathSegment**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), len); +} +UPB_INLINE envoy_type_matcher_v3_StructMatcher_PathSegment** envoy_type_matcher_v3_StructMatcher_resize_path(envoy_type_matcher_v3_StructMatcher *msg, size_t len, upb_arena *arena) { + return (envoy_type_matcher_v3_StructMatcher_PathSegment**)_upb_array_resize_accessor2(msg, UPB_SIZE(8, 16), len, UPB_SIZE(2, 3), arena); +} +UPB_INLINE struct envoy_type_matcher_v3_StructMatcher_PathSegment* envoy_type_matcher_v3_StructMatcher_add_path(envoy_type_matcher_v3_StructMatcher *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_StructMatcher_PathSegment* sub = (struct envoy_type_matcher_v3_StructMatcher_PathSegment*)_upb_msg_new(&envoy_type_matcher_v3_StructMatcher_PathSegment_msginit, arena); + bool ok = _upb_array_append_accessor2( + msg, UPB_SIZE(8, 16), UPB_SIZE(2, 3), &sub, arena); + if (!ok) return NULL; + return sub; +} +UPB_INLINE void envoy_type_matcher_v3_StructMatcher_set_value(envoy_type_matcher_v3_StructMatcher *msg, struct envoy_type_matcher_v3_ValueMatcher* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_type_matcher_v3_ValueMatcher*) = value; +} +UPB_INLINE struct envoy_type_matcher_v3_ValueMatcher* envoy_type_matcher_v3_StructMatcher_mutable_value(envoy_type_matcher_v3_StructMatcher *msg, upb_arena *arena) { + struct envoy_type_matcher_v3_ValueMatcher* sub = (struct envoy_type_matcher_v3_ValueMatcher*)envoy_type_matcher_v3_StructMatcher_value(msg); + if (sub == NULL) { + sub = (struct envoy_type_matcher_v3_ValueMatcher*)_upb_msg_new(&envoy_type_matcher_v3_ValueMatcher_msginit, arena); + if (!sub) return NULL; + envoy_type_matcher_v3_StructMatcher_set_value(msg, sub); + } + return sub; +} + +/* envoy.type.matcher.v3.StructMatcher.PathSegment */ + +UPB_INLINE envoy_type_matcher_v3_StructMatcher_PathSegment *envoy_type_matcher_v3_StructMatcher_PathSegment_new(upb_arena *arena) { + return (envoy_type_matcher_v3_StructMatcher_PathSegment *)_upb_msg_new(&envoy_type_matcher_v3_StructMatcher_PathSegment_msginit, arena); +} +UPB_INLINE envoy_type_matcher_v3_StructMatcher_PathSegment *envoy_type_matcher_v3_StructMatcher_PathSegment_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_type_matcher_v3_StructMatcher_PathSegment *ret = envoy_type_matcher_v3_StructMatcher_PathSegment_new(arena); + return (ret && upb_decode(buf, size, ret, &envoy_type_matcher_v3_StructMatcher_PathSegment_msginit, arena)) ? ret : NULL; +} +UPB_INLINE envoy_type_matcher_v3_StructMatcher_PathSegment *envoy_type_matcher_v3_StructMatcher_PathSegment_parse_ex(const char *buf, size_t size, + upb_arena *arena, int options) { + envoy_type_matcher_v3_StructMatcher_PathSegment *ret = envoy_type_matcher_v3_StructMatcher_PathSegment_new(arena); + return (ret && _upb_decode(buf, size, ret, &envoy_type_matcher_v3_StructMatcher_PathSegment_msginit, arena, options)) + ? ret : NULL; +} +UPB_INLINE char *envoy_type_matcher_v3_StructMatcher_PathSegment_serialize(const envoy_type_matcher_v3_StructMatcher_PathSegment *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_type_matcher_v3_StructMatcher_PathSegment_msginit, arena, len); +} + +typedef enum { + envoy_type_matcher_v3_StructMatcher_PathSegment_segment_key = 1, + envoy_type_matcher_v3_StructMatcher_PathSegment_segment_NOT_SET = 0 +} envoy_type_matcher_v3_StructMatcher_PathSegment_segment_oneofcases; +UPB_INLINE envoy_type_matcher_v3_StructMatcher_PathSegment_segment_oneofcases envoy_type_matcher_v3_StructMatcher_PathSegment_segment_case(const envoy_type_matcher_v3_StructMatcher_PathSegment* msg) { return (envoy_type_matcher_v3_StructMatcher_PathSegment_segment_oneofcases)*UPB_PTR_AT(msg, UPB_SIZE(8, 16), int32_t); } + +UPB_INLINE bool envoy_type_matcher_v3_StructMatcher_PathSegment_has_key(const envoy_type_matcher_v3_StructMatcher_PathSegment *msg) { return _upb_getoneofcase(msg, UPB_SIZE(8, 16)) == 1; } +UPB_INLINE upb_strview envoy_type_matcher_v3_StructMatcher_PathSegment_key(const envoy_type_matcher_v3_StructMatcher_PathSegment *msg) { return UPB_READ_ONEOF(msg, upb_strview, UPB_SIZE(0, 0), UPB_SIZE(8, 16), 1, upb_strview_make("", strlen(""))); } + +UPB_INLINE void envoy_type_matcher_v3_StructMatcher_PathSegment_set_key(envoy_type_matcher_v3_StructMatcher_PathSegment *msg, upb_strview value) { + UPB_WRITE_ONEOF(msg, upb_strview, UPB_SIZE(0, 0), value, UPB_SIZE(8, 16), 1); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_TYPE_MATCHER_V3_STRUCT_PROTO_UPB_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c new file mode 100644 index 00000000000..8418d1e9284 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c @@ -0,0 +1,354 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/admin/v3/config_dump.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/admin/v3/config_dump.upbdefs.h" + +extern upb_def_init envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit; +extern upb_def_init google_protobuf_any_proto_upbdefinit; +extern upb_def_init google_protobuf_timestamp_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern const upb_msglayout envoy_admin_v3_ConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_UpdateFailureState_msginit; +extern const upb_msglayout envoy_admin_v3_BootstrapConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_StaticListener_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit; +extern const upb_msglayout envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit; +extern const upb_msglayout envoy_admin_v3_ClustersConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit; +extern const upb_msglayout envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit; +extern const upb_msglayout envoy_admin_v3_RoutesConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit; +extern const upb_msglayout envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit; +extern const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit; +extern const upb_msglayout envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit; +extern const upb_msglayout envoy_admin_v3_SecretsConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit; +extern const upb_msglayout envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit; +extern const upb_msglayout envoy_admin_v3_EndpointsConfigDump_msginit; +extern const upb_msglayout envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit; +extern const upb_msglayout envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit; + +static const upb_msglayout *layouts[22] = { + &envoy_admin_v3_ConfigDump_msginit, + &envoy_admin_v3_UpdateFailureState_msginit, + &envoy_admin_v3_BootstrapConfigDump_msginit, + &envoy_admin_v3_ListenersConfigDump_msginit, + &envoy_admin_v3_ListenersConfigDump_StaticListener_msginit, + &envoy_admin_v3_ListenersConfigDump_DynamicListenerState_msginit, + &envoy_admin_v3_ListenersConfigDump_DynamicListener_msginit, + &envoy_admin_v3_ClustersConfigDump_msginit, + &envoy_admin_v3_ClustersConfigDump_StaticCluster_msginit, + &envoy_admin_v3_ClustersConfigDump_DynamicCluster_msginit, + &envoy_admin_v3_RoutesConfigDump_msginit, + &envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_msginit, + &envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_msginit, + &envoy_admin_v3_ScopedRoutesConfigDump_msginit, + &envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_msginit, + &envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_msginit, + &envoy_admin_v3_SecretsConfigDump_msginit, + &envoy_admin_v3_SecretsConfigDump_DynamicSecret_msginit, + &envoy_admin_v3_SecretsConfigDump_StaticSecret_msginit, + &envoy_admin_v3_EndpointsConfigDump_msginit, + &envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_msginit, + &envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_msginit, +}; + +static const char descriptor[6802] = {'\n', ' ', 'e', 'n', 'v', 'o', 'y', '/', 'a', 'd', 'm', 'i', 'n', '/', 'v', '3', '/', 'c', 'o', 'n', 'f', 'i', 'g', '_', 'd', +'u', 'm', 'p', '.', 'p', 'r', 'o', 't', 'o', '\022', '\016', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', +'\032', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '/', +'v', '3', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'p', 'r', 'o', 't', 'o', '\032', '\031', 'g', 'o', 'o', 'g', 'l', +'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'g', 'o', 'o', +'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', '.', 'p', 'r', +'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', +'t', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', +'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\"', 'c', '\n', '\n', 'C', 'o', +'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\022', '.', '\n', '\007', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\001', ' ', '\003', '(', '\013', +'2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\007', 'c', +'o', 'n', 'f', 'i', 'g', 's', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', +'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\"', '\225', '\002', '\n', '\022', +'U', 'p', 'd', 'a', 't', 'e', 'F', 'a', 'i', 'l', 'u', 'r', 'e', 'S', 't', 'a', 't', 'e', '\022', 'G', '\n', '\024', 'f', 'a', 'i', +'l', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\023', 'f', 'a', 'i', +'l', 'e', 'd', 'C', 'o', 'n', 'f', 'i', 'g', 'u', 'r', 'a', 't', 'i', 'o', 'n', '\022', 'J', '\n', '\023', 'l', 'a', 's', 't', '_', +'u', 'p', 'd', 'a', 't', 'e', '_', 'a', 't', 't', 'e', 'm', 'p', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\021', +'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'A', 't', 't', 'e', 'm', 'p', 't', '\022', '\030', '\n', '\007', 'd', 'e', 't', 'a', +'i', 'l', 's', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\007', 'd', 'e', 't', 'a', 'i', 'l', 's', '\022', '!', '\n', '\014', 'v', 'e', 'r', +'s', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\004', ' ', '\001', '(', '\t', 'R', '\013', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'I', +'n', 'f', 'o', ':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', +'2', 'a', 'l', 'p', 'h', 'a', '.', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'a', 'i', 'l', 'u', 'r', 'e', 'S', 't', 'a', 't', 'e', +'\"', '\310', '\001', '\n', '\023', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\022', +'B', '\n', '\t', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '\030', '\001', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', +'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'B', 'o', 'o', +'t', 's', 't', 'r', 'a', 'p', 'R', '\t', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', +'_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', +'d', 'a', 't', 'e', 'd', ':', '.', '\232', '\305', '\210', '\036', ')', '\n', '\'', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', +'.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'C', 'o', 'n', 'f', 'i', 'g', 'D', +'u', 'm', 'p', '\"', '\363', '\t', '\n', '\023', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', +'m', 'p', '\022', '!', '\n', '\014', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\001', ' ', '\001', '(', '\t', 'R', +'\013', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'f', 'o', '\022', ']', '\n', '\020', 's', 't', 'a', 't', 'i', 'c', '_', 'l', 'i', +'s', 't', 'e', 'n', 'e', 'r', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', +'i', 'n', '.', 'v', '3', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', +'.', 'S', 't', 'a', 't', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'R', '\017', 's', 't', 'a', 't', 'i', 'c', 'L', 'i', +'s', 't', 'e', 'n', 'e', 'r', 's', '\022', '`', '\n', '\021', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'l', 'i', 's', 't', 'e', 'n', +'e', 'r', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '3', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', +'3', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', +'a', 'm', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'R', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'L', 'i', 's', 't', +'e', 'n', 'e', 'r', 's', '\032', '\300', '\001', '\n', '\016', 'S', 't', 'a', 't', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '\022', +'0', '\n', '\010', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\010', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '\022', +'=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', +'\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'd', ':', '=', '\232', '\305', '\210', '\036', '8', '\n', '6', 'e', 'n', 'v', 'o', +'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', +'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', +'\032', '\357', '\001', '\n', '\024', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'S', 't', 'a', 't', 'e', +'\022', '!', '\n', '\014', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'v', +'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'f', 'o', '\022', '0', '\n', '\010', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '\030', '\002', ' ', +'\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', +'R', '\010', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', +'d', '\030', '\003', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', +'.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'd', ':', 'C', +'\232', '\305', '\210', '\036', '>', '\n', '<', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', +'a', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', +'a', 'm', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'S', 't', 'a', 't', 'e', '\032', '\222', '\004', '\n', '\017', 'D', 'y', 'n', +'a', 'm', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', +'\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '[', '\n', '\014', 'a', 'c', 't', 'i', 'v', 'e', '_', 's', 't', 'a', 't', 'e', '\030', '\002', +' ', '\001', '(', '\013', '2', '8', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'L', 'i', 's', +'t', 'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'L', +'i', 's', 't', 'e', 'n', 'e', 'r', 'S', 't', 'a', 't', 'e', 'R', '\013', 'a', 'c', 't', 'i', 'v', 'e', 'S', 't', 'a', 't', 'e', +'\022', ']', '\n', '\r', 'w', 'a', 'r', 'm', 'i', 'n', 'g', '_', 's', 't', 'a', 't', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '8', +'.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', +'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', +'r', 'S', 't', 'a', 't', 'e', 'R', '\014', 'w', 'a', 'r', 'm', 'i', 'n', 'g', 'S', 't', 'a', 't', 'e', '\022', '_', '\n', '\016', 'd', +'r', 'a', 'i', 'n', 'i', 'n', 'g', '_', 's', 't', 'a', 't', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '8', '.', 'e', 'n', 'v', +'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', +'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'S', 't', 'a', +'t', 'e', 'R', '\r', 'd', 'r', 'a', 'i', 'n', 'i', 'n', 'g', 'S', 't', 'a', 't', 'e', '\022', 'C', '\n', '\013', 'e', 'r', 'r', 'o', +'r', '_', 's', 't', 'a', 't', 'e', '\030', '\005', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', +'i', 'n', '.', 'v', '3', '.', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'a', 'i', 'l', 'u', 'r', 'e', 'S', 't', 'a', 't', 'e', 'R', +'\n', 'e', 'r', 'r', 'o', 'r', 'S', 't', 'a', 't', 'e', '\022', 'I', '\n', '\r', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', +'t', 'u', 's', '\030', '\006', ' ', '\001', '(', '\016', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', +'3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'S', 't', 'a', 't', 'u', 's', 'R', '\014', 'c', +'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', ':', '>', '\232', '\305', '\210', '\036', '9', '\n', '7', 'e', 'n', 'v', 'o', 'y', +'.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', 'C', +'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', +':', '.', '\232', '\305', '\210', '\036', ')', '\n', '\'', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', +'p', 'h', 'a', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\"', '\312', +'\007', '\n', '\022', 'C', 'l', 'u', 's', 't', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\022', '!', '\n', '\014', +'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'v', 'e', 'r', 's', 'i', +'o', 'n', 'I', 'n', 'f', 'o', '\022', 'Y', '\n', '\017', 's', 't', 'a', 't', 'i', 'c', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', 's', +'\030', '\002', ' ', '\003', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'C', +'l', 'u', 's', 't', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'C', +'l', 'u', 's', 't', 'e', 'r', 'R', '\016', 's', 't', 'a', 't', 'i', 'c', 'C', 'l', 'u', 's', 't', 'e', 'r', 's', '\022', 'i', '\n', +'\027', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'a', 'c', 't', 'i', 'v', 'e', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', 's', '\030', +'\003', ' ', '\003', '(', '\013', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'C', 'l', +'u', 's', 't', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'C', +'l', 'u', 's', 't', 'e', 'r', 'R', '\025', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'A', 'c', 't', 'i', 'v', 'e', 'C', 'l', 'u', 's', +'t', 'e', 'r', 's', '\022', 'k', '\n', '\030', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'w', 'a', 'r', 'm', 'i', 'n', 'g', '_', 'c', +'l', 'u', 's', 't', 'e', 'r', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', +'i', 'n', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', +'D', 'y', 'n', 'a', 'm', 'i', 'c', 'C', 'l', 'u', 's', 't', 'e', 'r', 'R', '\026', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'W', 'a', +'r', 'm', 'i', 'n', 'g', 'C', 'l', 'u', 's', 't', 'e', 'r', 's', '\032', '\273', '\001', '\n', '\r', 'S', 't', 'a', 't', 'i', 'c', 'C', +'l', 'u', 's', 't', 'e', 'r', '\022', '.', '\n', '\007', 'c', 'l', 'u', 's', 't', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\007', 'c', 'l', 'u', +'s', 't', 'e', 'r', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', +'\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', +'t', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'd', ':', ';', '\232', '\305', '\210', '\036', '6', '\n', +'4', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'C', 'l', 'u', 's', +'t', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'C', 'l', 'u', 's', +'t', 'e', 'r', '\032', '\360', '\002', '\n', '\016', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'C', 'l', 'u', 's', 't', 'e', 'r', '\022', '!', '\n', +'\014', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'v', 'e', 'r', 's', +'i', 'o', 'n', 'I', 'n', 'f', 'o', '\022', '.', '\n', '\007', 'c', 'l', 'u', 's', 't', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\013', '2', +'\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\007', 'c', 'l', +'u', 's', 't', 'e', 'r', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', +'(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', +'s', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'd', '\022', 'C', '\n', '\013', 'e', 'r', 'r', +'o', 'r', '_', 's', 't', 'a', 't', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', +'m', 'i', 'n', '.', 'v', '3', '.', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'a', 'i', 'l', 'u', 'r', 'e', 'S', 't', 'a', 't', 'e', +'R', '\n', 'e', 'r', 'r', 'o', 'r', 'S', 't', 'a', 't', 'e', '\022', 'I', '\n', '\r', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', +'a', 't', 'u', 's', '\030', '\005', ' ', '\001', '(', '\016', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', +'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'S', 't', 'a', 't', 'u', 's', 'R', '\014', +'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', ':', '<', '\232', '\305', '\210', '\036', '7', '\n', '5', 'e', 'n', 'v', 'o', +'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 's', 'C', +'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'C', 'l', 'u', 's', 't', 'e', 'r', ':', +'-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', +'h', 'a', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\"', '\335', '\006', '\n', +'\020', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\022', 'd', '\n', '\024', 's', 't', 'a', 't', +'i', 'c', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '2', '.', +'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', +'i', 'g', 'D', 'u', 'm', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 'R', +'\022', 's', 't', 'a', 't', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\022', 'g', '\n', '\025', 'd', 'y', +'n', 'a', 'm', 'i', 'c', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\003', ' ', '\003', '(', '\013', +'2', '3', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'R', 'o', 'u', 't', 'e', 's', 'C', +'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', +'f', 'i', 'g', 'R', '\023', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\032', +'\312', '\001', '\n', '\021', 'S', 't', 'a', 't', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '7', '\n', '\014', +'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\013', 'r', 'o', 'u', 't', 'e', 'C', 'o', 'n', +'f', 'i', 'g', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\013', +'2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', +'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'd', ':', '=', '\232', '\305', '\210', '\036', '8', '\n', '6', +'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'R', 'o', 'u', 't', 'e', +'s', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', +'n', 'f', 'i', 'g', '\032', '\377', '\002', '\n', '\022', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', +'i', 'g', '\022', '!', '\n', '\014', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\001', ' ', '\001', '(', '\t', 'R', +'\013', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'f', 'o', '\022', '7', '\n', '\014', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', +'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'A', 'n', 'y', 'R', '\013', 'r', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '=', '\n', '\014', 'l', 'a', +'s', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', +'U', 'p', 'd', 'a', 't', 'e', 'd', '\022', 'C', '\n', '\013', 'e', 'r', 'r', 'o', 'r', '_', 's', 't', 'a', 't', 'e', '\030', '\004', ' ', +'\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'U', 'p', 'd', 'a', +'t', 'e', 'F', 'a', 'i', 'l', 'u', 'r', 'e', 'S', 't', 'a', 't', 'e', 'R', '\n', 'e', 'r', 'r', 'o', 'r', 'S', 't', 'a', 't', +'e', '\022', 'I', '\n', '\r', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', 't', 'u', 's', '\030', '\005', ' ', '\001', '(', '\016', '2', +'$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'R', 'e', +'s', 'o', 'u', 'r', 'c', 'e', 'S', 't', 'a', 't', 'u', 's', 'R', '\014', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', +'s', ':', '>', '\232', '\305', '\210', '\036', '9', '\n', '7', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', +'l', 'p', 'h', 'a', '.', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', +'a', 'm', 'i', 'c', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', ':', '+', '\232', '\305', '\210', '\036', '&', '\n', '$', 'e', +'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'R', 'o', 'u', 't', 'e', 's', +'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\"', '\214', '\010', '\n', '\026', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', +'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\022', '~', '\n', '\033', 'i', 'n', 'l', 'i', 'n', 'e', '_', 's', 'c', +'o', 'p', 'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', +'?', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', +'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'I', 'n', 'l', 'i', 'n', 'e', 'S', 'c', 'o', 'p', +'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', 'R', '\030', 'i', 'n', 'l', 'i', 'n', 'e', 'S', 'c', 'o', +'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\022', '\201', '\001', '\n', '\034', 'd', 'y', 'n', 'a', 'm', +'i', 'c', '_', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\002', +' ', '\003', '(', '\013', '2', '@', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'S', 'c', 'o', +'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', +'i', 'c', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', 'R', '\031', 'd', 'y', 'n', +'a', 'm', 'i', 'c', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\032', '\201', '\002', +'\n', '\030', 'I', 'n', 'l', 'i', 'n', 'e', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', +'s', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'F', '\n', '\024', +'s', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\002', ' ', '\003', '(', +'\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\022', +'s', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\022', '=', '\n', '\014', 'l', 'a', 's', +'t', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', +'p', 'd', 'a', 't', 'e', 'd', ':', 'J', '\232', '\305', '\210', '\036', 'E', '\n', 'C', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', +'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', +'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'I', 'n', 'l', 'i', 'n', 'e', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', +'C', 'o', 'n', 'f', 'i', 'g', 's', '\032', '\266', '\003', '\n', '\031', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'S', 'c', 'o', 'p', 'e', 'd', +'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', +'\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '!', '\n', '\014', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\002', +' ', '\001', '(', '\t', 'R', '\013', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'f', 'o', '\022', 'F', '\n', '\024', 's', 'c', 'o', 'p', +'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\024', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\022', 's', 'c', 'o', 'p', +'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', +'d', 'a', 't', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', +'e', 'd', '\022', 'C', '\n', '\013', 'e', 'r', 'r', 'o', 'r', '_', 's', 't', 'a', 't', 'e', '\030', '\005', ' ', '\001', '(', '\013', '2', '\"', +'.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'a', 'i', +'l', 'u', 'r', 'e', 'S', 't', 'a', 't', 'e', 'R', '\n', 'e', 'r', 'r', 'o', 'r', 'S', 't', 'a', 't', 'e', '\022', 'I', '\n', '\r', +'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', 't', 'u', 's', '\030', '\006', ' ', '\001', '(', '\016', '2', '$', '.', 'e', 'n', 'v', +'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'R', 'e', 's', 'o', 'u', 'r', 'c', +'e', 'S', 't', 'a', 't', 'u', 's', 'R', '\014', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', ':', 'K', '\232', '\305', +'\210', '\036', 'F', '\n', 'D', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', +'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', +'n', 'a', 'm', 'i', 'c', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', 's', ':', '1', +'\232', '\305', '\210', '\036', ',', '\n', '*', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', +'a', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\"', +'\267', '\007', '\n', '\021', 'S', 'e', 'c', 'r', 'e', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '\022', 'U', '\n', '\016', +'s', 't', 'a', 't', 'i', 'c', '_', 's', 'e', 'c', 'r', 'e', 't', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '.', '.', 'e', 'n', +'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'S', 'e', 'c', 'r', 'e', 't', 's', 'C', 'o', 'n', 'f', 'i', +'g', 'D', 'u', 'm', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', 'S', 'e', 'c', 'r', 'e', 't', 'R', '\r', 's', 't', 'a', 't', 'i', +'c', 'S', 'e', 'c', 'r', 'e', 't', 's', '\022', 'e', '\n', '\026', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'a', 'c', 't', 'i', 'v', +'e', '_', 's', 'e', 'c', 'r', 'e', 't', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '/', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', +'d', 'm', 'i', 'n', '.', 'v', '3', '.', 'S', 'e', 'c', 'r', 'e', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', +'.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'S', 'e', 'c', 'r', 'e', 't', 'R', '\024', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'A', 'c', +'t', 'i', 'v', 'e', 'S', 'e', 'c', 'r', 'e', 't', 's', '\022', 'g', '\n', '\027', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'w', 'a', +'r', 'm', 'i', 'n', 'g', '_', 's', 'e', 'c', 'r', 'e', 't', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '/', '.', 'e', 'n', 'v', +'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'S', 'e', 'c', 'r', 'e', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', +'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'S', 'e', 'c', 'r', 'e', 't', 'R', '\025', 'd', 'y', 'n', 'a', 'm', +'i', 'c', 'W', 'a', 'r', 'm', 'i', 'n', 'g', 'S', 'e', 'c', 'r', 'e', 't', 's', '\032', '\377', '\002', '\n', '\r', 'D', 'y', 'n', 'a', +'m', 'i', 'c', 'S', 'e', 'c', 'r', 'e', 't', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', +'n', 'a', 'm', 'e', '\022', '!', '\n', '\014', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', 'o', '\030', '\002', ' ', '\001', '(', +'\t', 'R', '\013', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'f', 'o', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', +'d', 'a', 't', 'e', 'd', '\030', '\003', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', +'e', 'd', '\022', ',', '\n', '\006', 's', 'e', 'c', 'r', 'e', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\006', 's', 'e', 'c', 'r', 'e', 't', '\022', 'C', +'\n', '\013', 'e', 'r', 'r', 'o', 'r', '_', 's', 't', 'a', 't', 'e', '\030', '\005', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', +'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'a', 'i', 'l', 'u', 'r', 'e', +'S', 't', 'a', 't', 'e', 'R', '\n', 'e', 'r', 'r', 'o', 'r', 'S', 't', 'a', 't', 'e', '\022', 'I', '\n', '\r', 'c', 'l', 'i', 'e', +'n', 't', '_', 's', 't', 'a', 't', 'u', 's', '\030', '\006', ' ', '\001', '(', '\016', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', +'d', 'm', 'i', 'n', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'S', 't', 'a', +'t', 'u', 's', 'R', '\014', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', ':', ':', '\232', '\305', '\210', '\036', '5', '\n', +'3', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'S', 'e', 'c', 'r', +'e', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'S', 'e', 'c', 'r', +'e', 't', '\032', '\312', '\001', '\n', '\014', 'S', 't', 'a', 't', 'i', 'c', 'S', 'e', 'c', 'r', 'e', 't', '\022', '\022', '\n', '\004', 'n', 'a', +'m', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', +'d', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', +'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', +'e', 'd', '\022', ',', '\n', '\006', 's', 'e', 'c', 'r', 'e', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\006', 's', 'e', 'c', 'r', 'e', 't', ':', '9', +'\232', '\305', '\210', '\036', '4', '\n', '2', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', +'a', '.', 'S', 'e', 'c', 'r', 'e', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'S', 't', 'a', 't', 'i', +'c', 'S', 'e', 'c', 'r', 'e', 't', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', +'i', 'n', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'S', 'e', 'c', 'r', 'e', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', +'u', 'm', 'p', '\"', '\336', '\005', '\n', '\023', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', +'m', 'p', '\022', 'p', '\n', '\027', 's', 't', 'a', 't', 'i', 'c', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'c', 'o', 'n', +'f', 'i', 'g', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '8', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', +'v', '3', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'S', 't', +'a', 't', 'i', 'c', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\025', 's', 't', 'a', 't', 'i', +'c', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\022', 's', '\n', '\030', 'd', 'y', 'n', 'a', 'm', +'i', 'c', '_', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g', 's', '\030', '\003', ' ', '\003', '(', '\013', +'2', '9', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', +'t', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'E', 'n', 'd', 'p', 'o', +'i', 'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\026', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'E', 'n', 'd', 'p', 'o', 'i', 'n', +'t', 'C', 'o', 'n', 'f', 'i', 'g', 's', '\032', '\224', '\001', '\n', '\024', 'S', 't', 'a', 't', 'i', 'c', 'E', 'n', 'd', 'p', 'o', 'i', +'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '=', '\n', '\017', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'c', 'o', 'n', 'f', +'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'A', 'n', 'y', 'R', '\016', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '=', '\n', '\014', +'l', 'a', 's', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', +'s', 't', 'U', 'p', 'd', 'a', 't', 'e', 'd', '\032', '\310', '\002', '\n', '\025', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'E', 'n', 'd', 'p', +'o', 'i', 'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '!', '\n', '\014', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'i', 'n', 'f', +'o', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'f', 'o', '\022', '=', '\n', '\017', 'e', +'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\016', 'e', 'n', 'd', 'p', 'o', 'i', +'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '=', '\n', '\014', 'l', 'a', 's', 't', '_', 'u', 'p', 'd', 'a', 't', 'e', 'd', '\030', +'\003', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'T', +'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'R', '\013', 'l', 'a', 's', 't', 'U', 'p', 'd', 'a', 't', 'e', 'd', '\022', 'C', '\n', '\013', +'e', 'r', 'r', 'o', 'r', '_', 's', 't', 'a', 't', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', +'.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'U', 'p', 'd', 'a', 't', 'e', 'F', 'a', 'i', 'l', 'u', 'r', 'e', 'S', 't', +'a', 't', 'e', 'R', '\n', 'e', 'r', 'r', 'o', 'r', 'S', 't', 'a', 't', 'e', '\022', 'I', '\n', '\r', 'c', 'l', 'i', 'e', 'n', 't', +'_', 's', 't', 'a', 't', 'u', 's', '\030', '\005', ' ', '\001', '(', '\016', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', +'i', 'n', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'S', 't', 'a', 't', 'u', +'s', 'R', '\014', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', '*', ']', '\n', '\024', 'C', 'l', 'i', 'e', 'n', 't', +'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'S', 't', 'a', 't', 'u', 's', '\022', '\013', '\n', '\007', 'U', 'N', 'K', 'N', 'O', 'W', 'N', +'\020', '\000', '\022', '\r', '\n', '\t', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', 'E', 'D', '\020', '\001', '\022', '\022', '\n', '\016', 'D', 'O', 'E', 'S', +'_', 'N', 'O', 'T', '_', 'E', 'X', 'I', 'S', 'T', '\020', '\002', '\022', '\t', '\n', '\005', 'A', 'C', 'K', 'E', 'D', '\020', '\003', '\022', '\n', +'\n', '\006', 'N', 'A', 'C', 'K', 'E', 'D', '\020', '\004', 'B', '9', '\n', '\034', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', +'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', 'B', '\017', 'C', 'o', 'n', 'f', 'i', 'g', +'D', 'u', 'm', 'p', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', +'o', '3', +}; + +static upb_def_init *deps[6] = { + &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit, + &google_protobuf_any_proto_upbdefinit, + &google_protobuf_timestamp_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_admin_v3_config_dump_proto_upbdefinit = { + deps, + layouts, + "envoy/admin/v3/config_dump.proto", + UPB_STRVIEW_INIT(descriptor, 6802) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h new file mode 100644 index 00000000000..8e62d4e4444 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h @@ -0,0 +1,140 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/admin/v3/config_dump.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_ADMIN_V3_CONFIG_DUMP_PROTO_UPBDEFS_H_ +#define ENVOY_ADMIN_V3_CONFIG_DUMP_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_admin_v3_config_dump_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_UpdateFailureState_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.UpdateFailureState"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_BootstrapConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.BootstrapConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ListenersConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ListenersConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ListenersConfigDump_StaticListener_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ListenersConfigDump.StaticListener"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ListenersConfigDump_DynamicListenerState_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ListenersConfigDump.DynamicListenerState"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ListenersConfigDump_DynamicListener_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ListenersConfigDump.DynamicListener"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ClustersConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ClustersConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ClustersConfigDump_StaticCluster_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ClustersConfigDump.StaticCluster"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ClustersConfigDump_DynamicCluster_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ClustersConfigDump.DynamicCluster"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_RoutesConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.RoutesConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_RoutesConfigDump_StaticRouteConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.RoutesConfigDump.StaticRouteConfig"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.RoutesConfigDump.DynamicRouteConfig"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ScopedRoutesConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ScopedRoutesConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ScopedRoutesConfigDump_InlineScopedRouteConfigs_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ScopedRoutesConfigDump.InlineScopedRouteConfigs"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_ScopedRoutesConfigDump_DynamicScopedRouteConfigs_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.ScopedRoutesConfigDump.DynamicScopedRouteConfigs"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_SecretsConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.SecretsConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_SecretsConfigDump_DynamicSecret_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.SecretsConfigDump.DynamicSecret"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_SecretsConfigDump_StaticSecret_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.SecretsConfigDump.StaticSecret"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_EndpointsConfigDump_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.EndpointsConfigDump"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_EndpointsConfigDump_StaticEndpointConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.EndpointsConfigDump.StaticEndpointConfig"); +} + +UPB_INLINE const upb_msgdef *envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_admin_v3_config_dump_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.admin.v3.EndpointsConfigDump.DynamicEndpointConfig"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_ADMIN_V3_CONFIG_DUMP_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c new file mode 100644 index 00000000000..f86bfe76f4a --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c @@ -0,0 +1,383 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/bootstrap/v3/bootstrap.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/config/bootstrap/v3/bootstrap.upbdefs.h" + +extern upb_def_init envoy_config_cluster_v3_cluster_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_address_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_base_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_config_source_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_event_service_config_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_extension_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_socket_option_proto_upbdefinit; +extern upb_def_init envoy_config_listener_v3_listener_proto_upbdefinit; +extern upb_def_init envoy_config_metrics_v3_stats_proto_upbdefinit; +extern upb_def_init envoy_config_overload_v3_overload_proto_upbdefinit; +extern upb_def_init envoy_config_trace_v3_http_tracer_proto_upbdefinit; +extern upb_def_init envoy_extensions_transport_sockets_tls_v3_secret_proto_upbdefinit; +extern upb_def_init envoy_type_v3_percent_proto_upbdefinit; +extern upb_def_init google_protobuf_duration_proto_upbdefinit; +extern upb_def_init google_protobuf_struct_proto_upbdefinit; +extern upb_def_init google_protobuf_wrappers_proto_upbdefinit; +extern upb_def_init udpa_annotations_migrate_proto_upbdefinit; +extern upb_def_init udpa_annotations_security_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern upb_def_init validate_validate_proto_upbdefinit; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Admin_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_ClusterManager_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Watchdogs_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Watchdog_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_FatalAction_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_Runtime_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit; +extern const upb_msglayout envoy_config_bootstrap_v3_LayeredRuntime_msginit; + +static const upb_msglayout *layouts[17] = { + &envoy_config_bootstrap_v3_Bootstrap_msginit, + &envoy_config_bootstrap_v3_Bootstrap_StaticResources_msginit, + &envoy_config_bootstrap_v3_Bootstrap_DynamicResources_msginit, + &envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_msginit, + &envoy_config_bootstrap_v3_Admin_msginit, + &envoy_config_bootstrap_v3_ClusterManager_msginit, + &envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_msginit, + &envoy_config_bootstrap_v3_Watchdogs_msginit, + &envoy_config_bootstrap_v3_Watchdog_msginit, + &envoy_config_bootstrap_v3_Watchdog_WatchdogAction_msginit, + &envoy_config_bootstrap_v3_FatalAction_msginit, + &envoy_config_bootstrap_v3_Runtime_msginit, + &envoy_config_bootstrap_v3_RuntimeLayer_msginit, + &envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_msginit, + &envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_msginit, + &envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_msginit, + &envoy_config_bootstrap_v3_LayeredRuntime_msginit, +}; + +static const char descriptor[6993] = {'\n', ')', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '/', +'v', '3', '/', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'p', 'r', 'o', 't', 'o', '\022', '\031', 'e', 'n', 'v', 'o', 'y', +'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '\032', '%', 'e', 'n', 'v', +'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'l', 'u', 's', 't', 'e', 'r', '/', 'v', '3', '/', 'c', 'l', 'u', 's', +'t', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', +'o', 'r', 'e', '/', 'v', '3', '/', 'a', 'd', 'd', 'r', 'e', 's', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'e', 'n', 'v', +'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 's', 'e', '.', 'p', 'r', +'o', 't', 'o', '\032', '(', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', +'/', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'o', 'u', 'r', 'c', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '/', 'e', 'n', 'v', +'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'e', 'v', 'e', 'n', 't', '_', 's', +'e', 'r', 'v', 'i', 'c', 'e', '_', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '$', 'e', 'n', 'v', 'o', +'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', +'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '(', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', +'e', '/', 'v', '3', '/', 's', 'o', 'c', 'k', 'e', 't', '_', 'o', 'p', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', 'o', '\032', +'\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '/', 'v', '3', +'/', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\032', '#', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', +'n', 'f', 'i', 'g', '/', 'm', 'e', 't', 'r', 'i', 'c', 's', '/', 'v', '3', '/', 's', 't', 'a', 't', 's', '.', 'p', 'r', 'o', +'t', 'o', '\032', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', +'/', 'v', '3', '/', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'p', 'r', 'o', 't', 'o', '\032', '\'', 'e', 'n', 'v', 'o', 'y', +'/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 't', 'r', 'a', 'c', 'e', '/', 'v', '3', '/', 'h', 't', 't', 'p', '_', 't', 'r', 'a', +'c', 'e', 'r', '.', 'p', 'r', 'o', 't', 'o', '\032', '6', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', +'n', 's', '/', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', 's', '/', 't', 'l', 's', '/', +'v', '3', '/', 's', 'e', 'c', 'r', 'e', 't', '.', 'p', 'r', 'o', 't', 'o', '\032', '\033', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', +'p', 'e', '/', 'v', '3', '/', 'p', 'e', 'r', 'c', 'e', 'n', 't', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', +'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', '.', 'p', 'r', 'o', 't', +'o', '\032', '\034', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 's', 't', 'r', 'u', 'c', 't', +'.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'w', +'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', +'a', 't', 'i', 'o', 'n', 's', '/', 'm', 'i', 'g', 'r', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'u', 'd', 'p', +'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 'e', 'c', 'u', 'r', 'i', 't', 'y', '.', 'p', 'r', +'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', +'t', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', +'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', +'d', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\341', '\026', '\n', '\t', 'B', +'o', 'o', 't', 's', 't', 'r', 'a', 'p', '\022', '.', '\n', '\004', 'n', 'o', 'd', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\032', '.', +'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'N', 'o', 'd', 'e', +'R', '\004', 'n', 'o', 'd', 'e', '\022', '.', '\n', '\023', 'n', 'o', 'd', 'e', '_', 'c', 'o', 'n', 't', 'e', 'x', 't', '_', 'p', 'a', +'r', 'a', 'm', 's', '\030', '\032', ' ', '\003', '(', '\t', 'R', '\021', 'n', 'o', 'd', 'e', 'C', 'o', 'n', 't', 'e', 'x', 't', 'P', 'a', +'r', 'a', 'm', 's', '\022', '_', '\n', '\020', 's', 't', 'a', 't', 'i', 'c', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\030', +'\002', ' ', '\001', '(', '\013', '2', '4', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', +'s', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', +'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'R', '\017', 's', 't', 'a', 't', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', +'s', '\022', 'b', '\n', '\021', 'd', 'y', 'n', 'a', 'm', 'i', 'c', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\030', '\003', ' ', +'\001', '(', '\013', '2', '5', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', +'r', 'a', 'p', '.', 'v', '3', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', +'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'R', '\020', 'd', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', +'s', '\022', 'R', '\n', '\017', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '\030', '\004', ' ', '\001', '(', +'\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', +'p', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', 'R', '\016', 'c', 'l', 'u', 's', +'t', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\022', 'D', '\n', '\n', 'h', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', +'\016', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', +'.', 'v', '3', '.', 'A', 'p', 'i', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'h', 'd', 's', 'C', +'o', 'n', 'f', 'i', 'g', '\022', '\035', '\n', '\n', 'f', 'l', 'a', 'g', 's', '_', 'p', 'a', 't', 'h', '\030', '\005', ' ', '\001', '(', '\t', +'R', '\t', 'f', 'l', 'a', 'g', 's', 'P', 'a', 't', 'h', '\022', 'C', '\n', '\013', 's', 't', 'a', 't', 's', '_', 's', 'i', 'n', 'k', +'s', '\030', '\006', ' ', '\003', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', +'t', 'r', 'i', 'c', 's', '.', 'v', '3', '.', 'S', 't', 'a', 't', 's', 'S', 'i', 'n', 'k', 'R', '\n', 's', 't', 'a', 't', 's', +'S', 'i', 'n', 'k', 's', '\022', 'G', '\n', '\014', 's', 't', 'a', 't', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\r', ' ', '\001', +'(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', 't', 'r', 'i', 'c', 's', +'.', 'v', '3', '.', 'S', 't', 'a', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\013', 's', 't', 'a', 't', 's', 'C', 'o', 'n', +'f', 'i', 'g', '\022', 'q', '\n', '\024', 's', 't', 'a', 't', 's', '_', 'f', 'l', 'u', 's', 'h', '_', 'i', 'n', 't', 'e', 'r', 'v', +'a', 'l', '\030', '\007', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '$', '\372', 'B', '\016', '\252', '\001', '\013', '\032', '\003', '\010', '\254', '\002', '2', '\004', +'\020', '\300', '\204', '=', '\362', '\230', '\376', '\217', '\005', '\r', '\022', '\013', 's', 't', 'a', 't', 's', '_', 'f', 'l', 'u', 's', 'h', 'R', '\022', +'s', 't', 'a', 't', 's', 'F', 'l', 'u', 's', 'h', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', '\022', ':', '\n', '\024', 's', 't', 'a', +'t', 's', '_', 'f', 'l', 'u', 's', 'h', '_', 'o', 'n', '_', 'a', 'd', 'm', 'i', 'n', '\030', '\035', ' ', '\001', '(', '\010', 'B', '\007', +'\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\021', 's', 't', 'a', 't', 's', 'F', 'l', 'u', 's', 'h', 'O', 'n', 'A', 'd', +'m', 'i', 'n', '\022', 'C', '\n', '\010', 'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\030', '\010', ' ', '\001', '(', '\013', '2', '#', '.', 'e', +'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', +'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'B', '\002', '\030', '\001', 'R', '\010', 'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\022', 'B', '\n', +'\t', 'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', 's', '\030', '\033', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', +'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', +'d', 'o', 'g', 's', 'R', '\t', 'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', 's', '\022', '<', '\n', '\007', 't', 'r', 'a', 'c', 'i', 'n', +'g', '\030', '\t', ' ', '\001', '(', '\013', '2', '\036', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 't', 'r', +'a', 'c', 'e', '.', 'v', '3', '.', 'T', 'r', 'a', 'c', 'i', 'n', 'g', 'B', '\002', '\030', '\001', 'R', '\007', 't', 'r', 'a', 'c', 'i', +'n', 'g', '\022', 'R', '\n', '\017', 'l', 'a', 'y', 'e', 'r', 'e', 'd', '_', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\030', '\021', ' ', '\001', +'(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', +'a', 'p', '.', 'v', '3', '.', 'L', 'a', 'y', 'e', 'r', 'e', 'd', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'R', '\016', 'l', 'a', 'y', +'e', 'r', 'e', 'd', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '6', '\n', '\005', 'a', 'd', 'm', 'i', 'n', '\030', '\014', ' ', '\001', '(', +'\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', +'p', '.', 'v', '3', '.', 'A', 'd', 'm', 'i', 'n', 'R', '\005', 'a', 'd', 'm', 'i', 'n', '\022', 'd', '\n', '\020', 'o', 'v', 'e', 'r', +'l', 'o', 'a', 'd', '_', 'm', 'a', 'n', 'a', 'g', 'e', 'r', '\030', '\017', ' ', '\001', '(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', +'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '.', 'O', 'v', 'e', 'r', +'l', 'o', 'a', 'd', 'M', 'a', 'n', 'a', 'g', 'e', 'r', 'B', '\016', '\212', '\223', '\267', '*', '\002', '\010', '\001', '\212', '\223', '\267', '*', '\002', +'\020', '\001', 'R', '\017', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\022', '6', '\n', '\027', 'e', 'n', +'a', 'b', 'l', 'e', '_', 'd', 'i', 's', 'p', 'a', 't', 'c', 'h', 'e', 'r', '_', 's', 't', 'a', 't', 's', '\030', '\020', ' ', '\001', +'(', '\010', 'R', '\025', 'e', 'n', 'a', 'b', 'l', 'e', 'D', 'i', 's', 'p', 'a', 't', 'c', 'h', 'e', 'r', 'S', 't', 'a', 't', 's', +'\022', '#', '\n', '\r', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\022', ' ', '\001', '(', '\t', 'R', '\014', +'h', 'e', 'a', 'd', 'e', 'r', 'P', 'r', 'e', 'f', 'i', 'x', '\022', '_', '\n', '\035', 's', 't', 'a', 't', 's', '_', 's', 'e', 'r', +'v', 'e', 'r', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', '_', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\030', '\023', ' ', '\001', '(', +'\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '6', +'4', 'V', 'a', 'l', 'u', 'e', 'R', '\032', 's', 't', 'a', 't', 's', 'S', 'e', 'r', 'v', 'e', 'r', 'V', 'e', 'r', 's', 'i', 'o', +'n', 'O', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '\022', '4', '\n', '\027', 'u', 's', 'e', '_', 't', 'c', 'p', '_', 'f', 'o', 'r', '_', +'d', 'n', 's', '_', 'l', 'o', 'o', 'k', 'u', 'p', 's', '\030', '\024', ' ', '\001', '(', '\010', 'R', '\023', 'u', 's', 'e', 'T', 'c', 'p', +'F', 'o', 'r', 'D', 'n', 's', 'L', 'o', 'o', 'k', 'u', 'p', 's', '\022', ']', '\n', '\024', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', +'p', '_', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '\030', '\025', ' ', '\003', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', +'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', +'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\023', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'E', 'x', +'t', 'e', 'n', 's', 'i', 'o', 'n', 's', '\022', 'K', '\n', '\r', 'f', 'a', 't', 'a', 'l', '_', 'a', 'c', 't', 'i', 'o', 'n', 's', +'\030', '\034', ' ', '\003', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', +'t', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'F', 'a', 't', 'a', 'l', 'A', 'c', 't', 'i', 'o', 'n', 'R', '\014', 'f', 'a', +'t', 'a', 'l', 'A', 'c', 't', 'i', 'o', 'n', 's', '\022', 'I', '\n', '\016', 'c', 'o', 'n', 'f', 'i', 'g', '_', 's', 'o', 'u', 'r', +'c', 'e', 's', '\030', '\026', ' ', '\003', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\r', 'c', 'o', 'n', +'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 's', '\022', 'V', '\n', '\025', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 'c', 'o', 'n', +'f', 'i', 'g', '_', 's', 'o', 'u', 'r', 'c', 'e', '\030', '\027', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', +'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', +'c', 'e', 'R', '\023', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', '\022', '8', +'\n', '\030', 'd', 'e', 'f', 'a', 'u', 'l', 't', '_', 's', 'o', 'c', 'k', 'e', 't', '_', 'i', 'n', 't', 'e', 'r', 'f', 'a', 'c', +'e', '\030', '\030', ' ', '\001', '(', '\t', 'R', '\026', 'd', 'e', 'f', 'a', 'u', 'l', 't', 'S', 'o', 'c', 'k', 'e', 't', 'I', 'n', 't', +'e', 'r', 'f', 'a', 'c', 'e', '\022', '\214', '\001', '\n', '\036', 'c', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', '_', 'p', 'r', +'o', 'v', 'i', 'd', 'e', 'r', '_', 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 's', '\030', '\031', ' ', '\003', '(', '\013', '2', 'F', '.', +'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', +'.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', +'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 's', 'E', 'n', 't', 'r', 'y', 'R', '\034', 'c', 'e', 'r', 't', +'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 's', '\032', +'\232', '\002', '\n', '\017', 'S', 't', 'a', 't', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\022', '@', '\n', '\t', 'l', 'i', +'s', 't', 'e', 'n', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', +'f', 'i', 'g', '.', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '.', 'v', '3', '.', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', 'R', +'\t', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', 's', '\022', '<', '\n', '\010', 'c', 'l', 'u', 's', 't', 'e', 'r', 's', '\030', '\002', ' ', +'\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'l', 'u', 's', 't', 'e', +'r', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'R', '\010', 'c', 'l', 'u', 's', 't', 'e', 'r', 's', '\022', 'K', '\n', +'\007', 's', 'e', 'c', 'r', 'e', 't', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', +'t', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 't', 'r', 'a', 'n', 's', 'p', 'o', 'r', 't', '_', 's', 'o', 'c', 'k', 'e', 't', +'s', '.', 't', 'l', 's', '.', 'v', '3', '.', 'S', 'e', 'c', 'r', 'e', 't', 'R', '\007', 's', 'e', 'c', 'r', 'e', 't', 's', ':', +':', '\232', '\305', '\210', '\036', '5', '\n', '3', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', +'s', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'S', 't', 'a', 't', 'i', 'c', +'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '\032', '\211', '\003', '\n', '\020', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'e', 's', 'o', +'u', 'r', 'c', 'e', 's', '\022', 'A', '\n', '\n', 'l', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', +'2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', +'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\t', 'l', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '2', '\n', +'\025', 'l', 'd', 's', '_', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', '\005', ' ', +'\001', '(', '\t', 'R', '\023', 'l', 'd', 's', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'L', 'o', 'c', 'a', 't', 'o', 'r', '\022', +'A', '\n', '\n', 'c', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', +'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', +'o', 'u', 'r', 'c', 'e', 'R', '\t', 'c', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '2', '\n', '\025', 'c', 'd', 's', '_', 'r', +'e', 's', 'o', 'u', 'r', 'c', 'e', 's', '_', 'l', 'o', 'c', 'a', 't', 'o', 'r', '\030', '\006', ' ', '\001', '(', '\t', 'R', '\023', 'c', +'d', 's', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'L', 'o', 'c', 'a', 't', 'o', 'r', '\022', 'D', '\n', '\n', 'a', 'd', 's', +'_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', +'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'p', 'i', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', +'c', 'e', 'R', '\t', 'a', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', ':', ';', '\232', '\305', '\210', '\036', '6', '\n', '4', 'e', 'n', 'v', +'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', +'o', 't', 's', 't', 'r', 'a', 'p', '.', 'D', 'y', 'n', 'a', 'm', 'i', 'c', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 's', 'J', +'\004', '\010', '\004', '\020', '\005', '\032', '{', '\n', '!', 'C', 'e', 'r', 't', 'i', 'f', 'i', 'c', 'a', 't', 'e', 'P', 'r', 'o', 'v', 'i', +'d', 'e', 'r', 'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', +'\001', ' ', '\001', '(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '@', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', +'2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', +'y', 'p', 'e', 'd', 'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\005', 'v', 'a', 'l', 'u', +'e', ':', '\002', '8', '\001', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', +'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'B', +'\r', '\n', '\013', 's', 't', 'a', 't', 's', '_', 'f', 'l', 'u', 's', 'h', 'J', '\004', '\010', '\n', '\020', '\013', 'J', '\004', '\010', '\013', '\020', +'\014', 'R', '\007', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\"', '\376', '\001', '\n', '\005', 'A', 'd', 'm', 'i', 'n', '\022', '&', '\n', '\017', 'a', +'c', 'c', 'e', 's', 's', '_', 'l', 'o', 'g', '_', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\r', 'a', 'c', 'c', +'e', 's', 's', 'L', 'o', 'g', 'P', 'a', 't', 'h', '\022', '!', '\n', '\014', 'p', 'r', 'o', 'f', 'i', 'l', 'e', '_', 'p', 'a', 't', +'h', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\013', 'p', 'r', 'o', 'f', 'i', 'l', 'e', 'P', 'a', 't', 'h', '\022', '7', '\n', '\007', 'a', +'d', 'd', 'r', 'e', 's', 's', '\030', '\003', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', +'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'R', '\007', 'a', 'd', 'd', 'r', 'e', +'s', 's', '\022', 'I', '\n', '\016', 's', 'o', 'c', 'k', 'e', 't', '_', 'o', 'p', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\003', '(', +'\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', +'S', 'o', 'c', 'k', 'e', 't', 'O', 'p', 't', 'i', 'o', 'n', 'R', '\r', 's', 'o', 'c', 'k', 'e', 't', 'O', 'p', 't', 'i', 'o', +'n', 's', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', +'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'A', 'd', 'm', 'i', 'n', '\"', '\313', '\004', '\n', '\016', 'C', 'l', 'u', +'s', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '\022', ',', '\n', '\022', 'l', 'o', 'c', 'a', 'l', '_', 'c', 'l', 'u', 's', +'t', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\020', 'l', 'o', 'c', 'a', 'l', 'C', 'l', 'u', 's', +'t', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'g', '\n', '\021', 'o', 'u', 't', 'l', 'i', 'e', 'r', '_', 'd', 'e', 't', 'e', 'c', 't', +'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\013', '2', ':', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', +'e', 'r', '.', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', 'R', '\020', 'o', 'u', 't', 'l', +'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', '\022', 'R', '\n', '\024', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_', +'b', 'i', 'n', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', +'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', +'g', 'R', '\022', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 'B', 'i', 'n', 'd', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'Q', '\n', '\021', +'l', 'o', 'a', 'd', '_', 's', 't', 'a', 't', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\004', ' ', '\001', '(', '\013', '2', '%', +'.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'p', 'i', +'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\017', 'l', 'o', 'a', 'd', 'S', 't', 'a', 't', 's', 'C', 'o', +'n', 'f', 'i', 'g', '\032', '\311', '\001', '\n', '\020', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D', 'e', 't', 'e', 'c', 't', 'i', 'o', 'n', +'\022', '$', '\n', '\016', 'e', 'v', 'e', 'n', 't', '_', 'l', 'o', 'g', '_', 'p', 'a', 't', 'h', '\030', '\001', ' ', '\001', '(', '\t', 'R', +'\014', 'e', 'v', 'e', 'n', 't', 'L', 'o', 'g', 'P', 'a', 't', 'h', '\022', 'M', '\n', '\r', 'e', 'v', 'e', 'n', 't', '_', 's', 'e', +'r', 'v', 'i', 'c', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', +'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'E', 'v', 'e', 'n', 't', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'C', 'o', 'n', +'f', 'i', 'g', 'R', '\014', 'e', 'v', 'e', 'n', 't', 'S', 'e', 'r', 'v', 'i', 'c', 'e', ':', '@', '\232', '\305', '\210', '\036', ';', '\n', +'9', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', +'2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', 'M', 'a', 'n', 'a', 'g', 'e', 'r', '.', 'O', 'u', 't', 'l', 'i', 'e', 'r', 'D', +'e', 't', 'e', 'c', 't', 'i', 'o', 'n', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', '(', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', +'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'C', 'l', 'u', 's', 't', 'e', 'r', +'M', 'a', 'n', 'a', 'g', 'e', 'r', '\"', '\260', '\001', '\n', '\t', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 's', '\022', 'U', '\n', '\024', +'m', 'a', 'i', 'n', '_', 't', 'h', 'r', 'e', 'a', 'd', '_', 'w', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\030', '\001', ' ', '\001', '(', +'\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', +'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'R', '\022', 'm', 'a', 'i', 'n', 'T', 'h', 'r', 'e', 'a', 'd', +'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\022', 'L', '\n', '\017', 'w', 'o', 'r', 'k', 'e', 'r', '_', 'w', 'a', 't', 'c', 'h', 'd', +'o', 'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', +'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'R', '\016', 'w', 'o', 'r', +'k', 'e', 'r', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\"', '\272', '\006', '\n', '\010', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\022', +'L', '\n', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\030', '\007', ' ', '\003', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', +'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', +'d', 'o', 'g', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i', 'o', 'n', 'R', '\007', 'a', 'c', 't', 'i', 'o', +'n', 's', '\022', '<', '\n', '\014', 'm', 'i', 's', 's', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', +'\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', +'n', 'R', '\013', 'm', 'i', 's', 's', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'D', '\n', '\020', 'm', 'e', 'g', 'a', 'm', 'i', 's', +'s', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\017', 'm', 'e', 'g', 'a', 'm', 'i', +'s', 's', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', '<', '\n', '\014', 'k', 'i', 'l', 'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', +'\030', '\003', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\013', 'k', 'i', 'l', 'l', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'Z', '\n', '\027', +'m', 'a', 'x', '_', 'k', 'i', 'l', 'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '_', 'j', 'i', 't', 't', 'e', 'r', '\030', '\006', +' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', +'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\252', '\001', '\002', '2', '\000', 'R', '\024', 'm', 'a', 'x', 'K', 'i', 'l', 'l', +'T', 'i', 'm', 'e', 'o', 'u', 't', 'J', 'i', 't', 't', 'e', 'r', '\022', 'F', '\n', '\021', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', +'l', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\020', 'm', 'u', 'l', 't', 'i', 'k', +'i', 'l', 'l', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', 'G', '\n', '\023', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', '_', 't', +'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\030', '\005', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', +'p', 'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\022', 'm', 'u', 'l', 't', 'i', 'k', 'i', 'l', 'l', 'T', +'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\032', '\205', '\002', '\n', '\016', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i', +'o', 'n', '\022', 'B', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', +'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', 'E', 'x', 't', +'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\022', '`', '\n', '\005', 'e', +'v', 'e', 'n', 't', '\030', '\002', ' ', '\001', '(', '\016', '2', '@', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', +'.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '.', 'W', 'a', +'t', 'c', 'h', 'd', 'o', 'g', 'A', 'c', 't', 'i', 'o', 'n', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', 'E', 'v', 'e', 'n', +'t', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\005', 'e', 'v', 'e', 'n', 't', '\"', 'M', '\n', '\r', 'W', 'a', 't', +'c', 'h', 'd', 'o', 'g', 'E', 'v', 'e', 'n', 't', '\022', '\013', '\n', '\007', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\010', +'\n', '\004', 'K', 'I', 'L', 'L', '\020', '\001', '\022', '\r', '\n', '\t', 'M', 'U', 'L', 'T', 'I', 'K', 'I', 'L', 'L', '\020', '\002', '\022', '\014', +'\n', '\010', 'M', 'E', 'G', 'A', 'M', 'I', 'S', 'S', '\020', '\003', '\022', '\010', '\n', '\004', 'M', 'I', 'S', 'S', '\020', '\004', ':', ')', '\232', +'\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', +'r', 'a', 'p', '.', 'v', '2', '.', 'W', 'a', 't', 'c', 'h', 'd', 'o', 'g', '\"', 'Q', '\n', '\013', 'F', 'a', 't', 'a', 'l', 'A', +'c', 't', 'i', 'o', 'n', '\022', 'B', '\n', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\001', ' ', '\001', '(', '\013', '2', '*', '.', 'e', +'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'T', 'y', 'p', 'e', 'd', +'E', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\334', +'\001', '\n', '\007', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '!', '\n', '\014', 's', 'y', 'm', 'l', 'i', 'n', 'k', '_', 'r', 'o', 'o', +'t', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 's', 'y', 'm', 'l', 'i', 'n', 'k', 'R', 'o', 'o', 't', '\022', '\"', '\n', '\014', 's', +'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\014', 's', 'u', 'b', 'd', 'i', 'r', +'e', 'c', 't', 'o', 'r', 'y', '\022', '3', '\n', '\025', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', '_', 's', 'u', 'b', 'd', 'i', 'r', +'e', 'c', 't', 'o', 'r', 'y', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\024', 'o', 'v', 'e', 'r', 'r', 'i', 'd', 'e', 'S', 'u', 'b', +'d', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '+', '\n', '\004', 'b', 'a', 's', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\027', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'R', '\004', +'b', 'a', 's', 'e', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', +'.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\"', '\333', '\006', '\n', +'\014', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', +'(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '<', '\n', '\014', 's', 't', 'a', 't', +'i', 'c', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\002', ' ', '\001', '(', '\013', '2', '\027', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'S', 't', 'r', 'u', 'c', 't', 'H', '\000', 'R', '\013', 's', 't', 'a', 't', 'i', 'c', 'L', +'a', 'y', 'e', 'r', '\022', 'R', '\n', '\n', 'd', 'i', 's', 'k', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2', +'1', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', +'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'D', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', +'H', '\000', 'R', '\t', 'd', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', '\022', 'U', '\n', '\013', 'a', 'd', 'm', 'i', 'n', '_', 'l', 'a', +'y', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '2', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', +'.', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', 'H', '\000', 'R', '\n', 'a', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', +'\022', 'R', '\n', '\n', 'r', 't', 'd', 's', '_', 'l', 'a', 'y', 'e', 'r', '\030', '\005', ' ', '\001', '(', '\013', '2', '1', '.', 'e', 'n', +'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', +'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', 'H', '\000', 'R', '\t', +'r', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', '\032', '\301', '\001', '\n', '\t', 'D', 'i', 's', 'k', 'L', 'a', 'y', 'e', 'r', '\022', '!', +'\n', '\014', 's', 'y', 'm', 'l', 'i', 'n', 'k', '_', 'r', 'o', 'o', 't', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 's', 'y', 'm', +'l', 'i', 'n', 'k', 'R', 'o', 'o', 't', '\022', '\"', '\n', '\014', 's', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\030', +'\003', ' ', '\001', '(', '\t', 'R', '\014', 's', 'u', 'b', 'd', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', '\022', '4', '\n', '\026', 'a', 'p', +'p', 'e', 'n', 'd', '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', '_', 'c', 'l', 'u', 's', 't', 'e', 'r', '\030', '\002', ' ', '\001', '(', +'\010', 'R', '\024', 'a', 'p', 'p', 'e', 'n', 'd', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 'C', 'l', 'u', 's', 't', 'e', 'r', ':', '7', +'\232', '\305', '\210', '\036', '2', '\n', '0', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', +'t', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'D', 'i', 's', 'k', +'L', 'a', 'y', 'e', 'r', '\032', 'F', '\n', '\n', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y', 'e', 'r', ':', '8', '\232', '\305', '\210', '\036', +'3', '\n', '1', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', +'.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', '.', 'A', 'd', 'm', 'i', 'n', 'L', 'a', 'y', +'e', 'r', '\032', '\235', '\001', '\n', '\t', 'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', +'\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'C', '\n', '\013', 'r', 't', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', +'g', '\030', '\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', +'r', 'e', '.', 'v', '3', '.', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 'o', 'u', 'r', 'c', 'e', 'R', '\n', 'r', 't', 'd', 's', 'C', +'o', 'n', 'f', 'i', 'g', ':', '7', '\232', '\305', '\210', '\036', '2', '\n', '0', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', +'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'L', 'a', 'y', +'e', 'r', '.', 'R', 't', 'd', 's', 'L', 'a', 'y', 'e', 'r', ':', '-', '\232', '\305', '\210', '\036', '(', '\n', '&', 'e', 'n', 'v', 'o', +'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '2', '.', 'R', 'u', 'n', +'t', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', 'B', '\026', '\n', '\017', 'l', 'a', 'y', 'e', 'r', '_', 's', 'p', 'e', 'c', 'i', 'f', +'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', '\202', '\001', '\n', '\016', 'L', 'a', 'y', 'e', 'r', 'e', 'd', 'R', 'u', 'n', 't', 'i', +'m', 'e', '\022', '?', '\n', '\006', 'l', 'a', 'y', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o', +'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', '3', '.', 'R', 'u', 'n', +'t', 'i', 'm', 'e', 'L', 'a', 'y', 'e', 'r', 'R', '\006', 'l', 'a', 'y', 'e', 'r', 's', ':', '/', '\232', '\305', '\210', '\036', '*', '\n', +'(', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', '.', 'v', +'2', '.', 'L', 'a', 'y', 'e', 'r', 'e', 'd', 'R', 'u', 'n', 't', 'i', 'm', 'e', 'B', 'C', '\n', '\'', 'i', 'o', '.', 'e', 'n', +'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'b', 'o', 'o', +'t', 's', 't', 'r', 'a', 'p', '.', 'v', '3', 'B', '\016', 'B', 'o', 'o', 't', 's', 't', 'r', 'a', 'p', 'P', 'r', 'o', 't', 'o', +'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[22] = { + &envoy_config_cluster_v3_cluster_proto_upbdefinit, + &envoy_config_core_v3_address_proto_upbdefinit, + &envoy_config_core_v3_base_proto_upbdefinit, + &envoy_config_core_v3_config_source_proto_upbdefinit, + &envoy_config_core_v3_event_service_config_proto_upbdefinit, + &envoy_config_core_v3_extension_proto_upbdefinit, + &envoy_config_core_v3_socket_option_proto_upbdefinit, + &envoy_config_listener_v3_listener_proto_upbdefinit, + &envoy_config_metrics_v3_stats_proto_upbdefinit, + &envoy_config_overload_v3_overload_proto_upbdefinit, + &envoy_config_trace_v3_http_tracer_proto_upbdefinit, + &envoy_extensions_transport_sockets_tls_v3_secret_proto_upbdefinit, + &envoy_type_v3_percent_proto_upbdefinit, + &google_protobuf_duration_proto_upbdefinit, + &google_protobuf_struct_proto_upbdefinit, + &google_protobuf_wrappers_proto_upbdefinit, + &udpa_annotations_migrate_proto_upbdefinit, + &udpa_annotations_security_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + &validate_validate_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit = { + deps, + layouts, + "envoy/config/bootstrap/v3/bootstrap.proto", + UPB_STRVIEW_INIT(descriptor, 6993) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h new file mode 100644 index 00000000000..666cbed19e3 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h @@ -0,0 +1,115 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/bootstrap/v3/bootstrap.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_CONFIG_BOOTSTRAP_V3_BOOTSTRAP_PROTO_UPBDEFS_H_ +#define ENVOY_CONFIG_BOOTSTRAP_V3_BOOTSTRAP_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Bootstrap_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Bootstrap"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Bootstrap_StaticResources_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Bootstrap.StaticResources"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Bootstrap_DynamicResources_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Bootstrap.DynamicResources"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Bootstrap_CertificateProviderInstancesEntry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Bootstrap.CertificateProviderInstancesEntry"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Admin_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Admin"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_ClusterManager_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.ClusterManager"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_ClusterManager_OutlierDetection_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.ClusterManager.OutlierDetection"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Watchdogs_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Watchdogs"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Watchdog_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Watchdog"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Watchdog_WatchdogAction_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Watchdog.WatchdogAction"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_FatalAction_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.FatalAction"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_Runtime_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.Runtime"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_RuntimeLayer_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.RuntimeLayer"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_RuntimeLayer_DiskLayer_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.RuntimeLayer.DiskLayer"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_RuntimeLayer_AdminLayer_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.RuntimeLayer.AdminLayer"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_RuntimeLayer_RtdsLayer_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.RuntimeLayer.RtdsLayer"); +} + +UPB_INLINE const upb_msgdef *envoy_config_bootstrap_v3_LayeredRuntime_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_bootstrap_v3_bootstrap_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.bootstrap.v3.LayeredRuntime"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_CONFIG_BOOTSTRAP_V3_BOOTSTRAP_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c new file mode 100644 index 00000000000..e49149aad7b --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c @@ -0,0 +1,141 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/metrics/v3/stats.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/config/metrics/v3/stats.upbdefs.h" + +extern upb_def_init envoy_config_core_v3_address_proto_upbdefinit; +extern upb_def_init envoy_type_matcher_v3_string_proto_upbdefinit; +extern upb_def_init google_protobuf_any_proto_upbdefinit; +extern upb_def_init google_protobuf_wrappers_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern upb_def_init validate_validate_proto_upbdefinit; +extern const upb_msglayout envoy_config_metrics_v3_StatsSink_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsConfig_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsMatcher_msginit; +extern const upb_msglayout envoy_config_metrics_v3_TagSpecifier_msginit; +extern const upb_msglayout envoy_config_metrics_v3_HistogramBucketSettings_msginit; +extern const upb_msglayout envoy_config_metrics_v3_StatsdSink_msginit; +extern const upb_msglayout envoy_config_metrics_v3_DogStatsdSink_msginit; +extern const upb_msglayout envoy_config_metrics_v3_HystrixSink_msginit; + +static const upb_msglayout *layouts[8] = { + &envoy_config_metrics_v3_StatsSink_msginit, + &envoy_config_metrics_v3_StatsConfig_msginit, + &envoy_config_metrics_v3_StatsMatcher_msginit, + &envoy_config_metrics_v3_TagSpecifier_msginit, + &envoy_config_metrics_v3_HistogramBucketSettings_msginit, + &envoy_config_metrics_v3_StatsdSink_msginit, + &envoy_config_metrics_v3_DogStatsdSink_msginit, + &envoy_config_metrics_v3_HystrixSink_msginit, +}; + +static const char descriptor[2091] = {'\n', '#', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'm', 'e', 't', 'r', 'i', 'c', 's', '/', 'v', '3', +'/', 's', 't', 'a', 't', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\027', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', +'g', '.', 'm', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '3', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', +'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'a', 'd', 'd', 'r', 'e', 's', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', +'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 's', 't', 'r', +'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\031', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', +'b', 'u', 'f', '/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', +'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', +'!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', +'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', +'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\241', '\001', '\n', '\t', 'S', 't', 'a', 't', 's', 'S', 'i', 'n', 'k', '\022', '\022', +'\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', 'y', 'p', +'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', 'n', 'f', +'i', 'g', ':', '(', '\232', '\305', '\210', '\036', '#', '\n', '!', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', +'e', 't', 'r', 'i', 'c', 's', '.', 'v', '2', '.', 'S', 't', 'a', 't', 's', 'S', 'i', 'n', 'k', 'B', '\r', '\n', '\013', 'c', 'o', +'n', 'f', 'i', 'g', '_', 't', 'y', 'p', 'e', 'J', '\004', '\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\206', +'\003', '\n', '\013', 'S', 't', 'a', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'D', '\n', '\n', 's', 't', 'a', 't', 's', '_', 't', +'a', 'g', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'m', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '3', '.', 'T', 'a', 'g', 'S', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R', '\t', +'s', 't', 'a', 't', 's', 'T', 'a', 'g', 's', '\022', 'K', '\n', '\024', 'u', 's', 'e', '_', 'a', 'l', 'l', '_', 'd', 'e', 'f', 'a', +'u', 'l', 't', '_', 't', 'a', 'g', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', +'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'B', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', 'R', '\021', 'u', 's', 'e', 'A', 'l', 'l', +'D', 'e', 'f', 'a', 'u', 'l', 't', 'T', 'a', 'g', 's', '\022', 'J', '\n', '\r', 's', 't', 'a', 't', 's', '_', 'm', 'a', 't', 'c', +'h', 'e', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'m', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '3', '.', 'S', 't', 'a', 't', 's', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\014', +'s', 't', 'a', 't', 's', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', 'l', '\n', '\031', 'h', 'i', 's', 't', 'o', 'g', 'r', 'a', 'm', +'_', 'b', 'u', 'c', 'k', 'e', 't', '_', 's', 'e', 't', 't', 'i', 'n', 'g', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '0', '.', +'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '3', '.', 'H', +'i', 's', 't', 'o', 'g', 'r', 'a', 'm', 'B', 'u', 'c', 'k', 'e', 't', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', 'R', '\027', 'h', +'i', 's', 't', 'o', 'g', 'r', 'a', 'm', 'B', 'u', 'c', 'k', 'e', 't', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', ':', '*', '\232', +'\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', 't', 'r', 'i', 'c', +'s', '.', 'v', '2', '.', 'S', 't', 'a', 't', 's', 'C', 'o', 'n', 'f', 'i', 'g', '\"', '\230', '\002', '\n', '\014', 'S', 't', 'a', 't', +'s', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', '\037', '\n', '\n', 'r', 'e', 'j', 'e', 'c', 't', '_', 'a', 'l', 'l', '\030', '\001', ' ', +'\001', '(', '\010', 'H', '\000', 'R', '\t', 'r', 'e', 'j', 'e', 'c', 't', 'A', 'l', 'l', '\022', 'Q', '\n', '\016', 'e', 'x', 'c', 'l', 'u', +'s', 'i', 'o', 'n', '_', 'l', 'i', 's', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', +'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'L', 'i', 's', 't', 'S', 't', 'r', 'i', 'n', 'g', +'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\r', 'e', 'x', 'c', 'l', 'u', 's', 'i', 'o', 'n', 'L', 'i', 's', 't', '\022', +'Q', '\n', '\016', 'i', 'n', 'c', 'l', 'u', 's', 'i', 'o', 'n', '_', 'l', 'i', 's', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', '(', +'.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'L', 'i', +'s', 't', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\r', 'i', 'n', 'c', 'l', 'u', 's', +'i', 'o', 'n', 'L', 'i', 's', 't', ':', '+', '\232', '\305', '\210', '\036', '&', '\n', '$', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', +'f', 'i', 'g', '.', 'm', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '2', '.', 'S', 't', 'a', 't', 's', 'M', 'a', 't', 'c', 'h', +'e', 'r', 'B', '\024', '\n', '\r', 's', 't', 'a', 't', 's', '_', 'm', 'a', 't', 'c', 'h', 'e', 'r', '\022', '\003', '\370', 'B', '\001', '\"', +'\250', '\001', '\n', '\014', 'T', 'a', 'g', 'S', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\031', '\n', '\010', 't', 'a', 'g', '_', 'n', +'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 't', 'a', 'g', 'N', 'a', 'm', 'e', '\022', ' ', '\n', '\005', 'r', 'e', 'g', +'e', 'x', '\030', '\002', ' ', '\001', '(', '\t', 'B', '\010', '\372', 'B', '\005', 'r', '\003', '(', '\200', '\010', 'H', '\000', 'R', '\005', 'r', 'e', 'g', +'e', 'x', '\022', '!', '\n', '\013', 'f', 'i', 'x', 'e', 'd', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\t', 'H', '\000', +'R', '\n', 'f', 'i', 'x', 'e', 'd', 'V', 'a', 'l', 'u', 'e', ':', '+', '\232', '\305', '\210', '\036', '&', '\n', '$', 'e', 'n', 'v', 'o', +'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '2', '.', 'T', 'a', 'g', 'S', 'p', +'e', 'c', 'i', 'f', 'i', 'e', 'r', 'B', '\013', '\n', '\t', 't', 'a', 'g', '_', 'v', 'a', 'l', 'u', 'e', '\"', '\222', '\001', '\n', '\027', +'H', 'i', 's', 't', 'o', 'g', 'r', 'a', 'm', 'B', 'u', 'c', 'k', 'e', 't', 'S', 'e', 't', 't', 'i', 'n', 'g', 's', '\022', 'D', +'\n', '\005', 'm', 'a', 't', 'c', 'h', '\030', '\001', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', +'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', +'r', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\005', 'm', 'a', 't', 'c', 'h', '\022', '1', '\n', '\007', 'b', 'u', 'c', +'k', 'e', 't', 's', '\030', '\002', ' ', '\003', '(', '\001', 'B', '\027', '\372', 'B', '\024', '\222', '\001', '\021', '\010', '\001', '\030', '\001', '\"', '\013', '\022', +'\t', '!', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 'R', '\007', 'b', 'u', 'c', 'k', 'e', 't', 's', '\"', '\317', '\001', '\n', '\n', 'S', +'t', 'a', 't', 's', 'd', 'S', 'i', 'n', 'k', '\022', '9', '\n', '\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', +'\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', +'A', 'd', 'd', 'r', 'e', 's', 's', 'H', '\000', 'R', '\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\022', '*', '\n', '\020', 't', 'c', 'p', +'_', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\016', 't', 'c', +'p', 'C', 'l', 'u', 's', 't', 'e', 'r', 'N', 'a', 'm', 'e', '\022', '\026', '\n', '\006', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\003', ' ', +'\001', '(', '\t', 'R', '\006', 'p', 'r', 'e', 'f', 'i', 'x', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', +'.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '2', '.', 'S', 't', 'a', 't', 's', 'd', +'S', 'i', 'n', 'k', 'B', '\027', '\n', '\020', 's', 't', 'a', 't', 's', 'd', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', +'\003', '\370', 'B', '\001', '\"', '\217', '\002', '\n', '\r', 'D', 'o', 'g', 'S', 't', 'a', 't', 's', 'd', 'S', 'i', 'n', 'k', '\022', '9', '\n', +'\007', 'a', 'd', 'd', 'r', 'e', 's', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\035', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', +'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'A', 'd', 'd', 'r', 'e', 's', 's', 'H', '\000', 'R', '\007', 'a', +'d', 'd', 'r', 'e', 's', 's', '\022', '\026', '\n', '\006', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\006', 'p', +'r', 'e', 'f', 'i', 'x', '\022', 'Z', '\n', '\026', 'm', 'a', 'x', '_', 'b', 'y', 't', 'e', 's', '_', 'p', 'e', 'r', '_', 'd', 'a', +'t', 'a', 'g', 'r', 'a', 'm', '\030', '\004', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'U', 'I', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', 'B', '\007', '\372', 'B', '\004', '2', '\002', ' ', +'\000', 'R', '\023', 'm', 'a', 'x', 'B', 'y', 't', 'e', 's', 'P', 'e', 'r', 'D', 'a', 't', 'a', 'g', 'r', 'a', 'm', ':', ',', '\232', +'\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', 't', 'r', 'i', 'c', +'s', '.', 'v', '2', '.', 'D', 'o', 'g', 'S', 't', 'a', 't', 's', 'd', 'S', 'i', 'n', 'k', 'B', '\033', '\n', '\024', 'd', 'o', 'g', +'_', 's', 't', 'a', 't', 's', 'd', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'J', '\004', '\010', +'\002', '\020', '\003', '\"', 'Z', '\n', '\013', 'H', 'y', 's', 't', 'r', 'i', 'x', 'S', 'i', 'n', 'k', '\022', '\037', '\n', '\013', 'n', 'u', 'm', +'_', 'b', 'u', 'c', 'k', 'e', 't', 's', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\n', 'n', 'u', 'm', 'B', 'u', 'c', 'k', 'e', 't', +'s', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'm', 'e', +'t', 'r', 'i', 'c', 's', '.', 'v', '2', '.', 'H', 'y', 's', 't', 'r', 'i', 'x', 'S', 'i', 'n', 'k', 'B', '=', '\n', '%', 'i', +'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', +'.', 'm', 'e', 't', 'r', 'i', 'c', 's', '.', 'v', '3', 'B', '\n', 'S', 't', 'a', 't', 's', 'P', 'r', 'o', 't', 'o', 'P', '\001', +'\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[8] = { + &envoy_config_core_v3_address_proto_upbdefinit, + &envoy_type_matcher_v3_string_proto_upbdefinit, + &google_protobuf_any_proto_upbdefinit, + &google_protobuf_wrappers_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + &validate_validate_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_config_metrics_v3_stats_proto_upbdefinit = { + deps, + layouts, + "envoy/config/metrics/v3/stats.proto", + UPB_STRVIEW_INIT(descriptor, 2091) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h new file mode 100644 index 00000000000..0432cfd1f06 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h @@ -0,0 +1,70 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/metrics/v3/stats.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_CONFIG_METRICS_V3_STATS_PROTO_UPBDEFS_H_ +#define ENVOY_CONFIG_METRICS_V3_STATS_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_config_metrics_v3_stats_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_StatsSink_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.StatsSink"); +} + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_StatsConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.StatsConfig"); +} + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_StatsMatcher_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.StatsMatcher"); +} + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_TagSpecifier_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.TagSpecifier"); +} + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_HistogramBucketSettings_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.HistogramBucketSettings"); +} + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_StatsdSink_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.StatsdSink"); +} + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_DogStatsdSink_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.DogStatsdSink"); +} + +UPB_INLINE const upb_msgdef *envoy_config_metrics_v3_HystrixSink_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_metrics_v3_stats_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.metrics.v3.HystrixSink"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_CONFIG_METRICS_V3_STATS_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c new file mode 100644 index 00000000000..e189d990001 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c @@ -0,0 +1,141 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/overload/v3/overload.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/config/overload/v3/overload.upbdefs.h" + +extern upb_def_init envoy_type_v3_percent_proto_upbdefinit; +extern upb_def_init google_protobuf_any_proto_upbdefinit; +extern upb_def_init google_protobuf_duration_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern upb_def_init validate_validate_proto_upbdefinit; +extern const upb_msglayout envoy_config_overload_v3_ResourceMonitor_msginit; +extern const upb_msglayout envoy_config_overload_v3_ThresholdTrigger_msginit; +extern const upb_msglayout envoy_config_overload_v3_ScaledTrigger_msginit; +extern const upb_msglayout envoy_config_overload_v3_Trigger_msginit; +extern const upb_msglayout envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit; +extern const upb_msglayout envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit; +extern const upb_msglayout envoy_config_overload_v3_OverloadAction_msginit; +extern const upb_msglayout envoy_config_overload_v3_OverloadManager_msginit; + +static const upb_msglayout *layouts[8] = { + &envoy_config_overload_v3_ResourceMonitor_msginit, + &envoy_config_overload_v3_ThresholdTrigger_msginit, + &envoy_config_overload_v3_ScaledTrigger_msginit, + &envoy_config_overload_v3_Trigger_msginit, + &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_msginit, + &envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_msginit, + &envoy_config_overload_v3_OverloadAction_msginit, + &envoy_config_overload_v3_OverloadManager_msginit, +}; + +static const char descriptor[2145] = {'\n', '\'', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '/', 'v', +'3', '/', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'e', 'n', 'v', 'o', 'y', '.', 'c', +'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '\032', '\033', 'e', 'n', 'v', 'o', 'y', '/', +'t', 'y', 'p', 'e', '/', 'v', '3', '/', 'p', 'e', 'r', 'c', 'e', 'n', 't', '.', 'p', 'r', 'o', 't', 'o', '\032', '\031', 'g', 'o', +'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'a', 'n', 'y', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', +'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', '.', +'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', +'t', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', +'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', +'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\274', '\001', '\n', +'\017', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'M', 'o', 'n', 'i', 't', 'o', 'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', +'\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '9', '\n', '\014', 't', +'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'H', '\000', 'R', '\013', 't', 'y', 'p', 'e', 'd', 'C', 'o', +'n', 'f', 'i', 'g', ':', '4', '\232', '\305', '\210', '\036', '/', '\n', '-', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', +'.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'R', 'e', 's', 'o', 'u', 'r', 'c', +'e', 'M', 'o', 'n', 'i', 't', 'o', 'r', 'B', '\r', '\n', '\013', 'c', 'o', 'n', 'f', 'i', 'g', '_', 't', 'y', 'p', 'e', 'J', '\004', +'\010', '\002', '\020', '\003', 'R', '\006', 'c', 'o', 'n', 'f', 'i', 'g', '\"', 'x', '\n', '\020', 'T', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', +'T', 'r', 'i', 'g', 'g', 'e', 'r', '\022', '-', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\001', 'B', '\027', '\372', +'B', '\024', '\022', '\022', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', ')', '\000', '\000', '\000', '\000', '\000', '\000', '\000', '\000', 'R', '\005', 'v', +'a', 'l', 'u', 'e', ':', '5', '\232', '\305', '\210', '\036', '0', '\n', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', +'.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'T', 'h', 'r', 'e', 's', 'h', 'o', +'l', 'd', 'T', 'r', 'i', 'g', 'g', 'e', 'r', '\"', '\241', '\001', '\n', '\r', 'S', 'c', 'a', 'l', 'e', 'd', 'T', 'r', 'i', 'g', 'g', +'e', 'r', '\022', 'D', '\n', '\021', 's', 'c', 'a', 'l', 'i', 'n', 'g', '_', 't', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\030', '\001', +' ', '\001', '(', '\001', 'B', '\027', '\372', 'B', '\024', '\022', '\022', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', ')', '\000', '\000', '\000', '\000', +'\000', '\000', '\000', '\000', 'R', '\020', 's', 'c', 'a', 'l', 'i', 'n', 'g', 'T', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\022', 'J', '\n', +'\024', 's', 'a', 't', 'u', 'r', 'a', 't', 'i', 'o', 'n', '_', 't', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\030', '\002', ' ', '\001', +'(', '\001', 'B', '\027', '\372', 'B', '\024', '\022', '\022', '\031', '\000', '\000', '\000', '\000', '\000', '\000', '\360', '?', ')', '\000', '\000', '\000', '\000', '\000', '\000', +'\000', '\000', 'R', '\023', 's', 'a', 't', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'T', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\"', '\371', +'\001', '\n', '\007', 'T', 'r', 'i', 'g', 'g', 'e', 'r', '\022', '\033', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', +'\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'J', '\n', '\t', 't', 'h', 'r', 'e', 's', 'h', 'o', +'l', 'd', '\030', '\002', ' ', '\001', '(', '\013', '2', '*', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'o', +'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '.', 'T', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', 'T', 'r', 'i', 'g', 'g', +'e', 'r', 'H', '\000', 'R', '\t', 't', 'h', 'r', 'e', 's', 'h', 'o', 'l', 'd', '\022', 'A', '\n', '\006', 's', 'c', 'a', 'l', 'e', 'd', +'\030', '\003', ' ', '\001', '(', '\013', '2', '\'', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', +'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '.', 'S', 'c', 'a', 'l', 'e', 'd', 'T', 'r', 'i', 'g', 'g', 'e', 'r', 'H', '\000', 'R', +'\006', 's', 'c', 'a', 'l', 'e', 'd', ':', ',', '\232', '\305', '\210', '\036', '\'', '\n', '%', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', +'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'T', 'r', 'i', 'g', +'g', 'e', 'r', 'B', '\024', '\n', '\r', 't', 'r', 'i', 'g', 'g', 'e', 'r', '_', 'o', 'n', 'e', 'o', 'f', '\022', '\003', '\370', 'B', '\001', +'\"', '\247', '\004', '\n', '\037', 'S', 'c', 'a', 'l', 'e', 'T', 'i', 'm', 'e', 'r', 's', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'A', +'c', 't', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', '\022', '~', '\n', '\023', 't', 'i', 'm', 'e', 'r', '_', 's', 'c', 'a', 'l', +'e', '_', 'f', 'a', 'c', 't', 'o', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', 'D', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', +'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '.', 'S', 'c', 'a', 'l', 'e', 'T', 'i', +'m', 'e', 'r', 's', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'A', 'c', 't', 'i', 'o', 'n', 'C', 'o', 'n', 'f', 'i', 'g', '.', +'S', 'c', 'a', 'l', 'e', 'T', 'i', 'm', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\021', 't', 'i', 'm', +'e', 'r', 'S', 'c', 'a', 'l', 'e', 'F', 'a', 'c', 't', 'o', 'r', 's', '\032', '\200', '\002', '\n', '\n', 'S', 'c', 'a', 'l', 'e', 'T', +'i', 'm', 'e', 'r', '\022', 'e', '\n', '\005', 't', 'i', 'm', 'e', 'r', '\030', '\001', ' ', '\001', '(', '\016', '2', 'C', '.', 'e', 'n', 'v', +'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '.', 'S', 'c', 'a', +'l', 'e', 'T', 'i', 'm', 'e', 'r', 's', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'A', 'c', 't', 'i', 'o', 'n', 'C', 'o', 'n', +'f', 'i', 'g', '.', 'T', 'i', 'm', 'e', 'r', 'T', 'y', 'p', 'e', 'B', '\n', '\372', 'B', '\007', '\202', '\001', '\004', '\020', '\001', ' ', '\000', +'R', '\005', 't', 'i', 'm', 'e', 'r', '\022', '<', '\n', '\013', 'm', 'i', 'n', '_', 't', 'i', 'm', 'e', 'o', 'u', 't', '\030', '\002', ' ', +'\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'D', 'u', 'r', +'a', 't', 'i', 'o', 'n', 'H', '\000', 'R', '\n', 'm', 'i', 'n', 'T', 'i', 'm', 'e', 'o', 'u', 't', '\022', '5', '\n', '\t', 'm', 'i', +'n', '_', 's', 'c', 'a', 'l', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '\026', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', +'e', '.', 'v', '3', '.', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'H', '\000', 'R', '\010', 'm', 'i', 'n', 'S', 'c', 'a', 'l', 'e', 'B', +'\026', '\n', '\017', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '_', 'a', 'd', 'j', 'u', 's', 't', '\022', '\003', '\370', 'B', '\001', '\"', '\200', +'\001', '\n', '\t', 'T', 'i', 'm', 'e', 'r', 'T', 'y', 'p', 'e', '\022', '\017', '\n', '\013', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', +'E', 'D', '\020', '\000', '\022', '#', '\n', '\037', 'H', 'T', 'T', 'P', '_', 'D', 'O', 'W', 'N', 'S', 'T', 'R', 'E', 'A', 'M', '_', 'C', +'O', 'N', 'N', 'E', 'C', 'T', 'I', 'O', 'N', '_', 'I', 'D', 'L', 'E', '\020', '\001', '\022', '\037', '\n', '\033', 'H', 'T', 'T', 'P', '_', +'D', 'O', 'W', 'N', 'S', 'T', 'R', 'E', 'A', 'M', '_', 'S', 'T', 'R', 'E', 'A', 'M', '_', 'I', 'D', 'L', 'E', '\020', '\002', '\022', +'\034', '\n', '\030', 'T', 'R', 'A', 'N', 'S', 'P', 'O', 'R', 'T', '_', 'S', 'O', 'C', 'K', 'E', 'T', '_', 'C', 'O', 'N', 'N', 'E', +'C', 'T', '\020', '\003', '\"', '\344', '\001', '\n', '\016', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\033', +'\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'R', '\004', 'n', 'a', +'m', 'e', '\022', 'G', '\n', '\010', 't', 'r', 'i', 'g', 'g', 'e', 'r', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '!', '.', 'e', 'n', +'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '.', 'T', 'r', +'i', 'g', 'g', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\010', 't', 'r', 'i', 'g', 'g', 'e', 'r', 's', +'\022', '7', '\n', '\014', 't', 'y', 'p', 'e', 'd', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\024', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'A', 'n', 'y', 'R', '\013', 't', 'y', 'p', 'e', +'d', 'C', 'o', 'n', 'f', 'i', 'g', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', +'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '2', 'a', 'l', 'p', 'h', 'a', '.', 'O', 'v', 'e', 'r', +'l', 'o', 'a', 'd', 'A', 'c', 't', 'i', 'o', 'n', '\"', '\263', '\002', '\n', '\017', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'M', 'a', +'n', 'a', 'g', 'e', 'r', '\022', 'D', '\n', '\020', 'r', 'e', 'f', 'r', 'e', 's', 'h', '_', 'i', 'n', 't', 'e', 'r', 'v', 'a', 'l', +'\030', '\001', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', +'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', '\017', 'r', 'e', 'f', 'r', 'e', 's', 'h', 'I', 'n', 't', 'e', 'r', 'v', 'a', 'l', +'\022', '`', '\n', '\021', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', '_', 'm', 'o', 'n', 'i', 't', 'o', 'r', 's', '\030', '\002', ' ', '\003', +'(', '\013', '2', ')', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', +'d', '.', 'v', '3', '.', 'R', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'M', 'o', 'n', 'i', 't', 'o', 'r', 'B', '\010', '\372', 'B', '\005', +'\222', '\001', '\002', '\010', '\001', 'R', '\020', 'r', 'e', 's', 'o', 'u', 'r', 'c', 'e', 'M', 'o', 'n', 'i', 't', 'o', 'r', 's', '\022', 'B', +'\n', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '(', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', +'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', '.', 'O', 'v', 'e', 'r', 'l', 'o', 'a', +'d', 'A', 'c', 't', 'i', 'o', 'n', 'R', '\007', 'a', 'c', 't', 'i', 'o', 'n', 's', ':', '4', '\232', '\305', '\210', '\036', '/', '\n', '-', +'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '2', 'a', +'l', 'p', 'h', 'a', '.', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'M', 'a', 'n', 'a', 'g', 'e', 'r', 'B', 'A', '\n', '&', 'i', +'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', +'.', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '.', 'v', '3', 'B', '\r', 'O', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'P', 'r', 'o', +'t', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[7] = { + &envoy_type_v3_percent_proto_upbdefinit, + &google_protobuf_any_proto_upbdefinit, + &google_protobuf_duration_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + &validate_validate_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_config_overload_v3_overload_proto_upbdefinit = { + deps, + layouts, + "envoy/config/overload/v3/overload.proto", + UPB_STRVIEW_INIT(descriptor, 2145) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h new file mode 100644 index 00000000000..ca1dc51729c --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h @@ -0,0 +1,70 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/overload/v3/overload.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_CONFIG_OVERLOAD_V3_OVERLOAD_PROTO_UPBDEFS_H_ +#define ENVOY_CONFIG_OVERLOAD_V3_OVERLOAD_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_config_overload_v3_overload_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_ResourceMonitor_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.ResourceMonitor"); +} + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_ThresholdTrigger_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.ThresholdTrigger"); +} + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_ScaledTrigger_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.ScaledTrigger"); +} + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_Trigger_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.Trigger"); +} + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.ScaleTimersOverloadActionConfig"); +} + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_ScaleTimersOverloadActionConfig_ScaleTimer_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.ScaleTimersOverloadActionConfig.ScaleTimer"); +} + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_OverloadAction_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.OverloadAction"); +} + +UPB_INLINE const upb_msgdef *envoy_config_overload_v3_OverloadManager_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_overload_v3_overload_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.overload.v3.OverloadManager"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_CONFIG_OVERLOAD_V3_OVERLOAD_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c new file mode 100644 index 00000000000..1ee8a91170c --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c @@ -0,0 +1,102 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/common/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/extensions/filters/common/fault/v3/fault.upbdefs.h" + +extern upb_def_init envoy_type_v3_percent_proto_upbdefinit; +extern upb_def_init google_protobuf_duration_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern upb_def_init validate_validate_proto_upbdefinit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultDelay_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit; +extern const upb_msglayout envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit; + +static const upb_msglayout *layouts[5] = { + &envoy_extensions_filters_common_fault_v3_FaultDelay_msginit, + &envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_msginit, + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_msginit, + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_msginit, + &envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_msginit, +}; + +static const char descriptor[1354] = {'\n', '4', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 'f', 'i', 'l', 't', 'e', 'r', +'s', '/', 'c', 'o', 'm', 'm', 'o', 'n', '/', 'f', 'a', 'u', 'l', 't', '/', 'v', '3', '/', 'f', 'a', 'u', 'l', 't', '.', 'p', +'r', 'o', 't', 'o', '\022', '(', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', +'l', 't', 'e', 'r', 's', '.', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', '\032', '\033', 'e', 'n', +'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'v', '3', '/', 'p', 'e', 'r', 'c', 'e', 'n', 't', '.', 'p', 'r', 'o', 't', 'o', +'\032', '\036', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'd', 'u', 'r', 'a', 't', 'i', 'o', +'n', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', +'/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', +'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', +'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\304', +'\003', '\n', '\n', 'F', 'a', 'u', 'l', 't', 'D', 'e', 'l', 'a', 'y', '\022', 'F', '\n', '\013', 'f', 'i', 'x', 'e', 'd', '_', 'd', 'e', +'l', 'a', 'y', '\030', '\003', ' ', '\001', '(', '\013', '2', '\031', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\252', '\001', '\002', '*', '\000', 'H', '\000', 'R', '\n', +'f', 'i', 'x', 'e', 'd', 'D', 'e', 'l', 'a', 'y', '\022', 'e', '\n', '\014', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'd', 'e', 'l', 'a', +'y', '\030', '\005', ' ', '\001', '(', '\013', '2', '@', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', +'s', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', +'.', 'F', 'a', 'u', 'l', 't', 'D', 'e', 'l', 'a', 'y', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'D', 'e', 'l', 'a', 'y', 'H', '\000', +'R', '\013', 'h', 'e', 'a', 'd', 'e', 'r', 'D', 'e', 'l', 'a', 'y', '\022', '@', '\n', '\n', 'p', 'e', 'r', 'c', 'e', 'n', 't', 'a', +'g', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', +'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\n', 'p', 'e', 'r', 'c', 'e', 'n', +'t', 'a', 'g', 'e', '\032', 'I', '\n', '\013', 'H', 'e', 'a', 'd', 'e', 'r', 'D', 'e', 'l', 'a', 'y', ':', ':', '\232', '\305', '\210', '\036', +'5', '\n', '3', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'f', 'a', +'u', 'l', 't', '.', 'v', '2', '.', 'F', 'a', 'u', 'l', 't', 'D', 'e', 'l', 'a', 'y', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'D', +'e', 'l', 'a', 'y', '\"', '\033', '\n', '\016', 'F', 'a', 'u', 'l', 't', 'D', 'e', 'l', 'a', 'y', 'T', 'y', 'p', 'e', '\022', '\t', '\n', +'\005', 'F', 'I', 'X', 'E', 'D', '\020', '\000', ':', '.', '\232', '\305', '\210', '\036', ')', '\n', '\'', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', +'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '2', '.', 'F', 'a', 'u', 'l', +'t', 'D', 'e', 'l', 'a', 'y', 'B', '\033', '\n', '\024', 'f', 'a', 'u', 'l', 't', '_', 'd', 'e', 'l', 'a', 'y', '_', 's', 'e', 'c', +'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'J', '\004', '\010', '\002', '\020', '\003', 'J', '\004', '\010', '\001', '\020', '\002', 'R', '\004', 't', +'y', 'p', 'e', '\"', '\260', '\004', '\n', '\016', 'F', 'a', 'u', 'l', 't', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '\022', 'f', '\n', +'\013', 'f', 'i', 'x', 'e', 'd', '_', 'l', 'i', 'm', 'i', 't', '\030', '\001', ' ', '\001', '(', '\013', '2', 'C', '.', 'e', 'n', 'v', 'o', +'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'c', 'o', 'm', 'm', +'o', 'n', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', '.', 'F', 'a', 'u', 'l', 't', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', +'t', '.', 'F', 'i', 'x', 'e', 'd', 'L', 'i', 'm', 'i', 't', 'H', '\000', 'R', '\n', 'f', 'i', 'x', 'e', 'd', 'L', 'i', 'm', 'i', +'t', '\022', 'i', '\n', '\014', 'h', 'e', 'a', 'd', 'e', 'r', '_', 'l', 'i', 'm', 'i', 't', '\030', '\003', ' ', '\001', '(', '\013', '2', 'D', +'.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', +'.', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', '.', 'F', 'a', 'u', 'l', 't', 'R', 'a', 't', +'e', 'L', 'i', 'm', 'i', 't', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'L', 'i', 'm', 'i', 't', 'H', '\000', 'R', '\013', 'h', 'e', 'a', +'d', 'e', 'r', 'L', 'i', 'm', 'i', 't', '\022', '@', '\n', '\n', 'p', 'e', 'r', 'c', 'e', 'n', 't', 'a', 'g', 'e', '\030', '\002', ' ', +'\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'v', '3', '.', 'F', 'r', 'a', 'c', 't', +'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\n', 'p', 'e', 'r', 'c', 'e', 'n', 't', 'a', 'g', 'e', '\032', +'s', '\n', '\n', 'F', 'i', 'x', 'e', 'd', 'L', 'i', 'm', 'i', 't', '\022', '&', '\n', '\n', 'l', 'i', 'm', 'i', 't', '_', 'k', 'b', +'p', 's', '\030', '\001', ' ', '\001', '(', '\004', 'B', '\007', '\372', 'B', '\004', '2', '\002', '(', '\001', 'R', '\t', 'l', 'i', 'm', 'i', 't', 'K', +'b', 'p', 's', ':', '=', '\232', '\305', '\210', '\036', '8', '\n', '6', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'f', 'i', 'l', 't', 'e', 'r', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '2', '.', 'F', 'a', 'u', 'l', 't', 'R', 'a', 't', 'e', +'L', 'i', 'm', 'i', 't', '.', 'F', 'i', 'x', 'e', 'd', 'L', 'i', 'm', 'i', 't', '\032', 'M', '\n', '\013', 'H', 'e', 'a', 'd', 'e', +'r', 'L', 'i', 'm', 'i', 't', ':', '>', '\232', '\305', '\210', '\036', '9', '\n', '7', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', +'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '2', '.', 'F', 'a', 'u', 'l', 't', 'R', +'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'L', 'i', 'm', 'i', 't', ':', '2', '\232', '\305', '\210', +'\036', '-', '\n', '+', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'f', +'a', 'u', 'l', 't', '.', 'v', '2', '.', 'F', 'a', 'u', 'l', 't', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'B', '\021', '\n', +'\n', 'l', 'i', 'm', 'i', 't', '_', 't', 'y', 'p', 'e', '\022', '\003', '\370', 'B', '\001', 'B', 'N', '\n', '6', 'i', 'o', '.', 'e', 'n', +'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', +'.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', 'B', +'\n', 'F', 'a', 'u', 'l', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', +'o', 't', 'o', '3', +}; + +static upb_def_init *deps[6] = { + &envoy_type_v3_percent_proto_upbdefinit, + &google_protobuf_duration_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + &validate_validate_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit = { + deps, + layouts, + "envoy/extensions/filters/common/fault/v3/fault.proto", + UPB_STRVIEW_INIT(descriptor, 1354) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h new file mode 100644 index 00000000000..f3d64b4f3b2 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h @@ -0,0 +1,55 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/common/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_FILTERS_COMMON_FAULT_V3_FAULT_PROTO_UPBDEFS_H_ +#define ENVOY_EXTENSIONS_FILTERS_COMMON_FAULT_V3_FAULT_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_common_fault_v3_FaultDelay_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.common.fault.v3.FaultDelay"); +} + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_common_fault_v3_FaultDelay_HeaderDelay_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.common.fault.v3.FaultDelay.HeaderDelay"); +} + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_common_fault_v3_FaultRateLimit_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.common.fault.v3.FaultRateLimit"); +} + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_common_fault_v3_FaultRateLimit_FixedLimit_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.common.fault.v3.FaultRateLimit.FixedLimit"); +} + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_common_fault_v3_FaultRateLimit_HeaderLimit_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.common.fault.v3.FaultRateLimit.HeaderLimit"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_FILTERS_COMMON_FAULT_V3_FAULT_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c new file mode 100644 index 00000000000..cd46e9352e3 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c @@ -0,0 +1,120 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/extensions/filters/http/fault/v3/fault.upbdefs.h" + +extern upb_def_init envoy_config_route_v3_route_components_proto_upbdefinit; +extern upb_def_init envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit; +extern upb_def_init envoy_type_v3_percent_proto_upbdefinit; +extern upb_def_init google_protobuf_wrappers_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern upb_def_init validate_validate_proto_upbdefinit; +extern const upb_msglayout envoy_extensions_filters_http_fault_v3_FaultAbort_msginit; +extern const upb_msglayout envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit; +extern const upb_msglayout envoy_extensions_filters_http_fault_v3_HTTPFault_msginit; + +static const upb_msglayout *layouts[3] = { + &envoy_extensions_filters_http_fault_v3_FaultAbort_msginit, + &envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_msginit, + &envoy_extensions_filters_http_fault_v3_HTTPFault_msginit, +}; + +static const char descriptor[1812] = {'\n', '2', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '/', 'f', 'i', 'l', 't', 'e', 'r', +'s', '/', 'h', 't', 't', 'p', '/', 'f', 'a', 'u', 'l', 't', '/', 'v', '3', '/', 'f', 'a', 'u', 'l', 't', '.', 'p', 'r', 'o', +'t', 'o', '\022', '&', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', +'e', 'r', 's', '.', 'h', 't', 't', 'p', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', '\032', ',', 'e', 'n', 'v', 'o', 'y', '/', +'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'o', 'u', 't', 'e', '/', 'v', '3', '/', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'm', +'p', 'o', 'n', 'e', 'n', 't', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '4', 'e', 'n', 'v', 'o', 'y', '/', 'e', 'x', 't', 'e', +'n', 's', 'i', 'o', 'n', 's', '/', 'f', 'i', 'l', 't', 'e', 'r', 's', '/', 'c', 'o', 'm', 'm', 'o', 'n', '/', 'f', 'a', 'u', +'l', 't', '/', 'v', '3', '/', 'f', 'a', 'u', 'l', 't', '.', 'p', 'r', 'o', 't', 'o', '\032', '\033', 'e', 'n', 'v', 'o', 'y', '/', +'t', 'y', 'p', 'e', '/', 'v', '3', '/', 'p', 'e', 'r', 'c', 'e', 'n', 't', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'g', 'o', +'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'w', 'r', 'a', 'p', 'p', 'e', 'r', 's', '.', 'p', 'r', +'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', +'t', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', +'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', +'d', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\244', '\003', '\n', '\n', 'F', +'a', 'u', 'l', 't', 'A', 'b', 'o', 'r', 't', '\022', '.', '\n', '\013', 'h', 't', 't', 'p', '_', 's', 't', 'a', 't', 'u', 's', '\030', +'\002', ' ', '\001', '(', '\r', 'B', '\013', '\372', 'B', '\010', '*', '\006', '\020', '\330', '\004', '(', '\310', '\001', 'H', '\000', 'R', '\n', 'h', 't', 't', +'p', 'S', 't', 'a', 't', 'u', 's', '\022', '!', '\n', '\013', 'g', 'r', 'p', 'c', '_', 's', 't', 'a', 't', 'u', 's', '\030', '\005', ' ', +'\001', '(', '\r', 'H', '\000', 'R', '\n', 'g', 'r', 'p', 'c', 'S', 't', 'a', 't', 'u', 's', '\022', 'c', '\n', '\014', 'h', 'e', 'a', 'd', +'e', 'r', '_', 'a', 'b', 'o', 'r', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '>', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', +'t', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'h', 't', 't', 'p', '.', 'f', 'a', 'u', +'l', 't', '.', 'v', '3', '.', 'F', 'a', 'u', 'l', 't', 'A', 'b', 'o', 'r', 't', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'A', 'b', +'o', 'r', 't', 'H', '\000', 'R', '\013', 'h', 'e', 'a', 'd', 'e', 'r', 'A', 'b', 'o', 'r', 't', '\022', '@', '\n', '\n', 'p', 'e', 'r', +'c', 'e', 'n', 't', 'a', 'g', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', +'e', '.', 'v', '3', '.', 'F', 'r', 'a', 'c', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', '\n', 'p', +'e', 'r', 'c', 'e', 'n', 't', 'a', 'g', 'e', '\032', 'N', '\n', '\013', 'H', 'e', 'a', 'd', 'e', 'r', 'A', 'b', 'o', 'r', 't', ':', +'?', '\232', '\305', '\210', '\036', ':', '\n', '8', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', +'e', 'r', '.', 'h', 't', 't', 'p', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '2', '.', 'F', 'a', 'u', 'l', 't', 'A', 'b', 'o', +'r', 't', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'A', 'b', 'o', 'r', 't', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', +'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', 'e', 'r', '.', 'h', 't', 't', 'p', '.', 'f', 'a', +'u', 'l', 't', '.', 'v', '2', '.', 'F', 'a', 'u', 'l', 't', 'A', 'b', 'o', 'r', 't', 'B', '\021', '\n', '\n', 'e', 'r', 'r', 'o', +'r', '_', 't', 'y', 'p', 'e', '\022', '\003', '\370', 'B', '\001', 'J', '\004', '\010', '\001', '\020', '\002', '\"', '\274', '\007', '\n', '\t', 'H', 'T', 'T', +'P', 'F', 'a', 'u', 'l', 't', '\022', 'J', '\n', '\005', 'd', 'e', 'l', 'a', 'y', '\030', '\001', ' ', '\001', '(', '\013', '2', '4', '.', 'e', +'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'c', +'o', 'm', 'm', 'o', 'n', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', '.', 'F', 'a', 'u', 'l', 't', 'D', 'e', 'l', 'a', 'y', +'R', '\005', 'd', 'e', 'l', 'a', 'y', '\022', 'H', '\n', '\005', 'a', 'b', 'o', 'r', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '2', '.', +'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', +'h', 't', 't', 'p', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '3', '.', 'F', 'a', 'u', 'l', 't', 'A', 'b', 'o', 'r', 't', 'R', +'\005', 'a', 'b', 'o', 'r', 't', '\022', ')', '\n', '\020', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', '_', 'c', 'l', 'u', 's', 't', 'e', +'r', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\017', 'u', 'p', 's', 't', 'r', 'e', 'a', 'm', 'C', 'l', 'u', 's', 't', 'e', 'r', '\022', +'>', '\n', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', +'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'o', 'u', 't', 'e', '.', 'v', '3', '.', 'H', 'e', 'a', 'd', 'e', 'r', 'M', 'a', 't', +'c', 'h', 'e', 'r', 'R', '\007', 'h', 'e', 'a', 'd', 'e', 'r', 's', '\022', ')', '\n', '\020', 'd', 'o', 'w', 'n', 's', 't', 'r', 'e', +'a', 'm', '_', 'n', 'o', 'd', 'e', 's', '\030', '\005', ' ', '\003', '(', '\t', 'R', '\017', 'd', 'o', 'w', 'n', 's', 't', 'r', 'e', 'a', +'m', 'N', 'o', 'd', 'e', 's', '\022', 'H', '\n', '\021', 'm', 'a', 'x', '_', 'a', 'c', 't', 'i', 'v', 'e', '_', 'f', 'a', 'u', 'l', +'t', 's', '\030', '\006', ' ', '\001', '(', '\013', '2', '\034', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', +'f', '.', 'U', 'I', 'n', 't', '3', '2', 'V', 'a', 'l', 'u', 'e', 'R', '\017', 'm', 'a', 'x', 'A', 'c', 't', 'i', 'v', 'e', 'F', +'a', 'u', 'l', 't', 's', '\022', 'h', '\n', '\023', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', 'r', 'a', 't', 'e', '_', 'l', 'i', +'m', 'i', 't', '\030', '\007', ' ', '\001', '(', '\013', '2', '8', '.', 'e', 'n', 'v', 'o', 'y', '.', 'e', 'x', 't', 'e', 'n', 's', 'i', +'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'c', 'o', 'm', 'm', 'o', 'n', '.', 'f', 'a', 'u', 'l', 't', '.', +'v', '3', '.', 'F', 'a', 'u', 'l', 't', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', 'R', '\021', 'r', 'e', 's', 'p', 'o', 'n', +'s', 'e', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', 't', '\022', '2', '\n', '\025', 'd', 'e', 'l', 'a', 'y', '_', 'p', 'e', 'r', 'c', +'e', 'n', 't', '_', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\030', '\010', ' ', '\001', '(', '\t', 'R', '\023', 'd', 'e', 'l', 'a', 'y', 'P', +'e', 'r', 'c', 'e', 'n', 't', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '2', '\n', '\025', 'a', 'b', 'o', 'r', 't', '_', 'p', 'e', +'r', 'c', 'e', 'n', 't', '_', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\030', '\t', ' ', '\001', '(', '\t', 'R', '\023', 'a', 'b', 'o', 'r', +'t', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '4', '\n', '\026', 'd', 'e', 'l', 'a', 'y', '_', +'d', 'u', 'r', 'a', 't', 'i', 'o', 'n', '_', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\030', '\n', ' ', '\001', '(', '\t', 'R', '\024', 'd', +'e', 'l', 'a', 'y', 'D', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '9', '\n', '\031', 'a', 'b', +'o', 'r', 't', '_', 'h', 't', 't', 'p', '_', 's', 't', 'a', 't', 'u', 's', '_', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\030', '\013', +' ', '\001', '(', '\t', 'R', '\026', 'a', 'b', 'o', 'r', 't', 'H', 't', 't', 'p', 'S', 't', 'a', 't', 'u', 's', 'R', 'u', 'n', 't', +'i', 'm', 'e', '\022', '9', '\n', '\031', 'm', 'a', 'x', '_', 'a', 'c', 't', 'i', 'v', 'e', '_', 'f', 'a', 'u', 'l', 't', 's', '_', +'r', 'u', 'n', 't', 'i', 'm', 'e', '\030', '\014', ' ', '\001', '(', '\t', 'R', '\026', 'm', 'a', 'x', 'A', 'c', 't', 'i', 'v', 'e', 'F', +'a', 'u', 'l', 't', 's', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', 'L', '\n', '#', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', '_', +'r', 'a', 't', 'e', '_', 'l', 'i', 'm', 'i', 't', '_', 'p', 'e', 'r', 'c', 'e', 'n', 't', '_', 'r', 'u', 'n', 't', 'i', 'm', +'e', '\030', '\r', ' ', '\001', '(', '\t', 'R', '\037', 'r', 'e', 's', 'p', 'o', 'n', 's', 'e', 'R', 'a', 't', 'e', 'L', 'i', 'm', 'i', +'t', 'P', 'e', 'r', 'c', 'e', 'n', 't', 'R', 'u', 'n', 't', 'i', 'm', 'e', '\022', '9', '\n', '\031', 'a', 'b', 'o', 'r', 't', '_', +'g', 'r', 'p', 'c', '_', 's', 't', 'a', 't', 'u', 's', '_', 'r', 'u', 'n', 't', 'i', 'm', 'e', '\030', '\016', ' ', '\001', '(', '\t', +'R', '\026', 'a', 'b', 'o', 'r', 't', 'G', 'r', 'p', 'c', 'S', 't', 'a', 't', 'u', 's', 'R', 'u', 'n', 't', 'i', 'm', 'e', ':', +'2', '\232', '\305', '\210', '\036', '-', '\n', '+', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'f', 'i', 'l', 't', +'e', 'r', '.', 'h', 't', 't', 'p', '.', 'f', 'a', 'u', 'l', 't', '.', 'v', '2', '.', 'H', 'T', 'T', 'P', 'F', 'a', 'u', 'l', +'t', 'B', 'L', '\n', '4', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', +'e', 'x', 't', 'e', 'n', 's', 'i', 'o', 'n', 's', '.', 'f', 'i', 'l', 't', 'e', 'r', 's', '.', 'h', 't', 't', 'p', '.', 'f', +'a', 'u', 'l', 't', '.', 'v', '3', 'B', '\n', 'F', 'a', 'u', 'l', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', +'\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[8] = { + &envoy_config_route_v3_route_components_proto_upbdefinit, + &envoy_extensions_filters_common_fault_v3_fault_proto_upbdefinit, + &envoy_type_v3_percent_proto_upbdefinit, + &google_protobuf_wrappers_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + &validate_validate_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_extensions_filters_http_fault_v3_fault_proto_upbdefinit = { + deps, + layouts, + "envoy/extensions/filters/http/fault/v3/fault.proto", + UPB_STRVIEW_INIT(descriptor, 1812) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h new file mode 100644 index 00000000000..0beb986b665 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h @@ -0,0 +1,45 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/fault/v3/fault.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_FILTERS_HTTP_FAULT_V3_FAULT_PROTO_UPBDEFS_H_ +#define ENVOY_EXTENSIONS_FILTERS_HTTP_FAULT_V3_FAULT_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_extensions_filters_http_fault_v3_fault_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_http_fault_v3_FaultAbort_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_http_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.http.fault.v3.FaultAbort"); +} + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_http_fault_v3_FaultAbort_HeaderAbort_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_http_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.http.fault.v3.FaultAbort.HeaderAbort"); +} + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_http_fault_v3_HTTPFault_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_http_fault_v3_fault_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.http.fault.v3.HTTPFault"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_FILTERS_HTTP_FAULT_V3_FAULT_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c new file mode 100644 index 00000000000..2673ebbbdee --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c @@ -0,0 +1,130 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/status/v3/csds.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/service/status/v3/csds.upbdefs.h" + +extern upb_def_init envoy_admin_v3_config_dump_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_base_proto_upbdefinit; +extern upb_def_init envoy_type_matcher_v3_node_proto_upbdefinit; +extern upb_def_init google_api_annotations_proto_upbdefinit; +extern upb_def_init udpa_annotations_migrate_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern const upb_msglayout envoy_service_status_v3_ClientStatusRequest_msginit; +extern const upb_msglayout envoy_service_status_v3_PerXdsConfig_msginit; +extern const upb_msglayout envoy_service_status_v3_ClientConfig_msginit; +extern const upb_msglayout envoy_service_status_v3_ClientStatusResponse_msginit; + +static const upb_msglayout *layouts[4] = { + &envoy_service_status_v3_ClientStatusRequest_msginit, + &envoy_service_status_v3_PerXdsConfig_msginit, + &envoy_service_status_v3_ClientConfig_msginit, + &envoy_service_status_v3_ClientStatusResponse_msginit, +}; + +static const char descriptor[2001] = {'\n', '\"', 'e', 'n', 'v', 'o', 'y', '/', 's', 'e', 'r', 'v', 'i', 'c', 'e', '/', 's', 't', 'a', 't', 'u', 's', '/', 'v', '3', +'/', 'c', 's', 'd', 's', '.', 'p', 'r', 'o', 't', 'o', '\022', '\027', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', +'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '\032', ' ', 'e', 'n', 'v', 'o', 'y', '/', 'a', 'd', 'm', 'i', 'n', '/', +'v', '3', '/', 'c', 'o', 'n', 'f', 'i', 'g', '_', 'd', 'u', 'm', 'p', '.', 'p', 'r', 'o', 't', 'o', '\032', '\037', 'e', 'n', 'v', +'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'c', 'o', 'r', 'e', '/', 'v', '3', '/', 'b', 'a', 's', 'e', '.', 'p', 'r', +'o', 't', 'o', '\032', ' ', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', +'3', '/', 'n', 'o', 'd', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\034', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', +'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '\036', 'u', 'd', 'p', 'a', '/', 'a', +'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'm', 'i', 'g', 'r', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', +'\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', +'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', +'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\"', '\302', '\001', '\n', '\023', 'C', 'l', 'i', 'e', 'n', +'t', 'S', 't', 'a', 't', 'u', 's', 'R', 'e', 'q', 'u', 'e', 's', 't', '\022', 'G', '\n', '\r', 'n', 'o', 'd', 'e', '_', 'm', 'a', +'t', 'c', 'h', 'e', 'r', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', +'.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'N', 'o', 'd', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\014', +'n', 'o', 'd', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', 's', '\022', '.', '\n', '\004', 'n', 'o', 'd', 'e', '\030', '\002', ' ', '\001', '(', +'\013', '2', '\032', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', +'N', 'o', 'd', 'e', 'R', '\004', 'n', 'o', 'd', 'e', ':', '2', '\232', '\305', '\210', '\036', '-', '\n', '+', 'e', 'n', 'v', 'o', 'y', '.', +'s', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '2', '.', 'C', 'l', 'i', 'e', 'n', 't', 'S', +'t', 'a', 't', 'u', 's', 'R', 'e', 'q', 'u', 'e', 's', 't', '\"', '\360', '\004', '\n', '\014', 'P', 'e', 'r', 'X', 'd', 's', 'C', 'o', +'n', 'f', 'i', 'g', '\022', '=', '\n', '\006', 's', 't', 'a', 't', 'u', 's', '\030', '\001', ' ', '\001', '(', '\016', '2', '%', '.', 'e', 'n', +'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'o', 'n', +'f', 'i', 'g', 'S', 't', 'a', 't', 'u', 's', 'R', '\006', 's', 't', 'a', 't', 'u', 's', '\022', 'T', '\n', '\r', 'c', 'l', 'i', 'e', +'n', 't', '_', 's', 't', 'a', 't', 'u', 's', '\030', '\007', ' ', '\001', '(', '\016', '2', '+', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', +'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'o', +'n', 'f', 'i', 'g', 'S', 't', 'a', 't', 'u', 's', 'B', '\002', '\030', '\001', 'R', '\014', 'c', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', +'t', 'u', 's', '\022', 'N', '\n', '\017', 'l', 'i', 's', 't', 'e', 'n', 'e', 'r', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', +'\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'L', 'i', 's', 't', +'e', 'n', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', 'H', '\000', 'R', '\016', 'l', 'i', 's', 't', 'e', 'n', +'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'K', '\n', '\016', 'c', 'l', 'u', 's', 't', 'e', 'r', '_', 'c', 'o', 'n', 'f', 'i', +'g', '\030', '\003', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', +'C', 'l', 'u', 's', 't', 'e', 'r', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', 'H', '\000', 'R', '\r', 'c', 'l', 'u', +'s', 't', 'e', 'r', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'E', '\n', '\014', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', 'n', 'f', 'i', +'g', '\030', '\004', ' ', '\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', +'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', 'H', '\000', 'R', '\013', 'r', 'o', 'u', 't', 'e', +'C', 'o', 'n', 'f', 'i', 'g', '\022', 'X', '\n', '\023', 's', 'c', 'o', 'p', 'e', 'd', '_', 'r', 'o', 'u', 't', 'e', '_', 'c', 'o', +'n', 'f', 'i', 'g', '\030', '\005', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', +'v', '3', '.', 'S', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', +'H', '\000', 'R', '\021', 's', 'c', 'o', 'p', 'e', 'd', 'R', 'o', 'u', 't', 'e', 'C', 'o', 'n', 'f', 'i', 'g', '\022', 'N', '\n', '\017', +'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\006', ' ', '\001', '(', '\013', '2', '#', '.', 'e', +'n', 'v', 'o', 'y', '.', 'a', 'd', 'm', 'i', 'n', '.', 'v', '3', '.', 'E', 'n', 'd', 'p', 'o', 'i', 'n', 't', 's', 'C', 'o', +'n', 'f', 'i', 'g', 'D', 'u', 'm', 'p', 'H', '\000', 'R', '\016', 'e', 'n', 'd', 'p', 'o', 'i', 'n', 't', 'C', 'o', 'n', 'f', 'i', +'g', ':', '+', '\232', '\305', '\210', '\036', '&', '\n', '$', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', +'t', 'a', 't', 'u', 's', '.', 'v', '2', '.', 'P', 'e', 'r', 'X', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'B', '\020', '\n', '\016', +'p', 'e', 'r', '_', 'x', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\"', '\261', '\001', '\n', '\014', 'C', 'l', 'i', 'e', 'n', 't', +'C', 'o', 'n', 'f', 'i', 'g', '\022', '.', '\n', '\004', 'n', 'o', 'd', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\032', '.', 'e', 'n', +'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'N', 'o', 'd', 'e', 'R', '\004', +'n', 'o', 'd', 'e', '\022', 'D', '\n', '\n', 'x', 'd', 's', '_', 'c', 'o', 'n', 'f', 'i', 'g', '\030', '\002', ' ', '\003', '(', '\013', '2', +'%', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', +'.', 'P', 'e', 'r', 'X', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', 'R', '\t', 'x', 'd', 's', 'C', 'o', 'n', 'f', 'i', 'g', ':', +'+', '\232', '\305', '\210', '\036', '&', '\n', '$', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', +'t', 'u', 's', '.', 'v', '2', '.', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', '\"', '\212', '\001', '\n', '\024', 'C', +'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '\022', '=', '\n', '\006', 'c', 'o', +'n', 'f', 'i', 'g', '\030', '\001', ' ', '\003', '(', '\013', '2', '%', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', +'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'o', 'n', 'f', 'i', 'g', 'R', +'\006', 'c', 'o', 'n', 'f', 'i', 'g', ':', '3', '\232', '\305', '\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', +'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '2', '.', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', +'u', 's', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '*', 'K', '\n', '\014', 'C', 'o', 'n', 'f', 'i', 'g', 'S', 't', 'a', 't', 'u', +'s', '\022', '\013', '\n', '\007', 'U', 'N', 'K', 'N', 'O', 'W', 'N', '\020', '\000', '\022', '\n', '\n', '\006', 'S', 'Y', 'N', 'C', 'E', 'D', '\020', +'\001', '\022', '\014', '\n', '\010', 'N', 'O', 'T', '_', 'S', 'E', 'N', 'T', '\020', '\002', '\022', '\t', '\n', '\005', 'S', 'T', 'A', 'L', 'E', '\020', +'\003', '\022', '\t', '\n', '\005', 'E', 'R', 'R', 'O', 'R', '\020', '\004', '*', 'c', '\n', '\022', 'C', 'l', 'i', 'e', 'n', 't', 'C', 'o', 'n', +'f', 'i', 'g', 'S', 't', 'a', 't', 'u', 's', '\022', '\022', '\n', '\016', 'C', 'L', 'I', 'E', 'N', 'T', '_', 'U', 'N', 'K', 'N', 'O', +'W', 'N', '\020', '\000', '\022', '\024', '\n', '\020', 'C', 'L', 'I', 'E', 'N', 'T', '_', 'R', 'E', 'Q', 'U', 'E', 'S', 'T', 'E', 'D', '\020', +'\001', '\022', '\020', '\n', '\014', 'C', 'L', 'I', 'E', 'N', 'T', '_', 'A', 'C', 'K', 'E', 'D', '\020', '\002', '\022', '\021', '\n', '\r', 'C', 'L', +'I', 'E', 'N', 'T', '_', 'N', 'A', 'C', 'K', 'E', 'D', '\020', '\003', '2', '\270', '\002', '\n', '\034', 'C', 'l', 'i', 'e', 'n', 't', 'S', +'t', 'a', 't', 'u', 's', 'D', 'i', 's', 'c', 'o', 'v', 'e', 'r', 'y', 'S', 'e', 'r', 'v', 'i', 'c', 'e', '\022', 'w', '\n', '\022', +'S', 't', 'r', 'e', 'a', 'm', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', '\022', ',', '.', 'e', 'n', 'v', 'o', +'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', +'t', 'S', 't', 'a', 't', 'u', 's', 'R', 'e', 'q', 'u', 'e', 's', 't', '\032', '-', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', +'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', +'t', 'u', 's', 'R', 'e', 's', 'p', 'o', 'n', 's', 'e', '\"', '\000', '(', '\001', '0', '\001', '\022', '\236', '\001', '\n', '\021', 'F', 'e', 't', +'c', 'h', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', '\022', ',', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', +'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', +'t', 'u', 's', 'R', 'e', 'q', 'u', 'e', 's', 't', '\032', '-', '.', 'e', 'n', 'v', 'o', 'y', '.', 's', 'e', 'r', 'v', 'i', 'c', +'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', '.', 'C', 'l', 'i', 'e', 'n', 't', 'S', 't', 'a', 't', 'u', 's', 'R', +'e', 's', 'p', 'o', 'n', 's', 'e', '\"', ',', '\202', '\323', '\344', '\223', '\002', '\035', '\"', '\033', '/', 'v', '3', '/', 'd', 'i', 's', 'c', +'o', 'v', 'e', 'r', 'y', ':', 'c', 'l', 'i', 'e', 'n', 't', '_', 's', 't', 'a', 't', 'u', 's', '\202', '\323', '\344', '\223', '\002', '\003', +':', '\001', '*', 'B', '?', '\n', '%', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', +'y', '.', 's', 'e', 'r', 'v', 'i', 'c', 'e', '.', 's', 't', 'a', 't', 'u', 's', '.', 'v', '3', 'B', '\t', 'C', 's', 'd', 's', +'P', 'r', 'o', 't', 'o', 'P', '\001', '\210', '\001', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', +'3', +}; + +static upb_def_init *deps[8] = { + &envoy_admin_v3_config_dump_proto_upbdefinit, + &envoy_config_core_v3_base_proto_upbdefinit, + &envoy_type_matcher_v3_node_proto_upbdefinit, + &google_api_annotations_proto_upbdefinit, + &udpa_annotations_migrate_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_service_status_v3_csds_proto_upbdefinit = { + deps, + layouts, + "envoy/service/status/v3/csds.proto", + UPB_STRVIEW_INIT(descriptor, 2001) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h new file mode 100644 index 00000000000..91723cc10ae --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h @@ -0,0 +1,50 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/service/status/v3/csds.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_SERVICE_STATUS_V3_CSDS_PROTO_UPBDEFS_H_ +#define ENVOY_SERVICE_STATUS_V3_CSDS_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_service_status_v3_csds_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_service_status_v3_ClientStatusRequest_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_service_status_v3_csds_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.service.status.v3.ClientStatusRequest"); +} + +UPB_INLINE const upb_msgdef *envoy_service_status_v3_PerXdsConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_service_status_v3_csds_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.service.status.v3.PerXdsConfig"); +} + +UPB_INLINE const upb_msgdef *envoy_service_status_v3_ClientConfig_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_service_status_v3_csds_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.service.status.v3.ClientConfig"); +} + +UPB_INLINE const upb_msgdef *envoy_service_status_v3_ClientStatusResponse_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_service_status_v3_csds_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.service.status.v3.ClientStatusResponse"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_SERVICE_STATUS_V3_CSDS_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c new file mode 100644 index 00000000000..8b0ecb58151 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c @@ -0,0 +1,56 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/node.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/type/matcher/v3/node.upbdefs.h" + +extern upb_def_init envoy_type_matcher_v3_string_proto_upbdefinit; +extern upb_def_init envoy_type_matcher_v3_struct_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern const upb_msglayout envoy_type_matcher_v3_NodeMatcher_msginit; + +static const upb_msglayout *layouts[1] = { + &envoy_type_matcher_v3_NodeMatcher_msginit, +}; + +static const char descriptor[458] = {'\n', ' ', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'n', +'o', 'd', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\025', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', +'c', 'h', 'e', 'r', '.', 'v', '3', '\032', '\"', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', +'e', 'r', '/', 'v', '3', '/', 's', 't', 'r', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\"', 'e', 'n', 'v', 'o', 'y', +'/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 's', 't', 'r', 'u', 'c', 't', '.', 'p', +'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', +'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', '\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', +'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', 'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\"', '\300', '\001', '\n', '\013', +'N', 'o', 'd', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', '\022', '=', '\n', '\007', 'n', 'o', 'd', 'e', '_', 'i', 'd', '\030', '\001', ' ', +'\001', '(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', +'v', '3', '.', 'S', 't', 'r', 'i', 'n', 'g', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\006', 'n', 'o', 'd', 'e', 'I', 'd', '\022', +'K', '\n', '\016', 'n', 'o', 'd', 'e', '_', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '$', +'.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', +'r', 'u', 'c', 't', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'R', '\r', 'n', 'o', 'd', 'e', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', +'s', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', +'h', 'e', 'r', '.', 'N', 'o', 'd', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', ':', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', +'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', +'r', '.', 'v', '3', 'B', '\t', 'N', 'o', 'd', 'e', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', +'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[5] = { + &envoy_type_matcher_v3_string_proto_upbdefinit, + &envoy_type_matcher_v3_struct_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_type_matcher_v3_node_proto_upbdefinit = { + deps, + layouts, + "envoy/type/matcher/v3/node.proto", + UPB_STRVIEW_INIT(descriptor, 458) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h new file mode 100644 index 00000000000..9ec4a6def6a --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h @@ -0,0 +1,35 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/node.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_TYPE_MATCHER_V3_NODE_PROTO_UPBDEFS_H_ +#define ENVOY_TYPE_MATCHER_V3_NODE_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_type_matcher_v3_node_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_type_matcher_v3_NodeMatcher_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_type_matcher_v3_node_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.type.matcher.v3.NodeMatcher"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_TYPE_MATCHER_V3_NODE_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c new file mode 100644 index 00000000000..6660ffad3a1 --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c @@ -0,0 +1,63 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/struct.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/type/matcher/v3/struct.upbdefs.h" + +extern upb_def_init envoy_type_matcher_v3_value_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +extern upb_def_init validate_validate_proto_upbdefinit; +extern const upb_msglayout envoy_type_matcher_v3_StructMatcher_msginit; +extern const upb_msglayout envoy_type_matcher_v3_StructMatcher_PathSegment_msginit; + +static const upb_msglayout *layouts[2] = { + &envoy_type_matcher_v3_StructMatcher_msginit, + &envoy_type_matcher_v3_StructMatcher_PathSegment_msginit, +}; + +static const char descriptor[576] = {'\n', '\"', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 's', +'t', 'r', 'u', 'c', 't', '.', 'p', 'r', 'o', 't', 'o', '\022', '\025', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', +'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '\032', '!', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', +'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'v', 'a', 'l', 'u', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '\035', 'u', 'd', 'p', 'a', +'/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', 'o', +'\032', '!', 'u', 'd', 'p', 'a', '/', 'a', 'n', 'n', 'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'v', 'e', 'r', 's', 'i', 'o', +'n', 'i', 'n', 'g', '.', 'p', 'r', 'o', 't', 'o', '\032', '\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', +'d', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', '\276', '\002', '\n', '\r', 'S', 't', 'r', 'u', 'c', 't', 'M', 'a', 't', 'c', +'h', 'e', 'r', '\022', 'N', '\n', '\004', 'p', 'a', 't', 'h', '\030', '\002', ' ', '\003', '(', '\013', '2', '0', '.', 'e', 'n', 'v', 'o', 'y', +'.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'S', 't', 'r', 'u', 'c', 't', 'M', 'a', +'t', 'c', 'h', 'e', 'r', '.', 'P', 'a', 't', 'h', 'S', 'e', 'g', 'm', 'e', 'n', 't', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', +'\010', '\001', 'R', '\004', 'p', 'a', 't', 'h', '\022', 'C', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\013', '2', '#', +'.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'V', 'a', +'l', 'u', 'e', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'B', '\010', '\372', 'B', '\005', '\212', '\001', '\002', '\020', '\001', 'R', '\005', 'v', 'a', 'l', +'u', 'e', '\032', 'o', '\n', '\013', 'P', 'a', 't', 'h', 'S', 'e', 'g', 'm', 'e', 'n', 't', '\022', '\033', '\n', '\003', 'k', 'e', 'y', '\030', +'\001', ' ', '\001', '(', '\t', 'B', '\007', '\372', 'B', '\004', 'r', '\002', '\020', '\001', 'H', '\000', 'R', '\003', 'k', 'e', 'y', ':', '3', '\232', '\305', +'\210', '\036', '.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'S', +'t', 'r', 'u', 'c', 't', 'M', 'a', 't', 'c', 'h', 'e', 'r', '.', 'P', 'a', 't', 'h', 'S', 'e', 'g', 'm', 'e', 'n', 't', 'B', +'\016', '\n', '\007', 's', 'e', 'g', 'm', 'e', 'n', 't', '\022', '\003', '\370', 'B', '\001', ':', '\'', '\232', '\305', '\210', '\036', '\"', '\n', ' ', 'e', +'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'S', 't', 'r', 'u', 'c', 't', 'M', +'a', 't', 'c', 'h', 'e', 'r', 'B', '<', '\n', '#', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', 'o', 'x', 'y', '.', 'e', +'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', 'B', '\013', 'S', 't', 'r', +'u', 'c', 't', 'P', 'r', 'o', 't', 'o', 'P', '\001', '\272', '\200', '\310', '\321', '\006', '\002', '\020', '\002', 'b', '\006', 'p', 'r', 'o', 't', 'o', +'3', +}; + +static upb_def_init *deps[5] = { + &envoy_type_matcher_v3_value_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + &validate_validate_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_type_matcher_v3_struct_proto_upbdefinit = { + deps, + layouts, + "envoy/type/matcher/v3/struct.proto", + UPB_STRVIEW_INIT(descriptor, 576) +}; diff --git a/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h new file mode 100644 index 00000000000..472d486aa8b --- /dev/null +++ b/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h @@ -0,0 +1,40 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/type/matcher/v3/struct.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_TYPE_MATCHER_V3_STRUCT_PROTO_UPBDEFS_H_ +#define ENVOY_TYPE_MATCHER_V3_STRUCT_PROTO_UPBDEFS_H_ + +#include "upb/def.h" +#include "upb/port_def.inc" +#ifdef __cplusplus +extern "C" { +#endif + +#include "upb/def.h" + +#include "upb/port_def.inc" + +extern upb_def_init envoy_type_matcher_v3_struct_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_type_matcher_v3_StructMatcher_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_type_matcher_v3_struct_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.type.matcher.v3.StructMatcher"); +} + +UPB_INLINE const upb_msgdef *envoy_type_matcher_v3_StructMatcher_PathSegment_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_type_matcher_v3_struct_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.type.matcher.v3.StructMatcher.PathSegment"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_TYPE_MATCHER_V3_STRUCT_PROTO_UPBDEFS_H_ */ diff --git a/src/core/ext/xds/certificate_provider_factory.h b/src/core/ext/xds/certificate_provider_factory.h index 84c219e66bf..e9bba790de8 100644 --- a/src/core/ext/xds/certificate_provider_factory.h +++ b/src/core/ext/xds/certificate_provider_factory.h @@ -49,7 +49,7 @@ class CertificateProviderFactory { virtual const char* name() const = 0; virtual RefCountedPtr CreateCertificateProviderConfig( - const Json& config_json, grpc_error** error) = 0; + const Json& config_json, grpc_error_handle* error) = 0; // Create a CertificateProvider instance from config. virtual RefCountedPtr diff --git a/src/core/ext/xds/certificate_provider_store.h b/src/core/ext/xds/certificate_provider_store.h index 0954bc5e809..fb6ca72d6d0 100644 --- a/src/core/ext/xds/certificate_provider_store.h +++ b/src/core/ext/xds/certificate_provider_store.h @@ -92,7 +92,7 @@ class CertificateProviderStore }; RefCountedPtr CreateCertificateProviderLocked( - absl::string_view key); + absl::string_view key) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); // Releases a previously created certificate provider from the certificate // provider map if the value matches \a wrapper. @@ -101,10 +101,10 @@ class CertificateProviderStore Mutex mu_; // Map of plugin configurations - PluginDefinitionMap plugin_config_map_; + PluginDefinitionMap plugin_config_map_ ABSL_GUARDED_BY(mu_); // Underlying map for the providers. std::map - certificate_providers_map_; + certificate_providers_map_ ABSL_GUARDED_BY(mu_); }; } // namespace grpc_core diff --git a/src/core/ext/xds/file_watcher_certificate_provider_factory.cc b/src/core/ext/xds/file_watcher_certificate_provider_factory.cc index a5250eba7c4..7a793b06737 100644 --- a/src/core/ext/xds/file_watcher_certificate_provider_factory.cc +++ b/src/core/ext/xds/file_watcher_certificate_provider_factory.cc @@ -64,14 +64,14 @@ std::string FileWatcherCertificateProviderFactory::Config::ToString() const { RefCountedPtr FileWatcherCertificateProviderFactory::Config::Parse(const Json& config_json, - grpc_error** error) { + grpc_error_handle* error) { auto config = MakeRefCounted(); if (config_json.type() != Json::Type::OBJECT) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "error:config type should be OBJECT."); return nullptr; } - std::vector error_list; + std::vector error_list; ParseJsonObjectField(config_json.object_value(), "certificate_file", &config->identity_cert_file_, &error_list, false); ParseJsonObjectField(config_json.object_value(), "private_key_file", @@ -112,7 +112,7 @@ const char* FileWatcherCertificateProviderFactory::name() const { RefCountedPtr FileWatcherCertificateProviderFactory::CreateCertificateProviderConfig( - const Json& config_json, grpc_error** error) { + const Json& config_json, grpc_error_handle* error) { return FileWatcherCertificateProviderFactory::Config::Parse(config_json, error); } diff --git a/src/core/ext/xds/file_watcher_certificate_provider_factory.h b/src/core/ext/xds/file_watcher_certificate_provider_factory.h index c5700625e95..13e10debb3a 100644 --- a/src/core/ext/xds/file_watcher_certificate_provider_factory.h +++ b/src/core/ext/xds/file_watcher_certificate_provider_factory.h @@ -31,7 +31,7 @@ class FileWatcherCertificateProviderFactory class Config : public CertificateProviderFactory::Config { public: static RefCountedPtr Parse(const Json& config_json, - grpc_error** error); + grpc_error_handle* error); const char* name() const override; @@ -58,7 +58,7 @@ class FileWatcherCertificateProviderFactory RefCountedPtr CreateCertificateProviderConfig(const Json& config_json, - grpc_error** error) override; + grpc_error_handle* error) override; RefCountedPtr CreateCertificateProvider( RefCountedPtr config) override; diff --git a/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.cc b/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.cc index c1b7b84a826..6e63ae4ef3c 100644 --- a/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.cc +++ b/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.cc @@ -52,10 +52,10 @@ std::string GoogleMeshCaCertificateProviderFactory::Config::ToString() const { return "{}"; } -std::vector +std::vector GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectStsService( const Json::Object& sts_service) { - std::vector error_list_sts_service; + std::vector error_list_sts_service; if (!ParseJsonObjectField(sts_service, "token_exchange_service_uri", &sts_config_.token_exchange_service_uri, &error_list_sts_service, false)) { @@ -89,14 +89,14 @@ GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectStsService( return error_list_sts_service; } -std::vector +std::vector GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectCallCredentials( const Json::Object& call_credentials) { - std::vector error_list_call_credentials; + std::vector error_list_call_credentials; const Json::Object* sts_service = nullptr; if (ParseJsonObjectField(call_credentials, "sts_service", &sts_service, &error_list_call_credentials)) { - std::vector error_list_sts_service = + std::vector error_list_sts_service = ParseJsonObjectStsService(*sts_service); if (!error_list_sts_service.empty()) { error_list_call_credentials.push_back(GRPC_ERROR_CREATE_FROM_VECTOR( @@ -106,10 +106,10 @@ GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectCallCredentials( return error_list_call_credentials; } -std::vector +std::vector GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectGoogleGrpc( const Json::Object& google_grpc) { - std::vector error_list_google_grpc; + std::vector error_list_google_grpc; if (!ParseJsonObjectField(google_grpc, "target_uri", &endpoint_, &error_list_google_grpc, false)) { endpoint_ = "meshca.googleapis.com"; // Default target @@ -124,7 +124,7 @@ GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectGoogleGrpc( const Json::Object* call_credentials = nullptr; if (ExtractJsonType((*call_credentials_array)[0], "call_credentials[0]", &call_credentials, &error_list_google_grpc)) { - std::vector error_list_call_credentials = + std::vector error_list_call_credentials = ParseJsonObjectCallCredentials(*call_credentials); if (!error_list_call_credentials.empty()) { error_list_google_grpc.push_back(GRPC_ERROR_CREATE_FROM_VECTOR( @@ -137,14 +137,14 @@ GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectGoogleGrpc( return error_list_google_grpc; } -std::vector +std::vector GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectGrpcServices( const Json::Object& grpc_service) { - std::vector error_list_grpc_services; + std::vector error_list_grpc_services; const Json::Object* google_grpc = nullptr; if (ParseJsonObjectField(grpc_service, "google_grpc", &google_grpc, &error_list_grpc_services)) { - std::vector error_list_google_grpc = + std::vector error_list_google_grpc = ParseJsonObjectGoogleGrpc(*google_grpc); if (!error_list_google_grpc.empty()) { error_list_grpc_services.push_back(GRPC_ERROR_CREATE_FROM_VECTOR( @@ -158,10 +158,10 @@ GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectGrpcServices( return error_list_grpc_services; } -std::vector +std::vector GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectServer( const Json::Object& server) { - std::vector error_list_server; + std::vector error_list_server; std::string api_type; if (ParseJsonObjectField(server, "api_type", &api_type, &error_list_server, false)) { @@ -180,7 +180,7 @@ GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectServer( const Json::Object* grpc_service = nullptr; if (ExtractJsonType((*grpc_services)[0], "grpc_services[0]", &grpc_service, &error_list_server)) { - std::vector error_list_grpc_services = + std::vector error_list_grpc_services = ParseJsonObjectGrpcServices(*grpc_service); if (!error_list_grpc_services.empty()) { error_list_server.push_back(GRPC_ERROR_CREATE_FROM_VECTOR( @@ -193,8 +193,8 @@ GoogleMeshCaCertificateProviderFactory::Config::ParseJsonObjectServer( } RefCountedPtr -GoogleMeshCaCertificateProviderFactory::Config::Parse(const Json& config_json, - grpc_error** error) { +GoogleMeshCaCertificateProviderFactory::Config::Parse( + const Json& config_json, grpc_error_handle* error) { auto config = MakeRefCounted(); if (config_json.type() != Json::Type::OBJECT) { @@ -202,11 +202,11 @@ GoogleMeshCaCertificateProviderFactory::Config::Parse(const Json& config_json, "error:config type should be OBJECT."); return nullptr; } - std::vector error_list; + std::vector error_list; const Json::Object* server = nullptr; if (ParseJsonObjectField(config_json.object_value(), "server", &server, &error_list)) { - std::vector error_list_server = + std::vector error_list_server = config->ParseJsonObjectServer(*server); if (!error_list_server.empty()) { error_list.push_back( @@ -257,7 +257,7 @@ const char* GoogleMeshCaCertificateProviderFactory::name() const { RefCountedPtr GoogleMeshCaCertificateProviderFactory::CreateCertificateProviderConfig( - const Json& config_json, grpc_error** error) { + const Json& config_json, grpc_error_handle* error) { return GoogleMeshCaCertificateProviderFactory::Config::Parse(config_json, error); } diff --git a/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h b/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h index 31bf4275767..7a33f977a4a 100644 --- a/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h +++ b/src/core/ext/xds/google_mesh_ca_certificate_provider_factory.h @@ -63,19 +63,20 @@ class GoogleMeshCaCertificateProviderFactory const std::string& location() const { return location_; } static RefCountedPtr Parse(const Json& config_json, - grpc_error** error); + grpc_error_handle* error); private: // Helpers for parsing the config - std::vector ParseJsonObjectStsService( + std::vector ParseJsonObjectStsService( const Json::Object& sts_service); - std::vector ParseJsonObjectCallCredentials( + std::vector ParseJsonObjectCallCredentials( const Json::Object& call_credentials); - std::vector ParseJsonObjectGoogleGrpc( + std::vector ParseJsonObjectGoogleGrpc( const Json::Object& google_grpc); - std::vector ParseJsonObjectGrpcServices( + std::vector ParseJsonObjectGrpcServices( const Json::Object& grpc_service); - std::vector ParseJsonObjectServer(const Json::Object& server); + std::vector ParseJsonObjectServer( + const Json::Object& server); std::string endpoint_; StsConfig sts_config_; @@ -90,7 +91,7 @@ class GoogleMeshCaCertificateProviderFactory RefCountedPtr CreateCertificateProviderConfig(const Json& config_json, - grpc_error** error) override; + grpc_error_handle* error) override; RefCountedPtr CreateCertificateProvider( RefCountedPtr /*config*/) override { diff --git a/src/core/ext/xds/xds_api.cc b/src/core/ext/xds/xds_api.cc index 7aaed85ea77..e51bc07cbb1 100644 --- a/src/core/ext/xds/xds_api.cc +++ b/src/core/ext/xds/xds_api.cc @@ -28,11 +28,13 @@ #include "absl/strings/str_format.h" #include "absl/strings/str_join.h" #include "absl/strings/str_split.h" +#include "envoy/admin/v3/config_dump.upb.h" #include "envoy/config/cluster/v3/circuit_breaker.upb.h" #include "envoy/config/cluster/v3/cluster.upb.h" #include "envoy/config/cluster/v3/cluster.upbdefs.h" #include "envoy/config/core/v3/address.upb.h" #include "envoy/config/core/v3/base.upb.h" +#include "envoy/config/core/v3/base.upbdefs.h" #include "envoy/config/core/v3/config_source.upb.h" #include "envoy/config/core/v3/health_check.upb.h" #include "envoy/config/core/v3/protocol.upb.h" @@ -47,11 +49,14 @@ #include "envoy/config/route/v3/route.upb.h" #include "envoy/config/route/v3/route.upbdefs.h" #include "envoy/config/route/v3/route_components.upb.h" +#include "envoy/config/route/v3/route_components.upbdefs.h" #include "envoy/extensions/clusters/aggregate/v3/cluster.upb.h" +#include "envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h" #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h" #include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h" #include "envoy/extensions/transport_sockets/tls/v3/common.upb.h" #include "envoy/extensions/transport_sockets/tls/v3/tls.upb.h" +#include "envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.h" #include "envoy/service/cluster/v3/cds.upb.h" #include "envoy/service/cluster/v3/cds.upbdefs.h" #include "envoy/service/discovery/v3/discovery.upb.h" @@ -63,6 +68,8 @@ #include "envoy/service/load_stats/v3/lrs.upbdefs.h" #include "envoy/service/route/v3/rds.upb.h" #include "envoy/service/route/v3/rds.upbdefs.h" +#include "envoy/service/status/v3/csds.upb.h" +#include "envoy/service/status/v3/csds.upbdefs.h" #include "envoy/type/matcher/v3/regex.upb.h" #include "envoy/type/matcher/v3/string.upb.h" #include "envoy/type/v3/percent.upb.h" @@ -70,6 +77,7 @@ #include "google/protobuf/any.upb.h" #include "google/protobuf/duration.upb.h" #include "google/protobuf/struct.upb.h" +#include "google/protobuf/timestamp.upb.h" #include "google/protobuf/wrappers.upb.h" #include "google/rpc/status.upb.h" #include "udpa/type/v1/typed_struct.upb.h" @@ -82,27 +90,18 @@ #include #include "src/core/ext/xds/xds_api.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/slice/slice_utils.h" namespace grpc_core { -// TODO(donnadionne): Check to see if timeout is enabled, this will be -// removed once timeout feature is fully integration-tested and enabled by -// default. -bool XdsTimeoutEnabled() { - char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT"); - bool parsed_value; - bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); - gpr_free(value); - return parse_succeeded && parsed_value; -} - // TODO(donnadionne): Check to see if cluster types aggregate_cluster and // logical_dns are enabled, this will be // removed once the cluster types are fully integration-tested and enabled by @@ -138,14 +137,81 @@ bool XdsSecurityEnabled() { return parse_succeeded && parsed_value; } -// TODO(lidiz): This will be removed once the fault injection feature is -// fully integration-tested and enabled by default. -bool XdsFaultInjectionEnabled() { - char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); - bool parsed_value; - bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); - gpr_free(value); - return parse_succeeded && parsed_value; +// +// XdsApi::Route::HashPolicy +// + +XdsApi::Route::HashPolicy::HashPolicy(const HashPolicy& other) + : type(other.type), + header_name(other.header_name), + regex_substitution(other.regex_substitution) { + if (other.regex != nullptr) { + regex = + absl::make_unique(other.regex->pattern(), other.regex->options()); + } +} + +XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=( + const HashPolicy& other) { + type = other.type; + header_name = other.header_name; + if (other.regex != nullptr) { + regex = + absl::make_unique(other.regex->pattern(), other.regex->options()); + } + regex_substitution = other.regex_substitution; + return *this; +} + +XdsApi::Route::HashPolicy::HashPolicy(HashPolicy&& other) noexcept + : type(other.type), + header_name(std::move(other.header_name)), + regex(std::move(other.regex)), + regex_substitution(std::move(other.regex_substitution)) {} + +XdsApi::Route::HashPolicy& XdsApi::Route::HashPolicy::operator=( + HashPolicy&& other) noexcept { + type = other.type; + header_name = std::move(other.header_name); + regex = std::move(other.regex); + regex_substitution = std::move(other.regex_substitution); + return *this; +} + +bool XdsApi::Route::HashPolicy::HashPolicy::operator==( + const HashPolicy& other) const { + if (type != other.type) return false; + if (type == Type::HEADER) { + if (regex == nullptr) { + if (other.regex != nullptr) return false; + } else { + if (other.regex == nullptr) return false; + return header_name == other.header_name && + regex->pattern() == other.regex->pattern() && + regex_substitution == other.regex_substitution; + } + } + return true; +} + +std::string XdsApi::Route::HashPolicy::ToString() const { + std::vector contents; + switch (type) { + case Type::HEADER: + contents.push_back("type=HEADER"); + break; + case Type::CHANNEL_ID: + contents.push_back("type=CHANNEL_ID"); + break; + } + contents.push_back( + absl::StrFormat("terminal=%s", terminal ? "true" : "false")); + if (type == Type::HEADER) { + contents.push_back(absl::StrFormat( + "Header %s:/%s/%s", header_name, + (regex == nullptr) ? "" : regex->pattern(), regex_substitution)); + } + return absl::StrCat("{", absl::StrJoin(contents, ", "), "}"); } // @@ -186,6 +252,9 @@ std::string XdsApi::Route::ClusterWeight::ToString() const { std::string XdsApi::Route::ToString() const { std::vector contents; contents.push_back(matchers.ToString()); + for (const HashPolicy& hash_policy : hash_policies) { + contents.push_back(absl::StrCat("hash_policy=", hash_policy.ToString())); + } if (!cluster_name.empty()) { contents.push_back(absl::StrFormat("Cluster name: %s", cluster_name)); } @@ -439,29 +508,85 @@ bool XdsApi::DownstreamTlsContext::Empty() const { return common_tls_context.Empty(); } +// +// XdsApi::LdsUpdate::HttpConnectionManager +// + +std::string XdsApi::LdsUpdate::HttpConnectionManager::ToString() const { + absl::InlinedVector contents; + contents.push_back(absl::StrFormat( + "route_config_name=%s", + !route_config_name.empty() ? route_config_name.c_str() : "")); + contents.push_back(absl::StrFormat("http_max_stream_duration=%s", + http_max_stream_duration.ToString())); + if (rds_update.has_value()) { + contents.push_back( + absl::StrFormat("rds_update=%s", rds_update->ToString())); + } + if (!http_filters.empty()) { + std::vector filter_strings; + for (const auto& http_filter : http_filters) { + filter_strings.push_back(http_filter.ToString()); + } + contents.push_back(absl::StrCat("http_filters=[", + absl::StrJoin(filter_strings, ", "), "]")); + } + return absl::StrCat("{", absl::StrJoin(contents, ", "), "}"); +} + // // XdsApi::LdsUpdate::HttpFilter // -std::string XdsApi::LdsUpdate::HttpFilter::ToString() const { +std::string XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter::ToString() + const { return absl::StrCat("{name=", name, ", config=", config.ToString(), "}"); } // -// XdsApi::LdsUpdate::FilterChain::FilterChainMatch::CidrRange +// XdsApi::LdsUpdate::FilterChainData // -std::string -XdsApi::LdsUpdate::FilterChain::FilterChainMatch::CidrRange::ToString() const { - return absl::StrCat("{address_prefix=", address_prefix, - " prefix_len=", prefix_len, "}"); +std::string XdsApi::LdsUpdate::FilterChainData::ToString() const { + return absl::StrCat( + "{downstream_tls_context=", downstream_tls_context.ToString(), + " http_connection_manager=", http_connection_manager.ToString(), "}"); +} + +// +// XdsApi::LdsUpdate::FilterChainMap::CidrRange +// + +std::string XdsApi::LdsUpdate::FilterChainMap::CidrRange::ToString() const { + return absl::StrCat( + "{address_prefix=", grpc_sockaddr_to_string(&address, false), + ", prefix_len=", prefix_len, "}"); } // -// XdsApi::LdsUpdate::FilterChain::FilterChainMatch +// FilterChain // -std::string XdsApi::LdsUpdate::FilterChain::FilterChainMatch::ToString() const { +struct FilterChain { + struct FilterChainMatch { + uint32_t destination_port = 0; + std::vector prefix_ranges; + XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType source_type = + XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::kAny; + std::vector + source_prefix_ranges; + std::vector source_ports; + std::vector server_names; + std::string transport_protocol; + std::vector application_protocols; + + std::string ToString() const; + } filter_chain_match; + + std::shared_ptr filter_chain_data; +}; + +std::string FilterChain::FilterChainMatch::ToString() const { absl::InlinedVector contents; if (destination_port != 0) { contents.push_back(absl::StrCat("destination_port=", destination_port)); @@ -474,10 +599,10 @@ std::string XdsApi::LdsUpdate::FilterChain::FilterChainMatch::ToString() const { contents.push_back(absl::StrCat( "prefix_ranges={", absl::StrJoin(prefix_ranges_content, ", "), "}")); } - if (source_type == XdsApi::LdsUpdate::FilterChain::FilterChainMatch:: - ConnectionSourceType::kSameIpOrLoopback) { + if (source_type == XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType:: + kSameIpOrLoopback) { contents.push_back("source_type=SAME_IP_OR_LOOPBACK"); - } else if (source_type == XdsApi::LdsUpdate::FilterChain::FilterChainMatch:: + } else if (source_type == XdsApi::LdsUpdate::FilterChainMap:: ConnectionSourceType::kExternal) { contents.push_back("source_type=EXTERNAL"); } @@ -510,13 +635,40 @@ std::string XdsApi::LdsUpdate::FilterChain::FilterChainMatch::ToString() const { } // -// XdsApi::LdsUpdate::FilterChain +// XdsApi::LdsUpdate::FilterChainMap // -std::string XdsApi::LdsUpdate::FilterChain::ToString() const { - return absl::StrFormat("{filter_chain_match=%s, downstream_tls_context=%s}", - filter_chain_match.ToString(), - downstream_tls_context.ToString()); +std::string XdsApi::LdsUpdate::FilterChainMap::ToString() const { + std::vector contents; + for (const auto& destination_ip : destination_ip_vector) { + for (int source_type = 0; source_type < 3; ++source_type) { + for (const auto& source_ip : + destination_ip.source_types_array[source_type]) { + for (const auto& source_port_pair : source_ip.ports_map) { + FilterChain::FilterChainMatch filter_chain_match; + if (destination_ip.prefix_range.has_value()) { + filter_chain_match.prefix_ranges.push_back( + *destination_ip.prefix_range); + } + filter_chain_match.source_type = static_cast< + XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType>( + source_type); + if (source_ip.prefix_range.has_value()) { + filter_chain_match.source_prefix_ranges.push_back( + *source_ip.prefix_range); + } + if (source_port_pair.first != 0) { + filter_chain_match.source_ports.push_back(source_port_pair.first); + } + contents.push_back(absl::StrCat( + "{filter_chain_match=", filter_chain_match.ToString(), + ", filter_chain=", source_port_pair.second.data->ToString(), + "}")); + } + } + } + } + return absl::StrCat("{", absl::StrJoin(contents, ", "), "}"); } // @@ -524,36 +676,18 @@ std::string XdsApi::LdsUpdate::FilterChain::ToString() const { // std::string XdsApi::LdsUpdate::ToString() const { - absl::InlinedVector contents; + absl::InlinedVector contents; if (type == ListenerType::kTcpListener) { - std::vector filter_chains_content; - for (const auto& filter_chain : filter_chains) { - filter_chains_content.push_back(filter_chain.ToString()); - } - contents.push_back(absl::StrCat( - "filter_chains={", absl::StrJoin(filter_chains_content, ", "), "}")); + contents.push_back(absl::StrCat("address=", address)); + contents.push_back( + absl::StrCat("filter_chain_map=", filter_chain_map.ToString())); if (default_filter_chain.has_value()) { contents.push_back(absl::StrCat("default_filter_chain=", default_filter_chain->ToString())); } } else if (type == ListenerType::kHttpApiListener) { - contents.push_back(absl::StrFormat( - "route_config_name=%s", - !route_config_name.empty() ? route_config_name.c_str() : "")); - contents.push_back(absl::StrFormat("http_max_stream_duration=%s", - http_max_stream_duration.ToString())); - if (rds_update.has_value()) { - contents.push_back( - absl::StrFormat("rds_update=%s", rds_update->ToString())); - } - } - if (!http_filters.empty()) { - std::vector filter_strings; - for (const auto& http_filter : http_filters) { - filter_strings.push_back(http_filter.ToString()); - } - contents.push_back(absl::StrCat("http_filters=[", - absl::StrJoin(filter_strings, ", "), "]")); + contents.push_back(absl::StrFormat("http_connection_manager=%s", + http_connection_manager.ToString())); } return absl::StrCat("{", absl::StrJoin(contents, ", "), "}"); } @@ -673,8 +807,13 @@ const char* kCdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.Cluster"; const char* kEdsV2TypeUrl = "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment"; -bool IsLds(absl::string_view type_url) { - return type_url == XdsApi::kLdsTypeUrl || type_url == kLdsV2TypeUrl; +bool IsLds(absl::string_view type_url, bool* is_v2 = nullptr) { + if (type_url == XdsApi::kLdsTypeUrl) return true; + if (type_url == kLdsV2TypeUrl) { + if (is_v2 != nullptr) *is_v2 = true; + return true; + } + return false; } bool IsRds(absl::string_view type_url) { @@ -706,7 +845,11 @@ XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer, envoy_config_listener_v3_Listener_getmsgdef(symtab_.ptr()); envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab_.ptr()); envoy_config_cluster_v3_Cluster_getmsgdef(symtab_.ptr()); + envoy_extensions_clusters_aggregate_v3_ClusterConfig_getmsgdef(symtab_.ptr()); + envoy_config_cluster_v3_Cluster_getmsgdef(symtab_.ptr()); envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab_.ptr()); + envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_getmsgdef( + symtab_.ptr()); envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef( symtab_.ptr()); // Load HTTP filter proto messages into the upb symtab. @@ -925,8 +1068,8 @@ absl::string_view TypeUrlExternalToInternal(bool use_v3, grpc_slice XdsApi::CreateAdsRequest( const XdsBootstrap::XdsServer& server, const std::string& type_url, const std::set& resource_names, - const std::string& version, const std::string& nonce, grpc_error* error, - bool populate_node) { + const std::string& version, const std::string& nonce, + grpc_error_handle error, bool populate_node) { upb::Arena arena; const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(), server.ShouldUseV3()}; @@ -949,6 +1092,7 @@ grpc_slice XdsApi::CreateAdsRequest( request, StdStringToUpbString(nonce)); } // Set error_detail if it's a NACK. + std::string error_string_storage; if (error != GRPC_ERROR_NONE) { google_rpc_Status* error_detail = envoy_service_discovery_v3_DiscoveryRequest_mutable_error_detail( @@ -959,8 +1103,8 @@ grpc_slice XdsApi::CreateAdsRequest( // generate them in the parsing code, and then use that here. google_rpc_Status_set_code(error_detail, GRPC_STATUS_INVALID_ARGUMENT); // Error description comes from the error that was passed in. - upb_strview error_description = - StdStringToUpbString(absl::string_view(grpc_error_string(error))); + error_string_storage = grpc_error_std_string(error); + upb_strview error_description = StdStringToUpbString(error_string_storage); google_rpc_Status_set_message(error_detail, error_description); GRPC_ERROR_UNREF(error); } @@ -1054,8 +1198,9 @@ void MaybeLogClusterLoadAssignment( } } -grpc_error* RoutePathMatchParse(const envoy_config_route_v3_RouteMatch* match, - XdsApi::Route* route, bool* ignore_route) { +grpc_error_handle RoutePathMatchParse( + const envoy_config_route_v3_RouteMatch* match, XdsApi::Route* route, + bool* ignore_route) { auto* case_sensitive_ptr = envoy_config_route_v3_RouteMatch_case_sensitive(match); bool case_sensitive = true; @@ -1088,7 +1233,7 @@ grpc_error* RoutePathMatchParse(const envoy_config_route_v3_RouteMatch* match, return GRPC_ERROR_NONE; } } - type = StringMatcher::Type::PREFIX; + type = StringMatcher::Type::kPrefix; match_string = std::string(prefix); } else if (envoy_config_route_v3_RouteMatch_has_path(match)) { absl::string_view path = @@ -1122,13 +1267,13 @@ grpc_error* RoutePathMatchParse(const envoy_config_route_v3_RouteMatch* match, *ignore_route = true; return GRPC_ERROR_NONE; } - type = StringMatcher::Type::EXACT; + type = StringMatcher::Type::kExact; match_string = std::string(path); } else if (envoy_config_route_v3_RouteMatch_has_safe_regex(match)) { const envoy_type_matcher_v3_RegexMatcher* regex_matcher = envoy_config_route_v3_RouteMatch_safe_regex(match); GPR_ASSERT(regex_matcher != nullptr); - type = StringMatcher::Type::SAFE_REGEX; + type = StringMatcher::Type::kSafeRegex; match_string = UpbStringToStdString( envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); } else { @@ -1147,7 +1292,7 @@ grpc_error* RoutePathMatchParse(const envoy_config_route_v3_RouteMatch* match, return GRPC_ERROR_NONE; } -grpc_error* RouteHeaderMatchersParse( +grpc_error_handle RouteHeaderMatchersParse( const envoy_config_route_v3_RouteMatch* match, XdsApi::Route* route) { size_t size; const envoy_config_route_v3_HeaderMatcher* const* headers = @@ -1162,7 +1307,7 @@ grpc_error* RouteHeaderMatchersParse( int64_t range_end = 0; bool present_match = false; if (envoy_config_route_v3_HeaderMatcher_has_exact_match(header)) { - type = HeaderMatcher::Type::EXACT; + type = HeaderMatcher::Type::kExact; match_string = UpbStringToStdString( envoy_config_route_v3_HeaderMatcher_exact_match(header)); } else if (envoy_config_route_v3_HeaderMatcher_has_safe_regex_match( @@ -1170,28 +1315,28 @@ grpc_error* RouteHeaderMatchersParse( const envoy_type_matcher_v3_RegexMatcher* regex_matcher = envoy_config_route_v3_HeaderMatcher_safe_regex_match(header); GPR_ASSERT(regex_matcher != nullptr); - type = HeaderMatcher::Type::SAFE_REGEX; + type = HeaderMatcher::Type::kSafeRegex; match_string = UpbStringToStdString( envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); } else if (envoy_config_route_v3_HeaderMatcher_has_range_match(header)) { - type = HeaderMatcher::Type::RANGE; + type = HeaderMatcher::Type::kRange; const envoy_type_v3_Int64Range* range_matcher = envoy_config_route_v3_HeaderMatcher_range_match(header); range_start = envoy_type_v3_Int64Range_start(range_matcher); range_end = envoy_type_v3_Int64Range_end(range_matcher); } else if (envoy_config_route_v3_HeaderMatcher_has_present_match(header)) { - type = HeaderMatcher::Type::PRESENT; + type = HeaderMatcher::Type::kPresent; present_match = envoy_config_route_v3_HeaderMatcher_present_match(header); } else if (envoy_config_route_v3_HeaderMatcher_has_prefix_match(header)) { - type = HeaderMatcher::Type::PREFIX; + type = HeaderMatcher::Type::kPrefix; match_string = UpbStringToStdString( envoy_config_route_v3_HeaderMatcher_prefix_match(header)); } else if (envoy_config_route_v3_HeaderMatcher_has_suffix_match(header)) { - type = HeaderMatcher::Type::SUFFIX; + type = HeaderMatcher::Type::kSuffix; match_string = UpbStringToStdString( envoy_config_route_v3_HeaderMatcher_suffix_match(header)); } else if (envoy_config_route_v3_HeaderMatcher_has_contains_match(header)) { - type = HeaderMatcher::Type::CONTAINS; + type = HeaderMatcher::Type::kContains; match_string = UpbStringToStdString( envoy_config_route_v3_HeaderMatcher_contains_match(header)); } else { @@ -1214,7 +1359,7 @@ grpc_error* RouteHeaderMatchersParse( return GRPC_ERROR_NONE; } -grpc_error* RouteRuntimeFractionParse( +grpc_error_handle RouteRuntimeFractionParse( const envoy_config_route_v3_RouteMatch* match, XdsApi::Route* route) { const envoy_config_core_v3_RuntimeFractionalPercent* runtime_fraction = envoy_config_route_v3_RouteMatch_runtime_fraction(match); @@ -1247,9 +1392,9 @@ grpc_error* RouteRuntimeFractionParse( return GRPC_ERROR_NONE; } -grpc_error* ExtractHttpFilterTypeName(const EncodingContext& context, - const google_protobuf_Any* any, - absl::string_view* filter_type) { +grpc_error_handle ExtractHttpFilterTypeName(const EncodingContext& context, + const google_protobuf_Any* any, + absl::string_view* filter_type) { *filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any)); if (*filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") { upb_strview any_value = google_protobuf_Any_value(any); @@ -1267,7 +1412,7 @@ grpc_error* ExtractHttpFilterTypeName(const EncodingContext& context, } template -grpc_error* ParseTypedPerFilterConfig( +grpc_error_handle ParseTypedPerFilterConfig( const EncodingContext& context, const ParentType* parent, const EntryType* (*entry_func)(const ParentType*, size_t*), upb_strview (*key_func)(const EntryType*), @@ -1282,9 +1427,15 @@ grpc_error* ParseTypedPerFilterConfig( return GRPC_ERROR_CREATE_FROM_STATIC_STRING("empty filter name in map"); } const google_protobuf_Any* any = value_func(filter_entry); - bool is_optional = false; + GPR_ASSERT(any != nullptr); absl::string_view filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any)); + if (filter_type.empty()) { + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("no filter config specified for filter name ", key) + .c_str()); + } + bool is_optional = false; if (filter_type == "type.googleapis.com/envoy.config.route.v3.FilterConfig") { upb_strview any_value = google_protobuf_Any_value(any); @@ -1298,8 +1449,15 @@ grpc_error* ParseTypedPerFilterConfig( is_optional = envoy_config_route_v3_FilterConfig_is_optional(filter_config); any = envoy_config_route_v3_FilterConfig_config(filter_config); + if (any == nullptr) { + if (is_optional) continue; + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("no filter config specified for filter name ", key) + .c_str()); + } } - grpc_error* error = ExtractHttpFilterTypeName(context, any, &filter_type); + grpc_error_handle error = + ExtractHttpFilterTypeName(context, any, &filter_type); if (error != GRPC_ERROR_NONE) return error; const XdsHttpFilterImpl* filter_impl = XdsHttpFilterRegistry::GetFilterForType(filter_type); @@ -1323,9 +1481,9 @@ grpc_error* ParseTypedPerFilterConfig( return GRPC_ERROR_NONE; } -grpc_error* RouteActionParse(const EncodingContext& context, - const envoy_config_route_v3_Route* route_msg, - XdsApi::Route* route, bool* ignore_route) { +grpc_error_handle RouteActionParse(const EncodingContext& context, + const envoy_config_route_v3_Route* route_msg, + XdsApi::Route* route, bool* ignore_route) { if (!envoy_config_route_v3_Route_has_route(route_msg)) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "No RouteAction found in route."); @@ -1377,9 +1535,8 @@ grpc_error* RouteActionParse(const EncodingContext& context, cluster.weight = google_protobuf_UInt32Value_value(weight); if (cluster.weight == 0) continue; sum_of_weights += cluster.weight; - if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) && - context.use_v3) { - grpc_error* error = ParseTypedPerFilterConfig< + if (context.use_v3) { + grpc_error_handle error = ParseTypedPerFilterConfig< envoy_config_route_v3_WeightedCluster_ClusterWeight, envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry>( context, cluster_weight, @@ -1403,7 +1560,7 @@ grpc_error* RouteActionParse(const EncodingContext& context, // No cluster or weighted_clusters found in RouteAction, ignore this route. *ignore_route = true; } - if (XdsTimeoutEnabled() && !*ignore_route) { + if (!*ignore_route) { const envoy_config_route_v3_RouteAction_MaxStreamDuration* max_stream_duration = envoy_config_route_v3_RouteAction_max_stream_duration(route_action); @@ -1424,10 +1581,92 @@ grpc_error* RouteActionParse(const EncodingContext& context, } } } + // Get HashPolicy from RouteAction + if (XdsRingHashEnabled()) { + size_t size = 0; + const envoy_config_route_v3_RouteAction_HashPolicy* const* hash_policies = + envoy_config_route_v3_RouteAction_hash_policy(route_action, &size); + for (size_t i = 0; i < size; ++i) { + const envoy_config_route_v3_RouteAction_HashPolicy* hash_policy = + hash_policies[i]; + XdsApi::Route::HashPolicy policy; + policy.terminal = + envoy_config_route_v3_RouteAction_HashPolicy_terminal(hash_policy); + const envoy_config_route_v3_RouteAction_HashPolicy_Header* header; + const envoy_config_route_v3_RouteAction_HashPolicy_FilterState* + filter_state; + if ((header = envoy_config_route_v3_RouteAction_HashPolicy_header( + hash_policy)) != nullptr) { + policy.type = XdsApi::Route::HashPolicy::Type::HEADER; + policy.header_name = UpbStringToStdString( + envoy_config_route_v3_RouteAction_HashPolicy_Header_header_name( + header)); + const struct envoy_type_matcher_v3_RegexMatchAndSubstitute* + regex_rewrite = + envoy_config_route_v3_RouteAction_HashPolicy_Header_regex_rewrite( + header); + if (regex_rewrite == nullptr) { + gpr_log( + GPR_DEBUG, + "RouteAction HashPolicy contains policy specifier Header with " + "RegexMatchAndSubstitution but Regex is missing"); + continue; + } + const envoy_type_matcher_v3_RegexMatcher* regex_matcher = + envoy_type_matcher_v3_RegexMatchAndSubstitute_pattern( + regex_rewrite); + if (regex_matcher == nullptr) { + gpr_log( + GPR_DEBUG, + "RouteAction HashPolicy contains policy specifier Header with " + "RegexMatchAndSubstitution but RegexMatcher pattern is " + "missing"); + continue; + } + RE2::Options options; + policy.regex = absl::make_unique( + UpbStringToStdString( + envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)), + options); + if (!policy.regex->ok()) { + gpr_log( + GPR_DEBUG, + "RouteAction HashPolicy contains policy specifier Header with " + "RegexMatchAndSubstitution but RegexMatcher pattern does not " + "compile"); + continue; + } + policy.regex_substitution = UpbStringToStdString( + envoy_type_matcher_v3_RegexMatchAndSubstitute_substitution( + regex_rewrite)); + } else if ((filter_state = + envoy_config_route_v3_RouteAction_HashPolicy_filter_state( + hash_policy)) != nullptr) { + std::string key = UpbStringToStdString( + envoy_config_route_v3_RouteAction_HashPolicy_FilterState_key( + filter_state)); + if (key == "io.grpc.channel_id") { + policy.type = XdsApi::Route::HashPolicy::Type::CHANNEL_ID; + } else { + gpr_log(GPR_DEBUG, + "RouteAction HashPolicy contains policy specifier " + "FilterState but " + "key is not io.grpc.channel_id."); + continue; + } + } else { + gpr_log( + GPR_DEBUG, + "RouteAction HashPolicy contains unsupported policy specifier."); + continue; + } + route->hash_policies.emplace_back(std::move(policy)); + } + } return GRPC_ERROR_NONE; } -grpc_error* RouteConfigParse( +grpc_error_handle RouteConfigParse( const EncodingContext& context, const envoy_config_route_v3_RouteConfiguration* route_config, XdsApi::RdsUpdate* rds_update) { @@ -1458,9 +1697,8 @@ grpc_error* RouteConfigParse( return GRPC_ERROR_CREATE_FROM_STATIC_STRING("VirtualHost has no domains"); } // Parse typed_per_filter_config. - if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) && - context.use_v3) { - grpc_error* error = ParseTypedPerFilterConfig< + if (context.use_v3) { + grpc_error_handle error = ParseTypedPerFilterConfig< envoy_config_route_v3_VirtualHost, envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry>( context, virtual_hosts[i], @@ -1482,6 +1720,9 @@ grpc_error* RouteConfigParse( for (size_t j = 0; j < num_routes; ++j) { const envoy_config_route_v3_RouteMatch* match = envoy_config_route_v3_Route_match(routes[j]); + if (match == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Match can't be null."); + } size_t query_parameters_size; static_cast(envoy_config_route_v3_RouteMatch_query_parameters( match, &query_parameters_size)); @@ -1490,7 +1731,8 @@ grpc_error* RouteConfigParse( } XdsApi::Route route; bool ignore_route = false; - grpc_error* error = RoutePathMatchParse(match, &route, &ignore_route); + grpc_error_handle error = + RoutePathMatchParse(match, &route, &ignore_route); if (error != GRPC_ERROR_NONE) return error; if (ignore_route) continue; error = RouteHeaderMatchersParse(match, &route); @@ -1500,9 +1742,8 @@ grpc_error* RouteConfigParse( error = RouteActionParse(context, routes[j], &route, &ignore_route); if (error != GRPC_ERROR_NONE) return error; if (ignore_route) continue; - if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) && - context.use_v3) { - grpc_error* error = ParseTypedPerFilterConfig< + if (context.use_v3) { + grpc_error_handle error = ParseTypedPerFilterConfig< envoy_config_route_v3_Route, envoy_config_route_v3_Route_TypedPerFilterConfigEntry>( context, routes[j], @@ -1534,11 +1775,11 @@ CertificateProviderInstanceParse( certificate_provider_instance_proto))}; } -grpc_error* CommonTlsContextParse( +grpc_error_handle CommonTlsContextParse( const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext* common_tls_context_proto, XdsApi::CommonTlsContext* common_tls_context) GRPC_MUST_USE_RESULT; -grpc_error* CommonTlsContextParse( +grpc_error_handle CommonTlsContextParse( const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext* common_tls_context_proto, XdsApi::CommonTlsContext* common_tls_context) { @@ -1559,31 +1800,31 @@ grpc_error* CommonTlsContextParse( std::string matcher; if (envoy_type_matcher_v3_StringMatcher_has_exact( subject_alt_names_matchers[i])) { - type = StringMatcher::Type::EXACT; + type = StringMatcher::Type::kExact; matcher = UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_exact( subject_alt_names_matchers[i])); } else if (envoy_type_matcher_v3_StringMatcher_has_prefix( subject_alt_names_matchers[i])) { - type = StringMatcher::Type::PREFIX; + type = StringMatcher::Type::kPrefix; matcher = UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_prefix( subject_alt_names_matchers[i])); } else if (envoy_type_matcher_v3_StringMatcher_has_suffix( subject_alt_names_matchers[i])) { - type = StringMatcher::Type::SUFFIX; + type = StringMatcher::Type::kSuffix; matcher = UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_suffix( subject_alt_names_matchers[i])); } else if (envoy_type_matcher_v3_StringMatcher_has_contains( subject_alt_names_matchers[i])) { - type = StringMatcher::Type::CONTAINS; + type = StringMatcher::Type::kContains; matcher = UpbStringToStdString(envoy_type_matcher_v3_StringMatcher_contains( subject_alt_names_matchers[i])); } else if (envoy_type_matcher_v3_StringMatcher_has_safe_regex( subject_alt_names_matchers[i])) { - type = StringMatcher::Type::SAFE_REGEX; + type = StringMatcher::Type::kSafeRegex; auto* regex_matcher = envoy_type_matcher_v3_StringMatcher_safe_regex( subject_alt_names_matchers[i]); matcher = UpbStringToStdString( @@ -1603,7 +1844,7 @@ grpc_error* CommonTlsContextParse( string_matcher.status().message()) .c_str()); } - if (type == StringMatcher::Type::SAFE_REGEX && ignore_case) { + if (type == StringMatcher::Type::kSafeRegex && ignore_case) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "StringMatcher: ignore_case has no effect for SAFE_REGEX."); } @@ -1633,43 +1874,33 @@ grpc_error* CommonTlsContextParse( return GRPC_ERROR_NONE; } -grpc_error* LdsResponseParseClient( - const EncodingContext& context, - const envoy_config_listener_v3_ApiListener* api_listener, - XdsApi::LdsUpdate* lds_update) { - lds_update->type = XdsApi::LdsUpdate::ListenerType::kHttpApiListener; - const upb_strview encoded_api_listener = google_protobuf_Any_value( - envoy_config_listener_v3_ApiListener_api_listener(api_listener)); - const auto* http_connection_manager = - envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse( - encoded_api_listener.data, encoded_api_listener.size, context.arena); - if (http_connection_manager == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Could not parse HttpConnectionManager config from ApiListener"); - } - MaybeLogHttpConnectionManager(context, http_connection_manager); - if (XdsTimeoutEnabled()) { - // Obtain max_stream_duration from Http Protocol Options. - const envoy_config_core_v3_HttpProtocolOptions* options = - envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_common_http_protocol_options( - http_connection_manager); - if (options != nullptr) { - const google_protobuf_Duration* duration = - envoy_config_core_v3_HttpProtocolOptions_max_stream_duration(options); - if (duration != nullptr) { - lds_update->http_max_stream_duration.seconds = - google_protobuf_Duration_seconds(duration); - lds_update->http_max_stream_duration.nanos = - google_protobuf_Duration_nanos(duration); - } +grpc_error_handle HttpConnectionManagerParse( + bool is_client, const EncodingContext& context, + const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* + http_connection_manager_proto, + bool is_v2, + XdsApi::LdsUpdate::HttpConnectionManager* http_connection_manager) { + MaybeLogHttpConnectionManager(context, http_connection_manager_proto); + // Obtain max_stream_duration from Http Protocol Options. + const envoy_config_core_v3_HttpProtocolOptions* options = + envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_common_http_protocol_options( + http_connection_manager_proto); + if (options != nullptr) { + const google_protobuf_Duration* duration = + envoy_config_core_v3_HttpProtocolOptions_max_stream_duration(options); + if (duration != nullptr) { + http_connection_manager->http_max_stream_duration.seconds = + google_protobuf_Duration_seconds(duration); + http_connection_manager->http_max_stream_duration.nanos = + google_protobuf_Duration_nanos(duration); } } // Parse filters. - if ((XdsSecurityEnabled() || XdsFaultInjectionEnabled()) && context.use_v3) { + if (!is_v2) { size_t num_filters = 0; const auto* http_filters = envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_http_filters( - http_connection_manager, &num_filters); + http_connection_manager_proto, &num_filters); std::set names_seen; for (size_t i = 0; i < num_filters; ++i) { const auto* http_filter = http_filters[i]; @@ -1685,23 +1916,38 @@ grpc_error* LdsResponseParseClient( absl::StrCat("duplicate HTTP filter name: ", name).c_str()); } names_seen.insert(name); + const bool is_optional = + envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_is_optional( + http_filter); const google_protobuf_Any* any = envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_typed_config( http_filter); + if (any == nullptr) { + if (is_optional) continue; + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("no filter config specified for filter name ", name) + .c_str()); + } absl::string_view filter_type; - grpc_error* error = ExtractHttpFilterTypeName(context, any, &filter_type); + grpc_error_handle error = + ExtractHttpFilterTypeName(context, any, &filter_type); if (error != GRPC_ERROR_NONE) return error; const XdsHttpFilterImpl* filter_impl = XdsHttpFilterRegistry::GetFilterForType(filter_type); if (filter_impl == nullptr) { - if (envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_is_optional( - http_filter)) { - continue; - } + if (is_optional) continue; return GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("no filter registered for config type ", filter_type) .c_str()); } + if ((is_client && !filter_impl->IsSupportedOnClients()) || + (!is_client && !filter_impl->IsSupportedOnServers())) { + if (is_optional) continue; + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrFormat("Filter %s is not supported on %s", filter_type, + is_client ? "clients" : "servers") + .c_str()); + } absl::StatusOr filter_config = filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any), context.arena); @@ -1712,118 +1958,81 @@ grpc_error* LdsResponseParseClient( " failed to parse: ", filter_config.status().ToString()) .c_str()); } - lds_update->http_filters.emplace_back(XdsApi::LdsUpdate::HttpFilter{ - std::string(name), std::move(*filter_config)}); + http_connection_manager->http_filters.emplace_back( + XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{ + std::string(name), std::move(*filter_config)}); } + } else { + // If using a v2 config, we just hard-code a list containing only the + // router filter without actually looking at the config. This ensures + // that the right thing happens in the xds resolver without having + // to expose whether the resource we received was v2 or v3. + http_connection_manager->http_filters.emplace_back( + XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{ + "router", {kXdsHttpRouterFilterConfigName, Json()}}); + } + if (is_client) { + // Found inlined route_config. Parse it to find the cluster_name. + if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config( + http_connection_manager_proto)) { + const envoy_config_route_v3_RouteConfiguration* route_config = + envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_config( + http_connection_manager_proto); + XdsApi::RdsUpdate rds_update; + grpc_error_handle error = + RouteConfigParse(context, route_config, &rds_update); + if (error != GRPC_ERROR_NONE) return error; + http_connection_manager->rds_update = std::move(rds_update); + return GRPC_ERROR_NONE; + } + // Validate that RDS must be used to get the route_config dynamically. + const envoy_extensions_filters_network_http_connection_manager_v3_Rds* rds = + envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_rds( + http_connection_manager_proto); + if (rds == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "HttpConnectionManager neither has inlined route_config nor RDS."); + } + // Check that the ConfigSource specifies ADS. + const envoy_config_core_v3_ConfigSource* config_source = + envoy_extensions_filters_network_http_connection_manager_v3_Rds_config_source( + rds); + if (config_source == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "HttpConnectionManager missing config_source for RDS."); + } + if (!envoy_config_core_v3_ConfigSource_has_ads(config_source)) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "HttpConnectionManager ConfigSource for RDS does not specify ADS."); + } + // Get the route_config_name. + http_connection_manager->route_config_name = UpbStringToStdString( + envoy_extensions_filters_network_http_connection_manager_v3_Rds_route_config_name( + rds)); } - // Found inlined route_config. Parse it to find the cluster_name. - if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_route_config( - http_connection_manager)) { - const envoy_config_route_v3_RouteConfiguration* route_config = - envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_route_config( - http_connection_manager); - XdsApi::RdsUpdate rds_update; - grpc_error* error = RouteConfigParse(context, route_config, &rds_update); - if (error != GRPC_ERROR_NONE) return error; - lds_update->rds_update = std::move(rds_update); - return GRPC_ERROR_NONE; - } - // Validate that RDS must be used to get the route_config dynamically. - const envoy_extensions_filters_network_http_connection_manager_v3_Rds* rds = - envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_rds( - http_connection_manager); - if (rds == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "HttpConnectionManager neither has inlined route_config nor RDS."); - } - // Check that the ConfigSource specifies ADS. - const envoy_config_core_v3_ConfigSource* config_source = - envoy_extensions_filters_network_http_connection_manager_v3_Rds_config_source( - rds); - if (config_source == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "HttpConnectionManager missing config_source for RDS."); - } - if (!envoy_config_core_v3_ConfigSource_has_ads(config_source)) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "HttpConnectionManager ConfigSource for RDS does not specify ADS."); - } - // Get the route_config_name. - lds_update->route_config_name = UpbStringToStdString( - envoy_extensions_filters_network_http_connection_manager_v3_Rds_route_config_name( - rds)); return GRPC_ERROR_NONE; } -XdsApi::LdsUpdate::FilterChain::FilterChainMatch::CidrRange CidrRangeParse( - const envoy_config_core_v3_CidrRange* cidr_range_proto) { - uint32_t prefix_len = 0; - auto* prefix_len_proto = - envoy_config_core_v3_CidrRange_prefix_len(cidr_range_proto); - if (prefix_len_proto != nullptr) { - prefix_len = google_protobuf_UInt32Value_value(prefix_len_proto); - } - return {UpbStringToStdString( - envoy_config_core_v3_CidrRange_address_prefix(cidr_range_proto)), - prefix_len}; -} - -XdsApi::LdsUpdate::FilterChain::FilterChainMatch FilterChainMatchParse( - const envoy_config_listener_v3_FilterChainMatch* filter_chain_match_proto) { - XdsApi::LdsUpdate::FilterChain::FilterChainMatch filter_chain_match; - auto* destination_port = - envoy_config_listener_v3_FilterChainMatch_destination_port( - filter_chain_match_proto); - if (destination_port != nullptr) { - filter_chain_match.destination_port = - google_protobuf_UInt32Value_value(destination_port); - } - size_t size = 0; - auto* prefix_ranges = envoy_config_listener_v3_FilterChainMatch_prefix_ranges( - filter_chain_match_proto, &size); - filter_chain_match.prefix_ranges.reserve(size); - for (size_t i = 0; i < size; i++) { - filter_chain_match.prefix_ranges.push_back( - CidrRangeParse(prefix_ranges[i])); - } - filter_chain_match.source_type = static_cast< - XdsApi::LdsUpdate::FilterChain::FilterChainMatch::ConnectionSourceType>( - envoy_config_listener_v3_FilterChainMatch_source_type( - filter_chain_match_proto)); - auto* source_prefix_ranges = - envoy_config_listener_v3_FilterChainMatch_source_prefix_ranges( - filter_chain_match_proto, &size); - filter_chain_match.source_prefix_ranges.reserve(size); - for (size_t i = 0; i < size; i++) { - filter_chain_match.source_prefix_ranges.push_back( - CidrRangeParse(source_prefix_ranges[i])); - } - auto* source_ports = envoy_config_listener_v3_FilterChainMatch_source_ports( - filter_chain_match_proto, &size); - filter_chain_match.source_ports.reserve(size); - for (size_t i = 0; i < size; i++) { - filter_chain_match.source_ports.push_back(source_ports[i]); - } - auto* server_names = envoy_config_listener_v3_FilterChainMatch_server_names( - filter_chain_match_proto, &size); - for (size_t i = 0; i < size; i++) { - filter_chain_match.server_names.push_back( - UpbStringToStdString(server_names[i])); - } - filter_chain_match.transport_protocol = UpbStringToStdString( - envoy_config_listener_v3_FilterChainMatch_transport_protocol( - filter_chain_match_proto)); - auto* application_protocols = - envoy_config_listener_v3_FilterChainMatch_application_protocols( - filter_chain_match_proto, &size); - for (size_t i = 0; i < size; i++) { - filter_chain_match.application_protocols.push_back( - UpbStringToStdString(application_protocols[i])); +grpc_error_handle LdsResponseParseClient( + const EncodingContext& context, + const envoy_config_listener_v3_ApiListener* api_listener, bool is_v2, + XdsApi::LdsUpdate* lds_update) { + lds_update->type = XdsApi::LdsUpdate::ListenerType::kHttpApiListener; + const upb_strview encoded_api_listener = google_protobuf_Any_value( + envoy_config_listener_v3_ApiListener_api_listener(api_listener)); + const auto* http_connection_manager = + envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse( + encoded_api_listener.data, encoded_api_listener.size, context.arena); + if (http_connection_manager == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Could not parse HttpConnectionManager config from ApiListener"); } - return filter_chain_match; + return HttpConnectionManagerParse(true /* is_client */, context, + http_connection_manager, is_v2, + &lds_update->http_connection_manager); } -grpc_error* DownstreamTlsContextParse( +grpc_error_handle DownstreamTlsContextParse( const EncodingContext& context, const envoy_config_core_v3_TransportSocket* transport_socket, XdsApi::DownstreamTlsContext* downstream_tls_context) { @@ -1847,7 +2056,7 @@ grpc_error* DownstreamTlsContextParse( envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_common_tls_context( downstream_tls_context_proto); if (common_tls_context != nullptr) { - grpc_error* error = CommonTlsContextParse( + grpc_error_handle error = CommonTlsContextParse( common_tls_context, &downstream_tls_context->common_tls_context); if (error != GRPC_ERROR_NONE) return error; } @@ -1870,63 +2079,415 @@ grpc_error* DownstreamTlsContextParse( return GRPC_ERROR_NONE; } -XdsApi::LdsUpdate::FilterChain FilterChainParse( +grpc_error_handle CidrRangeParse( + const envoy_config_core_v3_CidrRange* cidr_range_proto, + XdsApi::LdsUpdate::FilterChainMap::CidrRange* cidr_range) { + std::string address_prefix = UpbStringToStdString( + envoy_config_core_v3_CidrRange_address_prefix(cidr_range_proto)); + grpc_error_handle error = + grpc_string_to_sockaddr(&cidr_range->address, address_prefix.c_str(), 0); + if (error != GRPC_ERROR_NONE) return error; + cidr_range->prefix_len = 0; + auto* prefix_len_proto = + envoy_config_core_v3_CidrRange_prefix_len(cidr_range_proto); + if (prefix_len_proto != nullptr) { + cidr_range->prefix_len = std::min( + google_protobuf_UInt32Value_value(prefix_len_proto), + (reinterpret_cast(cidr_range->address.addr)) + ->sa_family == GRPC_AF_INET + ? uint32_t(32) + : uint32_t(128)); + } + // Normalize the network address by masking it with prefix_len + grpc_sockaddr_mask_bits(&cidr_range->address, cidr_range->prefix_len); + return GRPC_ERROR_NONE; +} + +grpc_error_handle FilterChainMatchParse( + const envoy_config_listener_v3_FilterChainMatch* filter_chain_match_proto, + FilterChain::FilterChainMatch* filter_chain_match) { + auto* destination_port = + envoy_config_listener_v3_FilterChainMatch_destination_port( + filter_chain_match_proto); + if (destination_port != nullptr) { + filter_chain_match->destination_port = + google_protobuf_UInt32Value_value(destination_port); + } + size_t size = 0; + auto* prefix_ranges = envoy_config_listener_v3_FilterChainMatch_prefix_ranges( + filter_chain_match_proto, &size); + filter_chain_match->prefix_ranges.reserve(size); + for (size_t i = 0; i < size; i++) { + XdsApi::LdsUpdate::FilterChainMap::CidrRange cidr_range; + grpc_error_handle error = CidrRangeParse(prefix_ranges[i], &cidr_range); + if (error != GRPC_ERROR_NONE) return error; + filter_chain_match->prefix_ranges.push_back(cidr_range); + } + filter_chain_match->source_type = + static_cast( + envoy_config_listener_v3_FilterChainMatch_source_type( + filter_chain_match_proto)); + auto* source_prefix_ranges = + envoy_config_listener_v3_FilterChainMatch_source_prefix_ranges( + filter_chain_match_proto, &size); + filter_chain_match->source_prefix_ranges.reserve(size); + for (size_t i = 0; i < size; i++) { + XdsApi::LdsUpdate::FilterChainMap::CidrRange cidr_range; + grpc_error_handle error = + CidrRangeParse(source_prefix_ranges[i], &cidr_range); + if (error != GRPC_ERROR_NONE) return error; + filter_chain_match->source_prefix_ranges.push_back(cidr_range); + } + auto* source_ports = envoy_config_listener_v3_FilterChainMatch_source_ports( + filter_chain_match_proto, &size); + filter_chain_match->source_ports.reserve(size); + for (size_t i = 0; i < size; i++) { + filter_chain_match->source_ports.push_back(source_ports[i]); + } + auto* server_names = envoy_config_listener_v3_FilterChainMatch_server_names( + filter_chain_match_proto, &size); + for (size_t i = 0; i < size; i++) { + filter_chain_match->server_names.push_back( + UpbStringToStdString(server_names[i])); + } + filter_chain_match->transport_protocol = UpbStringToStdString( + envoy_config_listener_v3_FilterChainMatch_transport_protocol( + filter_chain_match_proto)); + auto* application_protocols = + envoy_config_listener_v3_FilterChainMatch_application_protocols( + filter_chain_match_proto, &size); + for (size_t i = 0; i < size; i++) { + filter_chain_match->application_protocols.push_back( + UpbStringToStdString(application_protocols[i])); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle FilterChainParse( const EncodingContext& context, - const envoy_config_listener_v3_FilterChain* filter_chain_proto, - grpc_error** error) { - XdsApi::LdsUpdate::FilterChain filter_chain; + const envoy_config_listener_v3_FilterChain* filter_chain_proto, bool is_v2, + FilterChain* filter_chain) { + grpc_error_handle error = GRPC_ERROR_NONE; auto* filter_chain_match = envoy_config_listener_v3_FilterChain_filter_chain_match( filter_chain_proto); if (filter_chain_match != nullptr) { - filter_chain.filter_chain_match = FilterChainMatchParse(filter_chain_match); + error = FilterChainMatchParse(filter_chain_match, + &filter_chain->filter_chain_match); + if (error != GRPC_ERROR_NONE) return error; } + // Parse the filters list. Currently we only support HttpConnectionManager. + size_t size = 0; + auto* filters = + envoy_config_listener_v3_FilterChain_filters(filter_chain_proto, &size); + if (size != 1) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "FilterChain should have exactly one filter: HttpConnectionManager; no " + "other filter is supported at the moment"); + } + auto* typed_config = envoy_config_listener_v3_Filter_typed_config(filters[0]); + if (typed_config == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No typed_config found in filter."); + } + absl::string_view type_url = + UpbStringToAbsl(google_protobuf_Any_type_url(typed_config)); + if (type_url != + "type.googleapis.com/" + "envoy.extensions.filters.network.http_connection_manager.v3." + "HttpConnectionManager") { + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("Unsupported filter type ", type_url).c_str()); + } + const upb_strview encoded_http_connection_manager = + google_protobuf_Any_value(typed_config); + const auto* http_connection_manager = + envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_parse( + encoded_http_connection_manager.data, + encoded_http_connection_manager.size, context.arena); + if (http_connection_manager == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Could not parse HttpConnectionManager config from filter " + "typed_config"); + } + filter_chain->filter_chain_data = + std::make_shared(); + error = HttpConnectionManagerParse( + false /* is_client */, context, http_connection_manager, is_v2, + &filter_chain->filter_chain_data->http_connection_manager); + if (error != GRPC_ERROR_NONE) return error; // Get the DownstreamTlsContext for the filter chain if (XdsSecurityEnabled()) { auto* transport_socket = envoy_config_listener_v3_FilterChain_transport_socket( filter_chain_proto); if (transport_socket != nullptr) { - *error = DownstreamTlsContextParse(context, transport_socket, - &filter_chain.downstream_tls_context); + error = DownstreamTlsContextParse( + context, transport_socket, + &filter_chain->filter_chain_data->downstream_tls_context); } } - return filter_chain; + return error; +} + +grpc_error_handle AddressParse( + const envoy_config_core_v3_Address* address_proto, std::string* address) { + const auto* socket_address = + envoy_config_core_v3_Address_socket_address(address_proto); + if (socket_address == nullptr) { + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + "Address does not have socket_address"); + } + if (envoy_config_core_v3_SocketAddress_protocol(socket_address) != + envoy_config_core_v3_SocketAddress_TCP) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "SocketAddress protocol is not TCP"); + } + uint32_t port = envoy_config_core_v3_SocketAddress_port_value(socket_address); + if (port > 65535) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Invalid port"); + } + *address = JoinHostPort( + UpbStringToAbsl( + envoy_config_core_v3_SocketAddress_address(socket_address)), + port); + return GRPC_ERROR_NONE; } -grpc_error* LdsResponseParseServer( +// An intermediate map for filter chains that we create to validate the list of +// filter chains received from the control plane and to finally create +// XdsApi::LdsUpdate::FilterChainMap +struct InternalFilterChainMap { + using SourceIpMap = + std::map; + using ConnectionSourceTypesArray = std::array; + struct DestinationIp { + absl::optional prefix_range; + bool transport_protocol_raw_buffer_provided = false; + ConnectionSourceTypesArray source_types_array; + }; + using DestinationIpMap = std::map; + DestinationIpMap destination_ip_map; +}; + +grpc_error_handle AddFilterChainDataForSourcePort( + const FilterChain& filter_chain, + XdsApi::LdsUpdate::FilterChainMap::SourcePortsMap* ports_map, + uint32_t port) { + auto insert_result = ports_map->emplace( + port, XdsApi::LdsUpdate::FilterChainMap::FilterChainDataSharedPtr{ + filter_chain.filter_chain_data}); + if (!insert_result.second) { + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat( + "Duplicate matching rules detected when adding filter chain: ", + filter_chain.filter_chain_match.ToString()) + .c_str()); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle AddFilterChainDataForSourcePorts( + const FilterChain& filter_chain, + XdsApi::LdsUpdate::FilterChainMap::SourcePortsMap* ports_map) { + if (filter_chain.filter_chain_match.source_ports.empty()) { + return AddFilterChainDataForSourcePort(filter_chain, ports_map, 0); + } else { + for (uint32_t port : filter_chain.filter_chain_match.source_ports) { + grpc_error_handle error = + AddFilterChainDataForSourcePort(filter_chain, ports_map, port); + if (error != GRPC_ERROR_NONE) return error; + } + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle AddFilterChainDataForSourceIpRange( + const FilterChain& filter_chain, + InternalFilterChainMap::SourceIpMap* source_ip_map) { + if (filter_chain.filter_chain_match.source_prefix_ranges.empty()) { + auto insert_result = source_ip_map->emplace( + "", XdsApi::LdsUpdate::FilterChainMap::SourceIp()); + return AddFilterChainDataForSourcePorts( + filter_chain, &insert_result.first->second.ports_map); + } else { + for (const auto& prefix_range : + filter_chain.filter_chain_match.source_prefix_ranges) { + auto insert_result = source_ip_map->emplace( + absl::StrCat(grpc_sockaddr_to_string(&prefix_range.address, false), + "/", prefix_range.prefix_len), + XdsApi::LdsUpdate::FilterChainMap::SourceIp()); + if (insert_result.second) { + insert_result.first->second.prefix_range.emplace(prefix_range); + } + grpc_error_handle error = AddFilterChainDataForSourcePorts( + filter_chain, &insert_result.first->second.ports_map); + if (error != GRPC_ERROR_NONE) return error; + } + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle AddFilterChainDataForSourceType( + const FilterChain& filter_chain, + InternalFilterChainMap::DestinationIp* destination_ip) { + GPR_ASSERT(static_cast( + filter_chain.filter_chain_match.source_type) < 3); + return AddFilterChainDataForSourceIpRange( + filter_chain, &destination_ip->source_types_array[static_cast( + filter_chain.filter_chain_match.source_type)]); +} + +grpc_error_handle AddFilterChainDataForApplicationProtocols( + const FilterChain& filter_chain, + InternalFilterChainMap::DestinationIp* destination_ip) { + // Only allow filter chains that do not mention application protocols + if (!filter_chain.filter_chain_match.application_protocols.empty()) { + return GRPC_ERROR_NONE; + } + return AddFilterChainDataForSourceType(filter_chain, destination_ip); +} + +grpc_error_handle AddFilterChainDataForTransportProtocol( + const FilterChain& filter_chain, + InternalFilterChainMap::DestinationIp* destination_ip) { + const std::string& transport_protocol = + filter_chain.filter_chain_match.transport_protocol; + // Only allow filter chains with no transport protocol or "raw_buffer" + if (!transport_protocol.empty() && transport_protocol != "raw_buffer") { + return GRPC_ERROR_NONE; + } + // If for this configuration, we've already seen filter chains that mention + // the transport protocol as "raw_buffer", we will never match filter chains + // that do not mention it. + if (destination_ip->transport_protocol_raw_buffer_provided && + transport_protocol.empty()) { + return GRPC_ERROR_NONE; + } + if (!transport_protocol.empty() && + !destination_ip->transport_protocol_raw_buffer_provided) { + destination_ip->transport_protocol_raw_buffer_provided = true; + // Clear out the previous entries if any since those entries did not mention + // "raw_buffer" + destination_ip->source_types_array = + InternalFilterChainMap::ConnectionSourceTypesArray(); + } + return AddFilterChainDataForApplicationProtocols(filter_chain, + destination_ip); +} + +grpc_error_handle AddFilterChainDataForServerNames( + const FilterChain& filter_chain, + InternalFilterChainMap::DestinationIp* destination_ip) { + // Don't continue adding filter chains with server names mentioned + if (!filter_chain.filter_chain_match.server_names.empty()) { + return GRPC_ERROR_NONE; + } + return AddFilterChainDataForTransportProtocol(filter_chain, destination_ip); +} + +grpc_error_handle AddFilterChainDataForDestinationIpRange( + const FilterChain& filter_chain, + InternalFilterChainMap::DestinationIpMap* destination_ip_map) { + if (filter_chain.filter_chain_match.prefix_ranges.empty()) { + auto insert_result = destination_ip_map->emplace( + "", InternalFilterChainMap::DestinationIp()); + return AddFilterChainDataForServerNames(filter_chain, + &insert_result.first->second); + } else { + for (const auto& prefix_range : + filter_chain.filter_chain_match.prefix_ranges) { + auto insert_result = destination_ip_map->emplace( + absl::StrCat(grpc_sockaddr_to_string(&prefix_range.address, false), + "/", prefix_range.prefix_len), + InternalFilterChainMap::DestinationIp()); + if (insert_result.second) { + insert_result.first->second.prefix_range.emplace(prefix_range); + } + grpc_error_handle error = AddFilterChainDataForServerNames( + filter_chain, &insert_result.first->second); + if (error != GRPC_ERROR_NONE) return error; + } + } + return GRPC_ERROR_NONE; +} + +XdsApi::LdsUpdate::FilterChainMap BuildFromInternalFilterChainMap( + InternalFilterChainMap* internal_filter_chain_map) { + XdsApi::LdsUpdate::FilterChainMap filter_chain_map; + for (auto& destination_ip_pair : + internal_filter_chain_map->destination_ip_map) { + XdsApi::LdsUpdate::FilterChainMap::DestinationIp destination_ip; + destination_ip.prefix_range = destination_ip_pair.second.prefix_range; + for (int i = 0; i < 3; i++) { + auto& source_ip_map = destination_ip_pair.second.source_types_array[i]; + for (auto& source_ip_pair : source_ip_map) { + destination_ip.source_types_array[i].push_back( + std::move(source_ip_pair.second)); + } + } + filter_chain_map.destination_ip_vector.push_back(std::move(destination_ip)); + } + return filter_chain_map; +} + +grpc_error_handle BuildFilterChainMap( + const std::vector& filter_chains, + XdsApi::LdsUpdate::FilterChainMap* filter_chain_map) { + InternalFilterChainMap internal_filter_chain_map; + for (const auto& filter_chain : filter_chains) { + // Discard filter chain entries that specify destination port + if (filter_chain.filter_chain_match.destination_port != 0) continue; + grpc_error_handle error = AddFilterChainDataForDestinationIpRange( + filter_chain, &internal_filter_chain_map.destination_ip_map); + if (error != GRPC_ERROR_NONE) return error; + } + *filter_chain_map = + BuildFromInternalFilterChainMap(&internal_filter_chain_map); + return GRPC_ERROR_NONE; +} + +grpc_error_handle LdsResponseParseServer( const EncodingContext& context, - const envoy_config_listener_v3_Listener* listener, + const envoy_config_listener_v3_Listener* listener, bool is_v2, XdsApi::LdsUpdate* lds_update) { lds_update->type = XdsApi::LdsUpdate::ListenerType::kTcpListener; - grpc_error* error = GRPC_ERROR_NONE; - // TODO(yashykt): As part of this, we'll need to refactor the code to process - // the HttpConnectionManager config so that it is shared with the client-side - // parsing. + grpc_error_handle error = + AddressParse(envoy_config_listener_v3_Listener_address(listener), + &lds_update->address); + if (error != GRPC_ERROR_NONE) return error; + const auto* use_original_dst = + envoy_config_listener_v3_Listener_use_original_dst(listener); + if (use_original_dst != nullptr) { + if (google_protobuf_BoolValue_value(use_original_dst)) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Field \'use_original_dst\' is not supported."); + } + } size_t size = 0; auto* filter_chains = envoy_config_listener_v3_Listener_filter_chains(listener, &size); - // TODO(yashykt): Remove following if block when FilterChainMatch - // implementation is in - if (size == 0) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "At least one filter chain needed."); - } - lds_update->filter_chains.reserve(size); + std::vector parsed_filter_chains; + parsed_filter_chains.reserve(size); for (size_t i = 0; i < size; i++) { - lds_update->filter_chains.push_back( - FilterChainParse(context, filter_chains[0], &error)); - if (error != GRPC_ERROR_NONE) { - return error; - } + FilterChain filter_chain; + error = FilterChainParse(context, filter_chains[i], is_v2, &filter_chain); + if (error != GRPC_ERROR_NONE) return error; + parsed_filter_chains.push_back(std::move(filter_chain)); } + error = + BuildFilterChainMap(parsed_filter_chains, &lds_update->filter_chain_map); + if (error != GRPC_ERROR_NONE) return error; auto* default_filter_chain = envoy_config_listener_v3_Listener_default_filter_chain(listener); if (default_filter_chain != nullptr) { - lds_update->default_filter_chain = - FilterChainParse(context, default_filter_chain, &error); - if (error != GRPC_ERROR_NONE) { - return error; + FilterChain filter_chain; + error = + FilterChainParse(context, default_filter_chain, is_v2, &filter_chain); + if (error != GRPC_ERROR_NONE) return error; + if (filter_chain.filter_chain_data != nullptr) { + lds_update->default_filter_chain = + std::move(*filter_chain.filter_chain_data); } } if (size == 0 && default_filter_chain == nullptr) { @@ -1935,13 +2496,13 @@ grpc_error* LdsResponseParseServer( return GRPC_ERROR_NONE; } -grpc_error* LdsResponseParse( +grpc_error_handle LdsResponseParse( const EncodingContext& context, const envoy_service_discovery_v3_DiscoveryResponse* response, const std::set& expected_listener_names, XdsApi::LdsUpdateMap* lds_update_map, std::set* resource_names_failed) { - std::vector errors; + std::vector errors; // Get the resources from the response. size_t size; const google_protobuf_Any* const* resources = @@ -1950,7 +2511,8 @@ grpc_error* LdsResponseParse( // Check the type_url of the resource. absl::string_view type_url = UpbStringToAbsl(google_protobuf_Any_type_url(resources[i])); - if (!IsLds(type_url)) { + bool is_v2 = false; + if (!IsLds(type_url, &is_v2)) { errors.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("resource index ", i, ": Resource is not LDS.") .c_str())); @@ -1983,7 +2545,11 @@ grpc_error* LdsResponseParse( resource_names_failed->insert(listener_name); continue; } - XdsApi::LdsUpdate& lds_update = (*lds_update_map)[listener_name]; + // Serialize into JSON and store it in the LdsUpdateMap + XdsApi::LdsResourceData& lds_resource_data = + (*lds_update_map)[listener_name]; + XdsApi::LdsUpdate& lds_update = lds_resource_data.resource; + lds_resource_data.serialized_proto = UpbStringToStdString(encoded_listener); // Check whether it's a client or server listener. const envoy_config_listener_v3_ApiListener* api_listener = envoy_config_listener_v3_Listener_api_listener(listener); @@ -2005,11 +2571,11 @@ grpc_error* LdsResponseParse( resource_names_failed->insert(listener_name); continue; } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (api_listener != nullptr) { - error = LdsResponseParseClient(context, api_listener, &lds_update); + error = LdsResponseParseClient(context, api_listener, is_v2, &lds_update); } else { - error = LdsResponseParseServer(context, listener, &lds_update); + error = LdsResponseParseServer(context, listener, is_v2, &lds_update); } if (error != GRPC_ERROR_NONE) { errors.push_back(grpc_error_add_child( @@ -2022,13 +2588,13 @@ grpc_error* LdsResponseParse( return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing LDS response", &errors); } -grpc_error* RdsResponseParse( +grpc_error_handle RdsResponseParse( const EncodingContext& context, const envoy_service_discovery_v3_DiscoveryResponse* response, const std::set& expected_route_configuration_names, XdsApi::RdsUpdateMap* rds_update_map, std::set* resource_names_failed) { - std::vector errors; + std::vector errors; // Get the resources from the response. size_t size; const google_protobuf_Any* const* resources = @@ -2072,9 +2638,15 @@ grpc_error* RdsResponseParse( resource_names_failed->insert(route_config_name); continue; } + // Serialize into JSON and store it in the RdsUpdateMap + XdsApi::RdsResourceData& rds_resource_data = + (*rds_update_map)[route_config_name]; + XdsApi::RdsUpdate& rds_update = rds_resource_data.resource; + rds_resource_data.serialized_proto = + UpbStringToStdString(encoded_route_config); // Parse the route_config. - XdsApi::RdsUpdate& rds_update = (*rds_update_map)[route_config_name]; - grpc_error* error = RouteConfigParse(context, route_config, &rds_update); + grpc_error_handle error = + RouteConfigParse(context, route_config, &rds_update); if (error != GRPC_ERROR_NONE) { errors.push_back(grpc_error_add_child( GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -2086,13 +2658,13 @@ grpc_error* RdsResponseParse( return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing RDS response", &errors); } -grpc_error* CdsResponseParse( +grpc_error_handle CdsResponseParse( const EncodingContext& context, const envoy_service_discovery_v3_DiscoveryResponse* response, const std::set& expected_cluster_names, XdsApi::CdsUpdateMap* cds_update_map, std::set* resource_names_failed) { - std::vector errors; + std::vector errors; // Get the resources from the response. size_t size; const google_protobuf_Any* const* resources = @@ -2135,7 +2707,11 @@ grpc_error* CdsResponseParse( resource_names_failed->insert(cluster_name); continue; } - XdsApi::CdsUpdate& cds_update = (*cds_update_map)[cluster_name]; + // Serialize into JSON and store it in the CdsUpdateMap + XdsApi::CdsResourceData& cds_resource_data = + (*cds_update_map)[cluster_name]; + XdsApi::CdsUpdate& cds_update = cds_resource_data.resource; + cds_resource_data.serialized_proto = UpbStringToStdString(encoded_cluster); // Check the cluster_discovery_type. if (!envoy_config_cluster_v3_Cluster_has_type(cluster) && !envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) { @@ -2344,7 +2920,7 @@ grpc_error* CdsResponseParse( envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_common_tls_context( upstream_tls_context); if (common_tls_context != nullptr) { - grpc_error* error = CommonTlsContextParse( + grpc_error_handle error = CommonTlsContextParse( common_tls_context, &cds_update.common_tls_context); if (error != GRPC_ERROR_NONE) { errors.push_back(grpc_error_add_child( @@ -2415,7 +2991,7 @@ grpc_error* CdsResponseParse( return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing CDS response", &errors); } -grpc_error* ServerAddressParseAndAppend( +grpc_error_handle ServerAddressParseAndAppend( const envoy_config_endpoint_v3_LbEndpoint* lb_endpoint, ServerAddressList* list) { // If health_status is not HEALTHY or UNKNOWN, skip this endpoint. @@ -2440,13 +3016,15 @@ grpc_error* ServerAddressParseAndAppend( } // Populate grpc_resolved_address. grpc_resolved_address addr; - grpc_string_to_sockaddr(&addr, address_str.c_str(), port); + grpc_error_handle error = + grpc_string_to_sockaddr(&addr, address_str.c_str(), port); + if (error != GRPC_ERROR_NONE) return error; // Append the address to the list. list->emplace_back(addr, nullptr); return GRPC_ERROR_NONE; } -grpc_error* LocalityParse( +grpc_error_handle LocalityParse( const envoy_config_endpoint_v3_LocalityLbEndpoints* locality_lb_endpoints, XdsApi::EdsUpdate::Priority::Locality* output_locality, size_t* priority) { // Parse LB weight. @@ -2463,6 +3041,9 @@ grpc_error* LocalityParse( const envoy_config_core_v3_Locality* locality = envoy_config_endpoint_v3_LocalityLbEndpoints_locality( locality_lb_endpoints); + if (locality == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty locality."); + } std::string region = UpbStringToStdString(envoy_config_core_v3_Locality_region(locality)); std::string zone = @@ -2477,7 +3058,7 @@ grpc_error* LocalityParse( envoy_config_endpoint_v3_LocalityLbEndpoints_lb_endpoints( locality_lb_endpoints, &size); for (size_t i = 0; i < size; ++i) { - grpc_error* error = ServerAddressParseAndAppend( + grpc_error_handle error = ServerAddressParseAndAppend( lb_endpoints[i], &output_locality->endpoints); if (error != GRPC_ERROR_NONE) return error; } @@ -2487,7 +3068,7 @@ grpc_error* LocalityParse( return GRPC_ERROR_NONE; } -grpc_error* DropParseAndAppend( +grpc_error_handle DropParseAndAppend( const envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload* drop_overload, XdsApi::EdsUpdate::DropConfig* drop_config) { @@ -2526,13 +3107,13 @@ grpc_error* DropParseAndAppend( return GRPC_ERROR_NONE; } -grpc_error* EdsResponseParse( +grpc_error_handle EdsResponseParse( const EncodingContext& context, const envoy_service_discovery_v3_DiscoveryResponse* response, const std::set& expected_eds_service_names, XdsApi::EdsUpdateMap* eds_update_map, std::set* resource_names_failed) { - std::vector errors; + std::vector errors; // Get the resources from the response. size_t size; const google_protobuf_Any* const* resources = @@ -2578,13 +3159,18 @@ grpc_error* EdsResponseParse( resource_names_failed->insert(eds_service_name); continue; } - XdsApi::EdsUpdate& eds_update = (*eds_update_map)[eds_service_name]; + // Serialize into JSON and store it in the EdsUpdateMap + XdsApi::EdsResourceData& eds_resource_data = + (*eds_update_map)[eds_service_name]; + XdsApi::EdsUpdate& eds_update = eds_resource_data.resource; + eds_resource_data.serialized_proto = + UpbStringToStdString(encoded_cluster_load_assignment); // Get the endpoints. size_t locality_size; const envoy_config_endpoint_v3_LocalityLbEndpoints* const* endpoints = envoy_config_endpoint_v3_ClusterLoadAssignment_endpoints( cluster_load_assignment, &locality_size); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; for (size_t j = 0; j < locality_size; ++j) { size_t priority; XdsApi::EdsUpdate::Priority::Locality locality; @@ -2898,10 +3484,10 @@ grpc_slice XdsApi::CreateLrsRequest( return SerializeLrsRequest(context, request); } -grpc_error* XdsApi::ParseLrsResponse(const grpc_slice& encoded_response, - bool* send_all_clusters, - std::set* cluster_names, - grpc_millis* load_reporting_interval) { +grpc_error_handle XdsApi::ParseLrsResponse( + const grpc_slice& encoded_response, bool* send_all_clusters, + std::set* cluster_names, + grpc_millis* load_reporting_interval) { upb::Arena arena; // Decode the response. const envoy_service_load_stats_v3_LoadStatsResponse* decoded_response = @@ -2938,4 +3524,276 @@ grpc_error* XdsApi::ParseLrsResponse(const grpc_slice& encoded_response, return GRPC_ERROR_NONE; } +namespace { +google_protobuf_Timestamp* GrpcMillisToTimestamp(const EncodingContext& context, + grpc_millis value) { + google_protobuf_Timestamp* timestamp = + google_protobuf_Timestamp_new(context.arena); + gpr_timespec timespec = grpc_millis_to_timespec(value, GPR_CLOCK_REALTIME); + google_protobuf_Timestamp_set_seconds(timestamp, timespec.tv_sec); + google_protobuf_Timestamp_set_nanos(timestamp, timespec.tv_nsec); + return timestamp; +} + +envoy_admin_v3_UpdateFailureState* CreateUpdateFailureStateUpb( + const EncodingContext& context, + const XdsApi::ResourceMetadata* resource_metadata) { + auto* update_failure_state = + envoy_admin_v3_UpdateFailureState_new(context.arena); + envoy_admin_v3_UpdateFailureState_set_details( + update_failure_state, + StdStringToUpbString(resource_metadata->failed_details)); + envoy_admin_v3_UpdateFailureState_set_version_info( + update_failure_state, + StdStringToUpbString(resource_metadata->failed_version)); + envoy_admin_v3_UpdateFailureState_set_last_update_attempt( + update_failure_state, + GrpcMillisToTimestamp(context, resource_metadata->failed_update_time)); + return update_failure_state; +} + +void DumpLdsConfig(const EncodingContext& context, + const XdsApi::ResourceTypeMetadata& resource_type_metadata, + envoy_service_status_v3_PerXdsConfig* per_xds_config) { + upb_strview kLdsTypeUrlUpb = upb_strview_makez(XdsApi::kLdsTypeUrl); + auto* listener_config_dump = + envoy_service_status_v3_PerXdsConfig_mutable_listener_config( + per_xds_config, context.arena); + envoy_admin_v3_ListenersConfigDump_set_version_info( + listener_config_dump, + StdStringToUpbString(resource_type_metadata.version)); + for (auto& p : resource_type_metadata.resource_metadata_map) { + absl::string_view name = p.first; + const XdsApi::ResourceMetadata* meta = p.second; + const upb_strview name_upb = StdStringToUpbString(name); + auto* dynamic_listener = + envoy_admin_v3_ListenersConfigDump_add_dynamic_listeners( + listener_config_dump, context.arena); + envoy_admin_v3_ListenersConfigDump_DynamicListener_set_name( + dynamic_listener, name_upb); + envoy_admin_v3_ListenersConfigDump_DynamicListener_set_client_status( + dynamic_listener, meta->client_status); + if (!meta->serialized_proto.empty()) { + // Set in-effective listeners + auto* dynamic_listener_state = + envoy_admin_v3_ListenersConfigDump_DynamicListener_mutable_active_state( + dynamic_listener, context.arena); + envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_version_info( + dynamic_listener_state, StdStringToUpbString(meta->version)); + envoy_admin_v3_ListenersConfigDump_DynamicListenerState_set_last_updated( + dynamic_listener_state, + GrpcMillisToTimestamp(context, meta->update_time)); + auto* listener_any = + envoy_admin_v3_ListenersConfigDump_DynamicListenerState_mutable_listener( + dynamic_listener_state, context.arena); + google_protobuf_Any_set_type_url(listener_any, kLdsTypeUrlUpb); + google_protobuf_Any_set_value( + listener_any, StdStringToUpbString(meta->serialized_proto)); + } + if (meta->client_status == XdsApi::ResourceMetadata::NACKED) { + // Set error_state if NACKED + envoy_admin_v3_ListenersConfigDump_DynamicListener_set_error_state( + dynamic_listener, CreateUpdateFailureStateUpb(context, meta)); + } + } +} + +void DumpRdsConfig(const EncodingContext& context, + const XdsApi::ResourceTypeMetadata& resource_type_metadata, + envoy_service_status_v3_PerXdsConfig* per_xds_config) { + upb_strview kRdsTypeUrlUpb = upb_strview_makez(XdsApi::kRdsTypeUrl); + auto* route_config_dump = + envoy_service_status_v3_PerXdsConfig_mutable_route_config(per_xds_config, + context.arena); + for (auto& p : resource_type_metadata.resource_metadata_map) { + absl::string_view name = p.first; + const XdsApi::ResourceMetadata* meta = p.second; + const upb_strview name_upb = StdStringToUpbString(name); + auto* dynamic_route_config = + envoy_admin_v3_RoutesConfigDump_add_dynamic_route_configs( + route_config_dump, context.arena); + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_client_status( + dynamic_route_config, meta->client_status); + auto* route_config_any = + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_mutable_route_config( + dynamic_route_config, context.arena); + if (!meta->serialized_proto.empty()) { + // Set in-effective route configs + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_version_info( + dynamic_route_config, StdStringToUpbString(meta->version)); + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_last_updated( + dynamic_route_config, + GrpcMillisToTimestamp(context, meta->update_time)); + google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb); + google_protobuf_Any_set_value( + route_config_any, StdStringToUpbString(meta->serialized_proto)); + } else { + // If there isn't a working route config, we still need to print the + // name. + auto* route_config = + envoy_config_route_v3_RouteConfiguration_new(context.arena); + envoy_config_route_v3_RouteConfiguration_set_name(route_config, name_upb); + size_t length; + char* bytes = envoy_config_route_v3_RouteConfiguration_serialize( + route_config, context.arena, &length); + google_protobuf_Any_set_type_url(route_config_any, kRdsTypeUrlUpb); + google_protobuf_Any_set_value(route_config_any, + upb_strview_make(bytes, length)); + } + if (meta->client_status == XdsApi::ResourceMetadata::NACKED) { + // Set error_state if NACKED + envoy_admin_v3_RoutesConfigDump_DynamicRouteConfig_set_error_state( + dynamic_route_config, CreateUpdateFailureStateUpb(context, meta)); + } + } +} + +void DumpCdsConfig(const EncodingContext& context, + const XdsApi::ResourceTypeMetadata& resource_type_metadata, + envoy_service_status_v3_PerXdsConfig* per_xds_config) { + upb_strview kCdsTypeUrlUpb = upb_strview_makez(XdsApi::kCdsTypeUrl); + auto* cluster_config_dump = + envoy_service_status_v3_PerXdsConfig_mutable_cluster_config( + per_xds_config, context.arena); + envoy_admin_v3_ClustersConfigDump_set_version_info( + cluster_config_dump, + StdStringToUpbString(resource_type_metadata.version)); + for (auto& p : resource_type_metadata.resource_metadata_map) { + absl::string_view name = p.first; + const XdsApi::ResourceMetadata* meta = p.second; + const upb_strview name_upb = StdStringToUpbString(name); + auto* dynamic_cluster = + envoy_admin_v3_ClustersConfigDump_add_dynamic_active_clusters( + cluster_config_dump, context.arena); + envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_client_status( + dynamic_cluster, meta->client_status); + auto* cluster_any = + envoy_admin_v3_ClustersConfigDump_DynamicCluster_mutable_cluster( + dynamic_cluster, context.arena); + if (!meta->serialized_proto.empty()) { + // Set in-effective clusters + envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_version_info( + dynamic_cluster, StdStringToUpbString(meta->version)); + envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_last_updated( + dynamic_cluster, GrpcMillisToTimestamp(context, meta->update_time)); + google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb); + google_protobuf_Any_set_value( + cluster_any, StdStringToUpbString(meta->serialized_proto)); + } else { + // If there isn't a working cluster, we still need to print the name. + auto* cluster = envoy_config_cluster_v3_Cluster_new(context.arena); + envoy_config_cluster_v3_Cluster_set_name(cluster, name_upb); + size_t length; + char* bytes = envoy_config_cluster_v3_Cluster_serialize( + cluster, context.arena, &length); + google_protobuf_Any_set_type_url(cluster_any, kCdsTypeUrlUpb); + google_protobuf_Any_set_value(cluster_any, + upb_strview_make(bytes, length)); + } + if (meta->client_status == XdsApi::ResourceMetadata::NACKED) { + // Set error_state if NACKED + envoy_admin_v3_ClustersConfigDump_DynamicCluster_set_error_state( + dynamic_cluster, CreateUpdateFailureStateUpb(context, meta)); + } + } +} + +void DumpEdsConfig(const EncodingContext& context, + const XdsApi::ResourceTypeMetadata& resource_type_metadata, + envoy_service_status_v3_PerXdsConfig* per_xds_config) { + upb_strview kEdsTypeUrlUpb = upb_strview_makez(XdsApi::kEdsTypeUrl); + auto* endpoint_config_dump = + envoy_service_status_v3_PerXdsConfig_mutable_endpoint_config( + per_xds_config, context.arena); + for (auto& p : resource_type_metadata.resource_metadata_map) { + absl::string_view name = p.first; + const XdsApi::ResourceMetadata* meta = p.second; + const upb_strview name_upb = StdStringToUpbString(name); + auto* dynamic_endpoint = + envoy_admin_v3_EndpointsConfigDump_add_dynamic_endpoint_configs( + endpoint_config_dump, context.arena); + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_client_status( + dynamic_endpoint, meta->client_status); + auto* endpoint_any = + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_mutable_endpoint_config( + dynamic_endpoint, context.arena); + if (!meta->serialized_proto.empty()) { + // Set in-effective endpoints + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_version_info( + dynamic_endpoint, StdStringToUpbString(meta->version)); + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_last_updated( + dynamic_endpoint, GrpcMillisToTimestamp(context, meta->update_time)); + google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb); + google_protobuf_Any_set_value( + endpoint_any, StdStringToUpbString(meta->serialized_proto)); + } else { + // If there isn't a working endpoint, we still need to print the name. + auto* cluster_load_assignment = + envoy_config_endpoint_v3_ClusterLoadAssignment_new(context.arena); + envoy_config_endpoint_v3_ClusterLoadAssignment_set_cluster_name( + cluster_load_assignment, name_upb); + size_t length; + char* bytes = envoy_config_endpoint_v3_ClusterLoadAssignment_serialize( + cluster_load_assignment, context.arena, &length); + google_protobuf_Any_set_type_url(endpoint_any, kEdsTypeUrlUpb); + google_protobuf_Any_set_value(endpoint_any, + upb_strview_make(bytes, length)); + } + if (meta->client_status == XdsApi::ResourceMetadata::NACKED) { + // Set error_state if NACKED + envoy_admin_v3_EndpointsConfigDump_DynamicEndpointConfig_set_error_state( + dynamic_endpoint, CreateUpdateFailureStateUpb(context, meta)); + } + } +} + +} // namespace + +std::string XdsApi::AssembleClientConfig( + const ResourceTypeMetadataMap& resource_type_metadata_map) { + upb::Arena arena; + // Create the ClientConfig for resource metadata from XdsClient + auto* client_config = envoy_service_status_v3_ClientConfig_new(arena.ptr()); + // Fill-in the node information + auto* node = envoy_service_status_v3_ClientConfig_mutable_node(client_config, + arena.ptr()); + const EncodingContext context = {client_, tracer_, symtab_.ptr(), arena.ptr(), + true}; + PopulateNode(context, node_, build_version_, user_agent_name_, node); + // Dump each xDS-type config into PerXdsConfig + for (auto& p : resource_type_metadata_map) { + absl::string_view type_url = p.first; + const ResourceTypeMetadata& resource_type_metadata = p.second; + if (type_url == kLdsTypeUrl) { + auto* per_xds_config = + envoy_service_status_v3_ClientConfig_add_xds_config(client_config, + context.arena); + DumpLdsConfig(context, resource_type_metadata, per_xds_config); + } else if (type_url == kRdsTypeUrl) { + auto* per_xds_config = + envoy_service_status_v3_ClientConfig_add_xds_config(client_config, + context.arena); + DumpRdsConfig(context, resource_type_metadata, per_xds_config); + } else if (type_url == kCdsTypeUrl) { + auto* per_xds_config = + envoy_service_status_v3_ClientConfig_add_xds_config(client_config, + context.arena); + DumpCdsConfig(context, resource_type_metadata, per_xds_config); + } else if (type_url == kEdsTypeUrl) { + auto* per_xds_config = + envoy_service_status_v3_ClientConfig_add_xds_config(client_config, + context.arena); + DumpEdsConfig(context, resource_type_metadata, per_xds_config); + } else { + gpr_log(GPR_ERROR, "invalid type_url %s", std::string(type_url).c_str()); + return ""; + } + } + // Serialize the upb message to bytes + size_t output_length; + char* output = envoy_service_status_v3_ClientConfig_serialize( + client_config, arena.ptr(), &output_length); + return std::string(output, output_length); +} + } // namespace grpc_core diff --git a/src/core/ext/xds/xds_api.h b/src/core/ext/xds/xds_api.h index 921274bc86a..e7bf1cd14e5 100644 --- a/src/core/ext/xds/xds_api.h +++ b/src/core/ext/xds/xds_api.h @@ -33,11 +33,12 @@ #include +#include "envoy/admin/v3/config_dump.upb.h" #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/xds/xds_bootstrap.h" #include "src/core/ext/xds/xds_client_stats.h" #include "src/core/ext/xds/xds_http_filters.h" -#include "src/core/lib/security/authorization/matchers.h" +#include "src/core/lib/matchers/matchers.h" namespace grpc_core { @@ -46,10 +47,6 @@ namespace grpc_core { // default. bool XdsSecurityEnabled(); -// TODO(lidiz): This will be removed once the fault injection feature is -// fully integration-tested and enabled by default. -bool XdsFaultInjectionEnabled(); - class XdsClient; class XdsApi { @@ -90,7 +87,31 @@ class XdsApi { std::string ToString() const; }; + struct HashPolicy { + enum Type { HEADER, CHANNEL_ID }; + Type type; + bool terminal = false; + // Fields used for type HEADER. + std::string header_name; + std::unique_ptr regex = nullptr; + std::string regex_substitution; + + HashPolicy() {} + + // Copyable. + HashPolicy(const HashPolicy& other); + HashPolicy& operator=(const HashPolicy& other); + + // Moveable. + HashPolicy(HashPolicy&& other) noexcept; + HashPolicy& operator=(HashPolicy&& other) noexcept; + + bool operator==(const HashPolicy& other) const; + std::string ToString() const; + }; + Matchers matchers; + std::vector hash_policies; // Action for this route. // TODO(roth): When we can use absl::variant<>, consider using that @@ -219,100 +240,157 @@ class XdsApi { kTcpListener = 0, kHttpApiListener, } type; - // The name to use in the RDS request. - std::string route_config_name; - // Storing the Http Connection Manager Common Http Protocol Option - // max_stream_duration - Duration http_max_stream_duration; - // The RouteConfiguration to use for this listener. - // Present only if it is inlined in the LDS response. - absl::optional rds_update; - - struct HttpFilter { - std::string name; - XdsHttpFilterImpl::FilterConfig config; - bool operator==(const HttpFilter& other) const { - return name == other.name && config == other.config; + struct HttpConnectionManager { + // The name to use in the RDS request. + std::string route_config_name; + // Storing the Http Connection Manager Common Http Protocol Option + // max_stream_duration + Duration http_max_stream_duration; + // The RouteConfiguration to use for this listener. + // Present only if it is inlined in the LDS response. + absl::optional rds_update; + + struct HttpFilter { + std::string name; + XdsHttpFilterImpl::FilterConfig config; + + bool operator==(const HttpFilter& other) const { + return name == other.name && config == other.config; + } + + std::string ToString() const; + }; + std::vector http_filters; + + bool operator==(const HttpConnectionManager& other) const { + return route_config_name == other.route_config_name && + http_max_stream_duration == other.http_max_stream_duration && + rds_update == other.rds_update && + http_filters == other.http_filters; } std::string ToString() const; }; - std::vector http_filters; - - struct FilterChain { - struct FilterChainMatch { - uint32_t destination_port = 0; - - struct CidrRange { - std::string address_prefix; - uint32_t prefix_len; - - bool operator==(const CidrRange& other) const { - return address_prefix == other.address_prefix && - prefix_len == other.prefix_len; - } - - std::string ToString() const; - }; - - std::vector prefix_ranges; - - enum class ConnectionSourceType { - kAny = 0, - kSameIpOrLoopback, - kExternal - } source_type = ConnectionSourceType::kAny; - - std::vector source_prefix_ranges; - std::vector source_ports; - std::vector server_names; - std::string transport_protocol; - std::vector application_protocols; - - bool operator==(const FilterChainMatch& other) const { - return destination_port == other.destination_port && - prefix_ranges == other.prefix_ranges && - source_type == other.source_type && - source_prefix_ranges == other.source_prefix_ranges && - source_ports == other.source_ports && - server_names == other.server_names && - transport_protocol == other.transport_protocol && - application_protocols == other.application_protocols; - } + // Populated for type=kHttpApiListener. + HttpConnectionManager http_connection_manager; - std::string ToString() const; - } filter_chain_match; + // Populated for type=kTcpListener. + // host:port listening_address set when type is kTcpListener + std::string address; + struct FilterChainData { DownstreamTlsContext downstream_tls_context; + // This is in principle the filter list. + // We currently require exactly one filter, which is the HCM. + HttpConnectionManager http_connection_manager; - bool operator==(const FilterChain& other) const { - return filter_chain_match == other.filter_chain_match && - downstream_tls_context == other.downstream_tls_context; + bool operator==(const FilterChainData& other) const { + return downstream_tls_context == other.downstream_tls_context && + http_connection_manager == other.http_connection_manager; } std::string ToString() const; - }; + } filter_chain_data; + + // A multi-level map used to determine which filter chain to use for a given + // incoming connection. Determining the right filter chain for a given + // connection checks the following properties, in order: + // - destination port (never matched, so not present in map) + // - destination IP address + // - server name (never matched, so not present in map) + // - transport protocol (allows only "raw_buffer" or unset, prefers the + // former, so only one of those two types is present in map) + // - application protocol (never matched, so not present in map) + // - connection source type (any, local or external) + // - source IP address + // - source port + // https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener_components.proto#config-listener-v3-filterchainmatch + // for more details + struct FilterChainMap { + struct FilterChainDataSharedPtr { + std::shared_ptr data; + bool operator==(const FilterChainDataSharedPtr& other) const { + return *data == *other.data; + } + }; + struct CidrRange { + grpc_resolved_address address; + uint32_t prefix_len; + + bool operator==(const CidrRange& other) const { + return memcmp(&address, &other.address, sizeof(address)) == 0 && + prefix_len == other.prefix_len; + } + + std::string ToString() const; + }; + using SourcePortsMap = std::map; + struct SourceIp { + absl::optional prefix_range; + SourcePortsMap ports_map; + + bool operator==(const SourceIp& other) const { + return prefix_range == other.prefix_range && + ports_map == other.ports_map; + } + }; + using SourceIpVector = std::vector; + enum class ConnectionSourceType { + kAny = 0, + kSameIpOrLoopback, + kExternal + }; + using ConnectionSourceTypesArray = std::array; + struct DestinationIp { + absl::optional prefix_range; + // We always fail match on server name, so those filter chains are not + // included here. + ConnectionSourceTypesArray source_types_array; + + bool operator==(const DestinationIp& other) const { + return prefix_range == other.prefix_range && + source_types_array == other.source_types_array; + } + }; + // We always fail match on destination ports map + using DestinationIpVector = std::vector; + DestinationIpVector destination_ip_vector; + + bool operator==(const FilterChainMap& other) const { + return destination_ip_vector == other.destination_ip_vector; + } + + std::string ToString() const; + } filter_chain_map; - std::vector filter_chains; - absl::optional default_filter_chain; + absl::optional default_filter_chain; bool operator==(const LdsUpdate& other) const { - return route_config_name == other.route_config_name && - rds_update == other.rds_update && - http_max_stream_duration == other.http_max_stream_duration && - http_filters == other.http_filters && - filter_chains == other.filter_chains && + return http_connection_manager == other.http_connection_manager && + address == other.address && + filter_chain_map == other.filter_chain_map && default_filter_chain == other.default_filter_chain; } std::string ToString() const; }; - using LdsUpdateMap = std::map; + struct LdsResourceData { + LdsUpdate resource; + std::string serialized_proto; + }; + + using LdsUpdateMap = std::map; + + struct RdsResourceData { + RdsUpdate resource; + std::string serialized_proto; + }; - using RdsUpdateMap = std::map; + using RdsUpdateMap = + std::map; struct CdsUpdate { enum ClusterType { EDS, LOGICAL_DNS, AGGREGATE }; @@ -355,7 +433,12 @@ class XdsApi { std::string ToString() const; }; - using CdsUpdateMap = std::map; + struct CdsResourceData { + CdsUpdate resource; + std::string serialized_proto; + }; + + using CdsUpdateMap = std::map; struct EdsUpdate { struct Priority { @@ -439,7 +522,13 @@ class XdsApi { std::string ToString() const; }; - using EdsUpdateMap = std::map; + struct EdsResourceData { + EdsUpdate resource; + std::string serialized_proto; + }; + + using EdsUpdateMap = + std::map; struct ClusterLoadReport { XdsClusterDropStats::Snapshot dropped_requests; @@ -452,18 +541,66 @@ class XdsApi { std::pair, ClusterLoadReport>; - XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node); + // The metadata of the xDS resource; used by the xDS config dump. + struct ResourceMetadata { + // Resource status from the view of a xDS client, which tells the + // synchronization status between the xDS client and the xDS server. + enum ClientResourceStatus { + // Client requested this resource but hasn't received any update from + // management server. The client will not fail requests, but will queue + // them + // until update arrives or the client times out waiting for the resource. + REQUESTED = 1, + // This resource has been requested by the client but has either not been + // delivered by the server or was previously delivered by the server and + // then subsequently removed from resources provided by the server. + DOES_NOT_EXIST, + // Client received this resource and replied with ACK. + ACKED, + // Client received this resource and replied with NACK. + NACKED + }; - // Creates an ADS request. - // Takes ownership of \a error. - grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server, - const std::string& type_url, - const std::set& resource_names, - const std::string& version, - const std::string& nonce, grpc_error* error, - bool populate_node); + // The client status of this resource. + ClientResourceStatus client_status = REQUESTED; + // The serialized bytes of the last successfully updated raw xDS resource. + std::string serialized_proto; + // The timestamp when the resource was last successfully updated. + grpc_millis update_time = 0; + // The last successfully updated version of the resource. + std::string version; + // The rejected version string of the last failed update attempt. + std::string failed_version; + // Details about the last failed update attempt. + std::string failed_details; + // Timestamp of the last failed update attempt. + grpc_millis failed_update_time = 0; + }; + using ResourceMetadataMap = + std::map; + struct ResourceTypeMetadata { + absl::string_view version; + ResourceMetadataMap resource_metadata_map; + }; + using ResourceTypeMetadataMap = + std::map; + static_assert(static_cast( + envoy_admin_v3_REQUESTED) == + ResourceMetadata::ClientResourceStatus::REQUESTED, + ""); + static_assert(static_cast( + envoy_admin_v3_DOES_NOT_EXIST) == + ResourceMetadata::ClientResourceStatus::DOES_NOT_EXIST, + ""); + static_assert(static_cast( + envoy_admin_v3_ACKED) == + ResourceMetadata::ClientResourceStatus::ACKED, + ""); + static_assert(static_cast( + envoy_admin_v3_NACKED) == + ResourceMetadata::ClientResourceStatus::NACKED, + ""); - // Parses an ADS response. // If the response can't be parsed at the top level, the resulting // type_url will be empty. // If there is any other type of validation error, the parse_error @@ -472,7 +609,7 @@ class XdsApi { // Otherwise, one of the *_update_map fields will be populated, based // on the type_url field. struct AdsParseResult { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; std::string version; std::string nonce; std::string type_url; @@ -482,6 +619,19 @@ class XdsApi { EdsUpdateMap eds_update_map; std::set resource_names_failed; }; + + XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node); + + // Creates an ADS request. + // Takes ownership of \a error. + grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server, + const std::string& type_url, + const std::set& resource_names, + const std::string& version, + const std::string& nonce, grpc_error_handle error, + bool populate_node); + + // Parses an ADS response. AdsParseResult ParseAdsResponse( const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response, const std::set& expected_listener_names, @@ -498,10 +648,14 @@ class XdsApi { // Parses the LRS response and returns \a // load_reporting_interval for client-side load reporting. If there is any // error, the output config is invalid. - grpc_error* ParseLrsResponse(const grpc_slice& encoded_response, - bool* send_all_clusters, - std::set* cluster_names, - grpc_millis* load_reporting_interval); + grpc_error_handle ParseLrsResponse(const grpc_slice& encoded_response, + bool* send_all_clusters, + std::set* cluster_names, + grpc_millis* load_reporting_interval); + + // Assemble the client config proto message and return the serialized result. + std::string AssembleClientConfig( + const ResourceTypeMetadataMap& resource_type_metadata_map); private: XdsClient* client_; diff --git a/src/core/ext/xds/xds_bootstrap.cc b/src/core/ext/xds/xds_bootstrap.cc index 321e8418441..33cf276d2c1 100644 --- a/src/core/ext/xds/xds_bootstrap.cc +++ b/src/core/ext/xds/xds_bootstrap.cc @@ -30,7 +30,6 @@ #include "src/core/ext/xds/certificate_provider_registry.h" #include "src/core/ext/xds/xds_api.h" -#include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/security/credentials/credentials.h" @@ -81,137 +80,27 @@ bool XdsBootstrap::XdsServer::ShouldUseV3() const { // XdsBootstrap // -namespace { - -std::string BootstrapString(const XdsBootstrap& bootstrap) { - std::vector parts; - if (bootstrap.node() != nullptr) { - parts.push_back(absl::StrFormat( - "node={\n" - " id=\"%s\",\n" - " cluster=\"%s\",\n" - " locality={\n" - " region=\"%s\",\n" - " zone=\"%s\",\n" - " sub_zone=\"%s\"\n" - " },\n" - " metadata=%s,\n" - "},\n", - bootstrap.node()->id, bootstrap.node()->cluster, - bootstrap.node()->locality_region, bootstrap.node()->locality_zone, - bootstrap.node()->locality_sub_zone, - bootstrap.node()->metadata.Dump())); - } - parts.push_back(absl::StrFormat( - "servers=[\n" - " {\n" - " uri=\"%s\",\n" - " creds_type=%s,\n", - bootstrap.server().server_uri, bootstrap.server().channel_creds_type)); - if (bootstrap.server().channel_creds_config.type() != Json::Type::JSON_NULL) { - parts.push_back( - absl::StrFormat(" creds_config=%s,", - bootstrap.server().channel_creds_config.Dump())); - } - if (!bootstrap.server().server_features.empty()) { - parts.push_back(absl::StrCat( - " server_features=[", - absl::StrJoin(bootstrap.server().server_features, ", "), "],\n")); - } - parts.push_back(" }\n],\n"); - parts.push_back("certificate_providers={\n"); - for (const auto& entry : bootstrap.certificate_providers()) { - parts.push_back( - absl::StrFormat(" %s={\n" - " plugin_name=%s\n" - " config=%s\n" - " },\n", - entry.first, entry.second.plugin_name, - entry.second.config->ToString())); - } - parts.push_back("}"); - return absl::StrJoin(parts, ""); -} - -std::unique_ptr ParseJsonAndCreate( - XdsClient* client, TraceFlag* tracer, absl::string_view json_string, - absl::string_view bootstrap_source, grpc_error** error) { +std::unique_ptr XdsBootstrap::Create( + absl::string_view json_string, grpc_error_handle* error) { Json json = Json::Parse(json_string, error); if (*error != GRPC_ERROR_NONE) { - grpc_error* error_out = GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING( - absl::StrCat("Failed to parse bootstrap from ", bootstrap_source) - .c_str(), - error, 1); + grpc_error_handle error_out = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Failed to parse bootstrap JSON string", error, 1); GRPC_ERROR_UNREF(*error); *error = error_out; return nullptr; } - std::unique_ptr result = - absl::make_unique(std::move(json), error); - if (*error == GRPC_ERROR_NONE && GRPC_TRACE_FLAG_ENABLED(*tracer)) { - gpr_log(GPR_INFO, - "[xds_client %p] Bootstrap config for creating xds client:\n%s", - client, BootstrapString(*result).c_str()); - } - return result; -} - -} // namespace - -std::unique_ptr XdsBootstrap::Create(XdsClient* client, - TraceFlag* tracer, - const char* fallback_config, - grpc_error** error) { - // First, try GRPC_XDS_BOOTSTRAP env var. - grpc_core::UniquePtr path(gpr_getenv("GRPC_XDS_BOOTSTRAP")); - if (path != nullptr) { - if (GRPC_TRACE_FLAG_ENABLED(*tracer)) { - gpr_log(GPR_INFO, - "[xds_client %p] Got bootstrap file location from " - "GRPC_XDS_BOOTSTRAP environment variable: %s", - client, path.get()); - } - grpc_slice contents; - *error = - grpc_load_file(path.get(), /*add_null_terminator=*/true, &contents); - if (*error != GRPC_ERROR_NONE) return nullptr; - absl::string_view contents_str_view = StringViewFromSlice(contents); - if (GRPC_TRACE_FLAG_ENABLED(*tracer)) { - gpr_log(GPR_DEBUG, "[xds_client %p] Bootstrap file contents: %s", client, - std::string(contents_str_view).c_str()); - } - std::string bootstrap_source = absl::StrCat("file ", path.get()); - auto result = ParseJsonAndCreate(client, tracer, contents_str_view, - bootstrap_source, error); - grpc_slice_unref_internal(contents); - return result; - } - // Next, try GRPC_XDS_BOOTSTRAP_CONFIG env var. - grpc_core::UniquePtr env_config( - gpr_getenv("GRPC_XDS_BOOTSTRAP_CONFIG")); - if (env_config != nullptr) { - return ParseJsonAndCreate(client, tracer, env_config.get(), - "GRPC_XDS_BOOTSTRAP_CONFIG env var", error); - } - // Finally, try fallback config. - if (fallback_config != nullptr) { - return ParseJsonAndCreate(client, tracer, fallback_config, - "fallback config", error); - } - // No bootstrap config found. - *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Environment variables GRPC_XDS_BOOTSTRAP or GRPC_XDS_BOOTSTRAP_CONFIG " - "not defined"); - return nullptr; + return absl::make_unique(std::move(json), error); } -XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) { +XdsBootstrap::XdsBootstrap(Json json, grpc_error_handle* error) { if (json.type() != Json::Type::OBJECT) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "malformed JSON in bootstrap file"); return; } - std::vector error_list; + std::vector error_list; auto it = json.mutable_object()->find("xds_servers"); if (it == json.mutable_object()->end()) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -220,7 +109,7 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"xds_servers\" field is not an array")); } else { - grpc_error* parse_error = ParseXdsServerList(&it->second); + grpc_error_handle parse_error = ParseXdsServerList(&it->second); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } it = json.mutable_object()->find("node"); @@ -229,10 +118,20 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"node\" field is not an object")); } else { - grpc_error* parse_error = ParseNode(&it->second); + grpc_error_handle parse_error = ParseNode(&it->second); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } + it = json.mutable_object()->find("server_listener_resource_name_template"); + if (it != json.mutable_object()->end()) { + if (it->second.type() != Json::Type::STRING) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "\"server_listener_resource_name_template\" field is not a string")); + } else { + server_listener_resource_name_template_ = + std::move(*it->second.mutable_string_value()); + } + } if (XdsSecurityEnabled()) { it = json.mutable_object()->find("certificate_providers"); if (it != json.mutable_object()->end()) { @@ -240,7 +139,7 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"certificate_providers\" field is not an object")); } else { - grpc_error* parse_error = ParseCertificateProviders(&it->second); + grpc_error_handle parse_error = ParseCertificateProviders(&it->second); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } @@ -249,15 +148,15 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error** error) { &error_list); } -grpc_error* XdsBootstrap::ParseXdsServerList(Json* json) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseXdsServerList(Json* json) { + std::vector error_list; for (size_t i = 0; i < json->mutable_array()->size(); ++i) { Json& child = json->mutable_array()->at(i); if (child.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("array element ", i, " is not an object").c_str())); } else { - grpc_error* parse_error = ParseXdsServer(&child, i); + grpc_error_handle parse_error = ParseXdsServer(&child, i); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } @@ -265,8 +164,8 @@ grpc_error* XdsBootstrap::ParseXdsServerList(Json* json) { &error_list); } -grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseXdsServer(Json* json, size_t idx) { + std::vector error_list; servers_.emplace_back(); XdsServer& server = servers_[servers_.size() - 1]; auto it = json->mutable_object()->find("server_uri"); @@ -287,7 +186,8 @@ grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"channel_creds\" field is not an array")); } else { - grpc_error* parse_error = ParseChannelCredsArray(&it->second, &server); + grpc_error_handle parse_error = + ParseChannelCredsArray(&it->second, &server); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } it = json->mutable_object()->find("server_features"); @@ -296,14 +196,15 @@ grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"server_features\" field is not an array")); } else { - grpc_error* parse_error = ParseServerFeaturesArray(&it->second, &server); + grpc_error_handle parse_error = + ParseServerFeaturesArray(&it->second, &server); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error // string is not static in this case. if (error_list.empty()) return GRPC_ERROR_NONE; - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("errors parsing index ", idx).c_str()); for (size_t i = 0; i < error_list.size(); ++i) { error = grpc_error_add_child(error, error_list[i]); @@ -311,16 +212,16 @@ grpc_error* XdsBootstrap::ParseXdsServer(Json* json, size_t idx) { return error; } -grpc_error* XdsBootstrap::ParseChannelCredsArray(Json* json, - XdsServer* server) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseChannelCredsArray(Json* json, + XdsServer* server) { + std::vector error_list; for (size_t i = 0; i < json->mutable_array()->size(); ++i) { Json& child = json->mutable_array()->at(i); if (child.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("array element ", i, " is not an object").c_str())); } else { - grpc_error* parse_error = ParseChannelCreds(&child, i, server); + grpc_error_handle parse_error = ParseChannelCreds(&child, i, server); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } @@ -332,9 +233,9 @@ grpc_error* XdsBootstrap::ParseChannelCredsArray(Json* json, &error_list); } -grpc_error* XdsBootstrap::ParseChannelCreds(Json* json, size_t idx, - XdsServer* server) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseChannelCreds(Json* json, size_t idx, + XdsServer* server) { + std::vector error_list; std::string type; auto it = json->mutable_object()->find("type"); if (it == json->mutable_object()->end()) { @@ -370,7 +271,7 @@ grpc_error* XdsBootstrap::ParseChannelCreds(Json* json, size_t idx, // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error // string is not static in this case. if (error_list.empty()) return GRPC_ERROR_NONE; - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("errors parsing index ", idx).c_str()); for (size_t i = 0; i < error_list.size(); ++i) { error = grpc_error_add_child(error, error_list[i]); @@ -378,9 +279,9 @@ grpc_error* XdsBootstrap::ParseChannelCreds(Json* json, size_t idx, return error; } -grpc_error* XdsBootstrap::ParseServerFeaturesArray(Json* json, - XdsServer* server) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseServerFeaturesArray(Json* json, + XdsServer* server) { + std::vector error_list; for (size_t i = 0; i < json->mutable_array()->size(); ++i) { Json& child = json->mutable_array()->at(i); if (child.type() == Json::Type::STRING && @@ -392,8 +293,8 @@ grpc_error* XdsBootstrap::ParseServerFeaturesArray(Json* json, "errors parsing \"server_features\" array", &error_list); } -grpc_error* XdsBootstrap::ParseNode(Json* json) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseNode(Json* json) { + std::vector error_list; node_ = absl::make_unique(); auto it = json->mutable_object()->find("id"); if (it != json->mutable_object()->end()) { @@ -419,7 +320,7 @@ grpc_error* XdsBootstrap::ParseNode(Json* json) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"locality\" field is not an object")); } else { - grpc_error* parse_error = ParseLocality(&it->second); + grpc_error_handle parse_error = ParseLocality(&it->second); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } @@ -436,8 +337,8 @@ grpc_error* XdsBootstrap::ParseNode(Json* json) { &error_list); } -grpc_error* XdsBootstrap::ParseLocality(Json* json) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseLocality(Json* json) { + std::vector error_list; auto it = json->mutable_object()->find("region"); if (it != json->mutable_object()->end()) { if (it->second.type() != Json::Type::STRING) { @@ -469,8 +370,8 @@ grpc_error* XdsBootstrap::ParseLocality(Json* json) { &error_list); } -grpc_error* XdsBootstrap::ParseCertificateProviders(Json* json) { - std::vector error_list; +grpc_error_handle XdsBootstrap::ParseCertificateProviders(Json* json) { + std::vector error_list; for (auto& certificate_provider : *(json->mutable_object())) { if (certificate_provider.second.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -478,7 +379,7 @@ grpc_error* XdsBootstrap::ParseCertificateProviders(Json* json) { "\" is not an object") .c_str())); } else { - grpc_error* parse_error = ParseCertificateProvider( + grpc_error_handle parse_error = ParseCertificateProvider( certificate_provider.first, &certificate_provider.second); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } @@ -487,9 +388,9 @@ grpc_error* XdsBootstrap::ParseCertificateProviders(Json* json) { "errors parsing \"certificate_providers\" object", &error_list); } -grpc_error* XdsBootstrap::ParseCertificateProvider( +grpc_error_handle XdsBootstrap::ParseCertificateProvider( const std::string& instance_name, Json* certificate_provider_json) { - std::vector error_list; + std::vector error_list; auto it = certificate_provider_json->mutable_object()->find("plugin_name"); if (it == certificate_provider_json->mutable_object()->end()) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -510,14 +411,14 @@ grpc_error* XdsBootstrap::ParseCertificateProvider( error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"config\" field is not an object")); } else { - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; config = factory->CreateCertificateProviderConfig(it->second, &parse_error); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } else { // "config" is an optional field, so create an empty JSON object. - grpc_error* parse_error = GRPC_ERROR_NONE; + grpc_error_handle parse_error = GRPC_ERROR_NONE; config = factory->CreateCertificateProviderConfig(Json::Object(), &parse_error); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); @@ -529,7 +430,7 @@ grpc_error* XdsBootstrap::ParseCertificateProvider( // Can't use GRPC_ERROR_CREATE_FROM_VECTOR() here, because the error // string is not static in this case. if (error_list.empty()) return GRPC_ERROR_NONE; - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("errors parsing element \"", instance_name, "\"").c_str()); for (size_t i = 0; i < error_list.size(); ++i) { error = grpc_error_add_child(error, error_list[i]); @@ -537,4 +438,56 @@ grpc_error* XdsBootstrap::ParseCertificateProvider( return error; } +std::string XdsBootstrap::ToString() const { + std::vector parts; + if (node_ != nullptr) { + parts.push_back(absl::StrFormat( + "node={\n" + " id=\"%s\",\n" + " cluster=\"%s\",\n" + " locality={\n" + " region=\"%s\",\n" + " zone=\"%s\",\n" + " sub_zone=\"%s\"\n" + " },\n" + " metadata=%s,\n" + "},\n", + node_->id, node_->cluster, node_->locality_region, node_->locality_zone, + node_->locality_sub_zone, node_->metadata.Dump())); + } + parts.push_back( + absl::StrFormat("servers=[\n" + " {\n" + " uri=\"%s\",\n" + " creds_type=%s,\n", + server().server_uri, server().channel_creds_type)); + if (server().channel_creds_config.type() != Json::Type::JSON_NULL) { + parts.push_back(absl::StrFormat(" creds_config=%s,", + server().channel_creds_config.Dump())); + } + if (!server().server_features.empty()) { + parts.push_back(absl::StrCat(" server_features=[", + absl::StrJoin(server().server_features, ", "), + "],\n")); + } + parts.push_back(" }\n],\n"); + if (!server_listener_resource_name_template_.empty()) { + parts.push_back( + absl::StrFormat("server_listener_resource_name_template=\"%s\",\n", + server_listener_resource_name_template_)); + } + parts.push_back("certificate_providers={\n"); + for (const auto& entry : certificate_providers_) { + parts.push_back( + absl::StrFormat(" %s={\n" + " plugin_name=%s\n" + " config=%s\n" + " },\n", + entry.first, entry.second.plugin_name, + entry.second.config->ToString())); + } + parts.push_back("}"); + return absl::StrJoin(parts, ""); +} + } // namespace grpc_core diff --git a/src/core/ext/xds/xds_bootstrap.h b/src/core/ext/xds/xds_bootstrap.h index 7eeb5ad01cd..eff5e7abd1e 100644 --- a/src/core/ext/xds/xds_bootstrap.h +++ b/src/core/ext/xds/xds_bootstrap.h @@ -67,27 +67,24 @@ class XdsBootstrap { bool ShouldUseV3() const; }; - // Creates bootstrap object, obtaining the bootstrap JSON as appropriate - // for the environment: - // - If the GRPC_XDS_BOOTSTRAP env var is set, reads the file it specifies - // to obtain the bootstrap JSON. - // - Otherwise, if the GRPC_XDS_BOOTSTRAP_CONFIG env var is set, reads the - // content of that env var to obtain the bootstrap JSON. - // - Otherwise, the JSON will be read from fallback_config (if non-null). + // Creates bootstrap object from json_string. // If *error is not GRPC_ERROR_NONE after returning, then there was an - // error (e.g., no config found or error reading the file). - static std::unique_ptr Create(XdsClient* client, - TraceFlag* tracer, - const char* fallback_config, - grpc_error** error); + // error parsing the contents. + static std::unique_ptr Create(absl::string_view json_string, + grpc_error_handle* error); - // Do not instantiate directly -- use ReadFromFile() above instead. - XdsBootstrap(Json json, grpc_error** error); + // Do not instantiate directly -- use Create() above instead. + XdsBootstrap(Json json, grpc_error_handle* error); + + std::string ToString() const; // TODO(roth): We currently support only one server. Fix this when we // add support for fallback for the xds channel. const XdsServer& server() const { return servers_[0]; } const Node* node() const { return node_.get(); } + const std::string& server_listener_resource_name_template() const { + return server_listener_resource_name_template_; + } const CertificateProviderStore::PluginDefinitionMap& certificate_providers() const { @@ -95,19 +92,21 @@ class XdsBootstrap { } private: - grpc_error* ParseXdsServerList(Json* json); - grpc_error* ParseXdsServer(Json* json, size_t idx); - grpc_error* ParseChannelCredsArray(Json* json, XdsServer* server); - grpc_error* ParseChannelCreds(Json* json, size_t idx, XdsServer* server); - grpc_error* ParseServerFeaturesArray(Json* json, XdsServer* server); - grpc_error* ParseNode(Json* json); - grpc_error* ParseLocality(Json* json); - grpc_error* ParseCertificateProviders(Json* json); - grpc_error* ParseCertificateProvider(const std::string& instance_name, - Json* certificate_provider_json); + grpc_error_handle ParseXdsServerList(Json* json); + grpc_error_handle ParseXdsServer(Json* json, size_t idx); + grpc_error_handle ParseChannelCredsArray(Json* json, XdsServer* server); + grpc_error_handle ParseChannelCreds(Json* json, size_t idx, + XdsServer* server); + grpc_error_handle ParseServerFeaturesArray(Json* json, XdsServer* server); + grpc_error_handle ParseNode(Json* json); + grpc_error_handle ParseLocality(Json* json); + grpc_error_handle ParseCertificateProviders(Json* json); + grpc_error_handle ParseCertificateProvider(const std::string& instance_name, + Json* certificate_provider_json); absl::InlinedVector servers_; std::unique_ptr node_; + std::string server_listener_resource_name_template_; CertificateProviderStore::PluginDefinitionMap certificate_providers_; }; diff --git a/src/core/ext/xds/xds_certificate_provider.cc b/src/core/ext/xds/xds_certificate_provider.cc index 7e84d5f9662..ce1ba673634 100644 --- a/src/core/ext/xds/xds_certificate_provider.cc +++ b/src/core/ext/xds/xds_certificate_provider.cc @@ -51,8 +51,8 @@ class RootCertificatesWatcher } } - void OnError(grpc_error* root_cert_error, - grpc_error* identity_cert_error) override { + void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) override { if (root_cert_error != GRPC_ERROR_NONE) { parent_->SetErrorForCert(cert_name_, root_cert_error /* pass the ref */, absl::nullopt); @@ -86,8 +86,8 @@ class IdentityCertificatesWatcher } } - void OnError(grpc_error* root_cert_error, - grpc_error* identity_cert_error) override { + void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) override { if (identity_cert_error != GRPC_ERROR_NONE) { parent_->SetErrorForCert(cert_name_, absl::nullopt, identity_cert_error /* pass the ref */); diff --git a/src/core/ext/xds/xds_certificate_provider.h b/src/core/ext/xds/xds_certificate_provider.h index 6b190cad53c..2f508830f76 100644 --- a/src/core/ext/xds/xds_certificate_provider.h +++ b/src/core/ext/xds/xds_certificate_provider.h @@ -127,9 +127,11 @@ class XdsCertificateProvider : public grpc_tls_certificate_provider { void WatchStatusCallback(std::string cert_name, bool root_being_watched, bool identity_being_watched); + RefCountedPtr distributor_; + Mutex mu_; std::map> - certificate_state_map_; + certificate_state_map_ ABSL_GUARDED_BY(mu_); // Use a separate mutex for san_matchers_ to avoid deadlocks since // san_matchers_ needs to be accessed when a handshake is being done and we @@ -141,9 +143,7 @@ class XdsCertificateProvider : public grpc_tls_certificate_provider { // subject_alternative_names_matchers() Mutex san_matchers_mu_; std::map> - san_matcher_map_; - - RefCountedPtr distributor_; + san_matcher_map_ ABSL_GUARDED_BY(san_matchers_mu_); }; } // namespace grpc_core diff --git a/src/core/ext/xds/xds_channel_args.h b/src/core/ext/xds/xds_channel_args.h index a258940361d..ea6c862b497 100644 --- a/src/core/ext/xds/xds_channel_args.h +++ b/src/core/ext/xds/xds_channel_args.h @@ -17,8 +17,11 @@ #ifndef GRPC_CORE_EXT_XDS_XDS_CHANNEL_ARGS_H #define GRPC_CORE_EXT_XDS_XDS_CHANNEL_ARGS_H -// Pointer channel arg containing a ref to the XdsClient object. -#define GRPC_ARG_XDS_CLIENT "grpc.xds_client" +// Specifies channel args for the xDS client. +// Used only when GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG +// is set. +#define GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS \ + "grpc.xds_client_channel_args" // Timeout in milliseconds to wait for a resource to be returned from // the xds server before assuming that it does not exist. diff --git a/src/core/ext/xds/xds_client.cc b/src/core/ext/xds/xds_client.cc index fddf9f201b2..d3549997e9d 100644 --- a/src/core/ext/xds/xds_client.cc +++ b/src/core/ext/xds/xds_client.cc @@ -1,20 +1,18 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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. - * - */ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// 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 @@ -35,20 +33,22 @@ #include "src/core/ext/filters/client_channel/client_channel.h" #include "src/core/ext/filters/client_channel/service_config.h" #include "src/core/ext/xds/xds_api.h" +#include "src/core/ext/xds/xds_bootstrap.h" #include "src/core/ext/xds/xds_channel_args.h" #include "src/core/ext/xds/xds_client.h" #include "src/core/ext/xds/xds_client_stats.h" #include "src/core/ext/xds/xds_http_filters.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" @@ -71,9 +71,9 @@ TraceFlag grpc_xds_client_refcount_trace(false, "xds_client_refcount"); namespace { Mutex* g_mu = nullptr; -const grpc_channel_args* g_channel_args = nullptr; -XdsClient* g_xds_client = nullptr; -char* g_fallback_bootstrap_config = nullptr; +const grpc_channel_args* g_channel_args ABSL_GUARDED_BY(*g_mu) = nullptr; +XdsClient* g_xds_client ABSL_GUARDED_BY(*g_mu) = nullptr; +char* g_fallback_bootstrap_config ABSL_GUARDED_BY(*g_mu) = nullptr; } // namespace @@ -101,8 +101,8 @@ class XdsClient::ChannelState::RetryableCall private: void StartNewCallLocked(); void StartRetryTimerLocked(); - static void OnRetryTimer(void* arg, grpc_error* error); - void OnRetryTimerLocked(grpc_error* error); + static void OnRetryTimer(void* arg, grpc_error_handle error); + void OnRetryTimerLocked(grpc_error_handle error); // The wrapped xds call that talks to the xds server. It's instantiated // every time we start a new call. It's null during call retry backoff. @@ -134,9 +134,11 @@ class XdsClient::ChannelState::AdsCallState XdsClient* xds_client() const { return chand()->xds_client(); } bool seen_response() const { return seen_response_; } - void Subscribe(const std::string& type_url, const std::string& name); - void Unsubscribe(const std::string& type_url, const std::string& name, - bool delay_unsubscription); + void SubscribeLocked(const std::string& type_url, const std::string& name) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + void UnsubscribeLocked(const std::string& type_url, const std::string& name, + bool delay_unsubscription) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); bool HasSubscribedResources() const; @@ -177,7 +179,7 @@ class XdsClient::ChannelState::AdsCallState } private: - static void OnTimer(void* arg, grpc_error* error) { + static void OnTimer(void* arg, grpc_error_handle error) { ResourceState* self = static_cast(arg); { MutexLock lock(&self->ads_calld_->xds_client()->mu_); @@ -187,36 +189,43 @@ class XdsClient::ChannelState::AdsCallState self->Unref(DEBUG_LOCATION, "timer"); } - void OnTimerLocked(grpc_error* error) { + void OnTimerLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_) { if (error == GRPC_ERROR_NONE && timer_pending_) { timer_pending_ = false; - grpc_error* watcher_error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle watcher_error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrFormat( "timeout obtaining resource {type=%s name=%s} from xds server", type_url_, name_) .c_str()); + watcher_error = grpc_error_set_int( + watcher_error, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, "[xds_client %p] %s", ads_calld_->xds_client(), - grpc_error_string(watcher_error)); + grpc_error_std_string(watcher_error).c_str()); } if (type_url_ == XdsApi::kLdsTypeUrl) { ListenerState& state = ads_calld_->xds_client()->listener_map_[name_]; + state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; for (const auto& p : state.watchers) { p.first->OnError(GRPC_ERROR_REF(watcher_error)); } } else if (type_url_ == XdsApi::kRdsTypeUrl) { RouteConfigState& state = ads_calld_->xds_client()->route_config_map_[name_]; + state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; for (const auto& p : state.watchers) { p.first->OnError(GRPC_ERROR_REF(watcher_error)); } } else if (type_url_ == XdsApi::kCdsTypeUrl) { ClusterState& state = ads_calld_->xds_client()->cluster_map_[name_]; + state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; for (const auto& p : state.watchers) { p.first->OnError(GRPC_ERROR_REF(watcher_error)); } } else if (type_url_ == XdsApi::kEdsTypeUrl) { EndpointState& state = ads_calld_->xds_client()->endpoint_map_[name_]; + state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; for (const auto& p : state.watchers) { p.first->OnError(GRPC_ERROR_REF(watcher_error)); } @@ -243,26 +252,38 @@ class XdsClient::ChannelState::AdsCallState // Nonce and error for this resource type. std::string nonce; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; // Subscribed resources of this type. std::map> subscribed_resources; }; - void SendMessageLocked(const std::string& type_url); - - void AcceptLdsUpdate(XdsApi::LdsUpdateMap lds_update_map); - void AcceptRdsUpdate(XdsApi::RdsUpdateMap rds_update_map); - void AcceptCdsUpdate(XdsApi::CdsUpdateMap cds_update_map); - void AcceptEdsUpdate(XdsApi::EdsUpdateMap eds_update_map); - - static void OnRequestSent(void* arg, grpc_error* error); - void OnRequestSentLocked(grpc_error* error); - static void OnResponseReceived(void* arg, grpc_error* error); - bool OnResponseReceivedLocked(); - static void OnStatusReceived(void* arg, grpc_error* error); - void OnStatusReceivedLocked(grpc_error* error); + void SendMessageLocked(const std::string& type_url) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + + void AcceptLdsUpdateLocked(std::string version, grpc_millis update_time, + XdsApi::LdsUpdateMap lds_update_map) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + void AcceptRdsUpdateLocked(std::string version, grpc_millis update_time, + XdsApi::RdsUpdateMap rds_update_map) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + void AcceptCdsUpdateLocked(std::string version, grpc_millis update_time, + XdsApi::CdsUpdateMap cds_update_map) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + void AcceptEdsUpdateLocked(std::string version, grpc_millis update_time, + XdsApi::EdsUpdateMap eds_update_map) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + + static void OnRequestSent(void* arg, grpc_error_handle error); + void OnRequestSentLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + static void OnResponseReceived(void* arg, grpc_error_handle error); + bool OnResponseReceivedLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + static void OnStatusReceived(void* arg, grpc_error_handle error); + void OnStatusReceivedLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); bool IsCurrentCallOnChannel() const; @@ -335,12 +356,15 @@ class XdsClient::ChannelState::LrsCallState void Orphan() override; private: - void ScheduleNextReportLocked(); - static void OnNextReportTimer(void* arg, grpc_error* error); - bool OnNextReportTimerLocked(grpc_error* error); - bool SendReportLocked(); - static void OnReportDone(void* arg, grpc_error* error); - bool OnReportDoneLocked(grpc_error* error); + void ScheduleNextReportLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + static void OnNextReportTimer(void* arg, grpc_error_handle error); + bool OnNextReportTimerLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + bool SendReportLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + static void OnReportDone(void* arg, grpc_error_handle error); + bool OnReportDoneLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); bool IsCurrentReporterOnCall() const { return this == parent_->reporter_.get(); @@ -359,12 +383,15 @@ class XdsClient::ChannelState::LrsCallState grpc_closure on_report_done_; }; - static void OnInitialRequestSent(void* arg, grpc_error* error); - void OnInitialRequestSentLocked(); - static void OnResponseReceived(void* arg, grpc_error* error); - bool OnResponseReceivedLocked(); - static void OnStatusReceived(void* arg, grpc_error* error); - void OnStatusReceivedLocked(grpc_error* error); + static void OnInitialRequestSent(void* arg, grpc_error_handle error); + void OnInitialRequestSentLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + static void OnResponseReceived(void* arg, grpc_error_handle error); + bool OnResponseReceivedLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + static void OnStatusReceived(void* arg, grpc_error_handle error); + void OnStatusReceivedLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); bool IsCurrentCallOnChannel() const; @@ -420,7 +447,7 @@ class XdsClient::ChannelState::StateWatcher "[xds_client %p] xds channel in state:TRANSIENT_FAILURE " "status_message:(%s)", parent_->xds_client(), status.ToString().c_str()); - parent_->xds_client()->NotifyOnErrorLocked( + parent_->xds_client_->NotifyOnErrorLocked( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "xds channel in TRANSIENT_FAILURE")); } @@ -435,26 +462,13 @@ class XdsClient::ChannelState::StateWatcher namespace { -grpc_channel* CreateXdsChannel(const XdsBootstrap::XdsServer& server) { - // Build channel args. - absl::InlinedVector args_to_add = { - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_KEEPALIVE_TIME_MS), - 5 * 60 * GPR_MS_PER_SEC), - grpc_channel_arg_integer_create( - const_cast(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL), 1), - }; - grpc_channel_args* new_args = grpc_channel_args_copy_and_add( - g_channel_args, args_to_add.data(), args_to_add.size()); - // Create channel creds. +grpc_channel* CreateXdsChannel(grpc_channel_args* args, + const XdsBootstrap::XdsServer& server) { RefCountedPtr channel_creds = XdsChannelCredsRegistry::MakeChannelCreds(server.channel_creds_type, server.channel_creds_config); - // Create channel. - grpc_channel* channel = grpc_secure_channel_create( - channel_creds.get(), server.server_uri.c_str(), new_args, nullptr); - grpc_channel_args_destroy(new_args); - return channel; + return grpc_secure_channel_create(channel_creds.get(), + server.server_uri.c_str(), args, nullptr); } } // namespace @@ -471,7 +485,7 @@ XdsClient::ChannelState::ChannelState(WeakRefCountedPtr xds_client, gpr_log(GPR_INFO, "[xds_client %p] creating channel to %s", xds_client_.get(), server.server_uri.c_str()); } - channel_ = CreateXdsChannel(server); + channel_ = CreateXdsChannel(xds_client_->args_, server); GPR_ASSERT(channel_ != nullptr); StartConnectivityWatchLocked(); } @@ -504,7 +518,7 @@ XdsClient::ChannelState::LrsCallState* XdsClient::ChannelState::lrs_calld() } bool XdsClient::ChannelState::HasActiveAdsCall() const { - return ads_calld_->calld() != nullptr; + return ads_calld_ != nullptr && ads_calld_->calld() != nullptr; } void XdsClient::ChannelState::MaybeStartLrsCall() { @@ -516,24 +530,22 @@ void XdsClient::ChannelState::MaybeStartLrsCall() { void XdsClient::ChannelState::StopLrsCall() { lrs_calld_.reset(); } void XdsClient::ChannelState::StartConnectivityWatchLocked() { - grpc_channel_element* client_channel_elem = - grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel_)); - GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter); + ClientChannel* client_channel = ClientChannel::GetFromChannel(channel_); + GPR_ASSERT(client_channel != nullptr); watcher_ = new StateWatcher(Ref(DEBUG_LOCATION, "ChannelState+watch")); - grpc_client_channel_start_connectivity_watch( - client_channel_elem, GRPC_CHANNEL_IDLE, + client_channel->AddConnectivityWatcher( + GRPC_CHANNEL_IDLE, OrphanablePtr(watcher_)); } void XdsClient::ChannelState::CancelConnectivityWatchLocked() { - grpc_channel_element* client_channel_elem = - grpc_channel_stack_last_element(grpc_channel_get_channel_stack(channel_)); - GPR_ASSERT(client_channel_elem->filter == &grpc_client_channel_filter); - grpc_client_channel_stop_connectivity_watch(client_channel_elem, watcher_); + ClientChannel* client_channel = ClientChannel::GetFromChannel(channel_); + GPR_ASSERT(client_channel != nullptr); + client_channel->RemoveConnectivityWatcher(watcher_); } -void XdsClient::ChannelState::Subscribe(const std::string& type_url, - const std::string& name) { +void XdsClient::ChannelState::SubscribeLocked(const std::string& type_url, + const std::string& name) { if (ads_calld_ == nullptr) { // Start the ADS call if this is the first request. ads_calld_.reset(new RetryableCall( @@ -547,16 +559,16 @@ void XdsClient::ChannelState::Subscribe(const std::string& type_url, // because when the call is restarted it will resend all necessary requests. if (ads_calld() == nullptr) return; // Subscribe to this resource if the ADS call is active. - ads_calld()->Subscribe(type_url, name); + ads_calld()->SubscribeLocked(type_url, name); } -void XdsClient::ChannelState::Unsubscribe(const std::string& type_url, - const std::string& name, - bool delay_unsubscription) { +void XdsClient::ChannelState::UnsubscribeLocked(const std::string& type_url, + const std::string& name, + bool delay_unsubscription) { if (ads_calld_ != nullptr) { auto* calld = ads_calld_->calld(); if (calld != nullptr) { - calld->Unsubscribe(type_url, name, delay_unsubscription); + calld->UnsubscribeLocked(type_url, name, delay_unsubscription); if (!calld->HasSubscribedResources()) ads_calld_.reset(); } } @@ -639,7 +651,7 @@ void XdsClient::ChannelState::RetryableCall::StartRetryTimerLocked() { template void XdsClient::ChannelState::RetryableCall::OnRetryTimer( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { RetryableCall* calld = static_cast(arg); { MutexLock lock(&calld->chand_->xds_client()->mu_); @@ -650,7 +662,7 @@ void XdsClient::ChannelState::RetryableCall::OnRetryTimer( template void XdsClient::ChannelState::RetryableCall::OnRetryTimerLocked( - grpc_error* error) { + grpc_error_handle error) { retry_timer_callback_pending_ = false; if (!shutting_down_ && error == GRPC_ERROR_NONE) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { @@ -718,16 +730,16 @@ XdsClient::ChannelState::AdsCallState::AdsCallState( GRPC_CLOSURE_INIT(&on_request_sent_, OnRequestSent, this, grpc_schedule_on_exec_ctx); for (const auto& p : xds_client()->listener_map_) { - Subscribe(XdsApi::kLdsTypeUrl, std::string(p.first)); + SubscribeLocked(XdsApi::kLdsTypeUrl, std::string(p.first)); } for (const auto& p : xds_client()->route_config_map_) { - Subscribe(XdsApi::kRdsTypeUrl, std::string(p.first)); + SubscribeLocked(XdsApi::kRdsTypeUrl, std::string(p.first)); } for (const auto& p : xds_client()->cluster_map_) { - Subscribe(XdsApi::kCdsTypeUrl, std::string(p.first)); + SubscribeLocked(XdsApi::kCdsTypeUrl, std::string(p.first)); } for (const auto& p : xds_client()->endpoint_map_) { - Subscribe(XdsApi::kEdsTypeUrl, std::string(p.first)); + SubscribeLocked(XdsApi::kEdsTypeUrl, std::string(p.first)); } // Op: recv initial metadata. op = ops; @@ -791,7 +803,8 @@ void XdsClient::ChannelState::AdsCallState::Orphan() { } void XdsClient::ChannelState::AdsCallState::SendMessageLocked( - const std::string& type_url) { + const std::string& type_url) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_) { // Buffer message sending if an existing message is in flight. if (send_message_payload_ != nullptr) { buffered_requests_.insert(type_url); @@ -816,7 +829,7 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked( "error=%s resources=%s", xds_client(), type_url.c_str(), xds_client()->resource_version_map_[type_url].c_str(), - state.nonce.c_str(), grpc_error_string(state.error), + state.nonce.c_str(), grpc_error_std_string(state.error).c_str(), absl::StrJoin(resource_names, " ").c_str()); } GRPC_ERROR_UNREF(state.error); @@ -843,7 +856,7 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked( } } -void XdsClient::ChannelState::AdsCallState::Subscribe( +void XdsClient::ChannelState::AdsCallState::SubscribeLocked( const std::string& type_url, const std::string& name) { auto& state = state_map_[type_url].subscribed_resources[name]; if (state == nullptr) { @@ -853,7 +866,7 @@ void XdsClient::ChannelState::AdsCallState::Subscribe( } } -void XdsClient::ChannelState::AdsCallState::Unsubscribe( +void XdsClient::ChannelState::AdsCallState::UnsubscribeLocked( const std::string& type_url, const std::string& name, bool delay_unsubscription) { state_map_[type_url].subscribed_resources.erase(name); @@ -867,7 +880,24 @@ bool XdsClient::ChannelState::AdsCallState::HasSubscribedResources() const { return false; } -void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate( +namespace { + +// Build a resource metadata struct for ADS result accepting methods and CSDS. +XdsApi::ResourceMetadata CreateResourceMetadataAcked( + std::string serialized_proto, std::string version, + grpc_millis update_time) { + XdsApi::ResourceMetadata resource_metadata; + resource_metadata.serialized_proto = std::move(serialized_proto); + resource_metadata.update_time = update_time; + resource_metadata.version = std::move(version); + resource_metadata.client_status = XdsApi::ResourceMetadata::ACKED; + return resource_metadata; +} + +} // namespace + +void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdateLocked( + std::string version, grpc_millis update_time, XdsApi::LdsUpdateMap lds_update_map) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, @@ -879,7 +909,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate( std::set rds_resource_names_seen; for (auto& p : lds_update_map) { const std::string& listener_name = p.first; - XdsApi::LdsUpdate& lds_update = p.second; + XdsApi::LdsUpdate& lds_update = p.second.resource; auto& state = lds_state.subscribed_resources[listener_name]; if (state != nullptr) state->Finish(); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { @@ -887,8 +917,9 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate( listener_name.c_str(), lds_update.ToString().c_str()); } // Record the RDS resource names seen. - if (!lds_update.route_config_name.empty()) { - rds_resource_names_seen.insert(lds_update.route_config_name); + if (!lds_update.http_connection_manager.route_config_name.empty()) { + rds_resource_names_seen.insert( + lds_update.http_connection_manager.route_config_name); } // Ignore identical update. ListenerState& listener_state = xds_client()->listener_map_[listener_name]; @@ -904,6 +935,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate( } // Update the listener state. listener_state.update = std::move(lds_update); + listener_state.meta = CreateResourceMetadataAcked( + std::move(p.second.serialized_proto), version, update_time); // Notify watchers. for (const auto& p : listener_state.watchers) { p.first->OnListenerChanged(*listener_state.update); @@ -947,7 +980,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptLdsUpdate( } } -void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate( +void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdateLocked( + std::string version, grpc_millis update_time, XdsApi::RdsUpdateMap rds_update_map) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, @@ -958,7 +992,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate( auto& rds_state = state_map_[XdsApi::kRdsTypeUrl]; for (auto& p : rds_update_map) { const std::string& route_config_name = p.first; - XdsApi::RdsUpdate& rds_update = p.second; + XdsApi::RdsUpdate& rds_update = p.second.resource; auto& state = rds_state.subscribed_resources[route_config_name]; if (state != nullptr) state->Finish(); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { @@ -979,6 +1013,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate( } // Update the cache. route_config_state.update = std::move(rds_update); + route_config_state.meta = CreateResourceMetadataAcked( + std::move(p.second.serialized_proto), version, update_time); // Notify all watchers. for (const auto& p : route_config_state.watchers) { p.first->OnRouteConfigChanged(*route_config_state.update); @@ -986,7 +1022,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdate( } } -void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate( +void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdateLocked( + std::string version, grpc_millis update_time, XdsApi::CdsUpdateMap cds_update_map) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, @@ -998,7 +1035,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate( std::set eds_resource_names_seen; for (auto& p : cds_update_map) { const char* cluster_name = p.first.c_str(); - XdsApi::CdsUpdate& cds_update = p.second; + XdsApi::CdsUpdate& cds_update = p.second.resource; auto& state = cds_state.subscribed_resources[cluster_name]; if (state != nullptr) state->Finish(); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { @@ -1022,6 +1059,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate( } // Update the cluster state. cluster_state.update = std::move(cds_update); + cluster_state.meta = CreateResourceMetadataAcked( + std::move(p.second.serialized_proto), version, update_time); // Notify all watchers. for (const auto& p : cluster_state.watchers) { p.first->OnClusterChanged(cluster_state.update.value()); @@ -1064,7 +1103,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdate( } } -void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate( +void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdateLocked( + std::string version, grpc_millis update_time, XdsApi::EdsUpdateMap eds_update_map) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, @@ -1075,7 +1115,7 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate( auto& eds_state = state_map_[XdsApi::kEdsTypeUrl]; for (auto& p : eds_update_map) { const char* eds_service_name = p.first.c_str(); - XdsApi::EdsUpdate& eds_update = p.second; + XdsApi::EdsUpdate& eds_update = p.second.resource; auto& state = eds_state.subscribed_resources[eds_service_name]; if (state != nullptr) state->Finish(); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { @@ -1096,6 +1136,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate( } // Update the cluster state. endpoint_state.update = std::move(eds_update); + endpoint_state.meta = CreateResourceMetadataAcked( + std::move(p.second.serialized_proto), version, update_time); // Notify all watchers. for (const auto& p : endpoint_state.watchers) { p.first->OnEndpointChanged(endpoint_state.update.value()); @@ -1103,8 +1145,8 @@ void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdate( } } -void XdsClient::ChannelState::AdsCallState::OnRequestSent(void* arg, - grpc_error* error) { +void XdsClient::ChannelState::AdsCallState::OnRequestSent( + void* arg, grpc_error_handle error) { AdsCallState* ads_calld = static_cast(arg); { MutexLock lock(&ads_calld->xds_client()->mu_); @@ -1114,7 +1156,7 @@ void XdsClient::ChannelState::AdsCallState::OnRequestSent(void* arg, } void XdsClient::ChannelState::AdsCallState::OnRequestSentLocked( - grpc_error* error) { + grpc_error_handle error) { if (IsCurrentCallOnChannel() && error == GRPC_ERROR_NONE) { // Clean up the sent message. grpc_byte_buffer_destroy(send_message_payload_); @@ -1138,7 +1180,7 @@ void XdsClient::ChannelState::AdsCallState::OnRequestSentLocked( } void XdsClient::ChannelState::AdsCallState::OnResponseReceived( - void* arg, grpc_error* /* error */) { + void* arg, grpc_error_handle /* error */) { AdsCallState* ads_calld = static_cast(arg); bool done; { @@ -1172,14 +1214,17 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() { // Ignore unparsable response. gpr_log(GPR_ERROR, "[xds_client %p] Error parsing ADS response (%s) -- ignoring", - xds_client(), grpc_error_string(result.parse_error)); + xds_client(), grpc_error_std_string(result.parse_error).c_str()); GRPC_ERROR_UNREF(result.parse_error); } else { + grpc_millis update_time = grpc_core::ExecCtx::Get()->Now(); // Update nonce. auto& state = state_map_[result.type_url]; state.nonce = std::move(result.nonce); // NACK or ACK the response. if (result.parse_error != GRPC_ERROR_NONE) { + xds_client()->UpdateResourceMetadataWithFailedParseResultLocked( + update_time, result); GRPC_ERROR_UNREF(state.error); state.error = result.parse_error; // NACK unacceptable update. @@ -1187,19 +1232,24 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() { "[xds_client %p] ADS response invalid for resource type %s " "version %s, will NACK: nonce=%s error=%s", xds_client(), result.type_url.c_str(), result.version.c_str(), - state.nonce.c_str(), grpc_error_string(result.parse_error)); + state.nonce.c_str(), + grpc_error_std_string(result.parse_error).c_str()); SendMessageLocked(result.type_url); } else { seen_response_ = true; // Accept the ADS response according to the type_url. if (result.type_url == XdsApi::kLdsTypeUrl) { - AcceptLdsUpdate(std::move(result.lds_update_map)); + AcceptLdsUpdateLocked(result.version, update_time, + std::move(result.lds_update_map)); } else if (result.type_url == XdsApi::kRdsTypeUrl) { - AcceptRdsUpdate(std::move(result.rds_update_map)); + AcceptRdsUpdateLocked(result.version, update_time, + std::move(result.rds_update_map)); } else if (result.type_url == XdsApi::kCdsTypeUrl) { - AcceptCdsUpdate(std::move(result.cds_update_map)); + AcceptCdsUpdateLocked(result.version, update_time, + std::move(result.cds_update_map)); } else if (result.type_url == XdsApi::kEdsTypeUrl) { - AcceptEdsUpdate(std::move(result.eds_update_map)); + AcceptEdsUpdateLocked(result.version, update_time, + std::move(result.eds_update_map)); } xds_client()->resource_version_map_[result.type_url] = std::move(result.version); @@ -1230,7 +1280,7 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() { } void XdsClient::ChannelState::AdsCallState::OnStatusReceived( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { AdsCallState* ads_calld = static_cast(arg); { MutexLock lock(&ads_calld->xds_client()->mu_); @@ -1240,14 +1290,14 @@ void XdsClient::ChannelState::AdsCallState::OnStatusReceived( } void XdsClient::ChannelState::AdsCallState::OnStatusReceivedLocked( - grpc_error* error) { + grpc_error_handle error) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { char* status_details = grpc_slice_to_c_string(status_details_); gpr_log(GPR_INFO, "[xds_client %p] ADS call status received. Status = %d, details " "= '%s', (chand: %p, ads_calld: %p, call: %p), error '%s'", xds_client(), status_code_, status_details, chand(), this, call_, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); gpr_free(status_details); } // Ignore status from a stale call. @@ -1302,7 +1352,7 @@ void XdsClient::ChannelState::LrsCallState::Reporter:: } void XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimer( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { Reporter* self = static_cast(arg); bool done; { @@ -1313,7 +1363,7 @@ void XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimer( } bool XdsClient::ChannelState::LrsCallState::Reporter::OnNextReportTimerLocked( - grpc_error* error) { + grpc_error_handle error) { next_report_timer_callback_pending_ = false; if (error != GRPC_ERROR_NONE || !IsCurrentReporterOnCall()) { GRPC_ERROR_UNREF(error); @@ -1378,7 +1428,7 @@ bool XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() { } void XdsClient::ChannelState::LrsCallState::Reporter::OnReportDone( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { Reporter* self = static_cast(arg); bool done; { @@ -1389,7 +1439,7 @@ void XdsClient::ChannelState::LrsCallState::Reporter::OnReportDone( } bool XdsClient::ChannelState::LrsCallState::Reporter::OnReportDoneLocked( - grpc_error* error) { + grpc_error_handle error) { grpc_byte_buffer_destroy(parent_->send_message_payload_); parent_->send_message_payload_ = nullptr; // If there are no more registered stats to report, cancel the call. @@ -1559,7 +1609,7 @@ void XdsClient::ChannelState::LrsCallState::MaybeStartReportingLocked() { } void XdsClient::ChannelState::LrsCallState::OnInitialRequestSent( - void* arg, grpc_error* /*error*/) { + void* arg, grpc_error_handle /*error*/) { LrsCallState* lrs_calld = static_cast(arg); { MutexLock lock(&lrs_calld->xds_client()->mu_); @@ -1576,7 +1626,7 @@ void XdsClient::ChannelState::LrsCallState::OnInitialRequestSentLocked() { } void XdsClient::ChannelState::LrsCallState::OnResponseReceived( - void* arg, grpc_error* /*error*/) { + void* arg, grpc_error_handle /*error*/) { LrsCallState* lrs_calld = static_cast(arg); bool done; { @@ -1604,13 +1654,13 @@ bool XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() { bool send_all_clusters = false; std::set new_cluster_names; grpc_millis new_load_reporting_interval; - grpc_error* parse_error = xds_client()->api_.ParseLrsResponse( + grpc_error_handle parse_error = xds_client()->api_.ParseLrsResponse( response_slice, &send_all_clusters, &new_cluster_names, &new_load_reporting_interval); if (parse_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "[xds_client %p] LRS response parsing failed. error=%s", - xds_client(), grpc_error_string(parse_error)); + xds_client(), grpc_error_std_string(parse_error).c_str()); GRPC_ERROR_UNREF(parse_error); return; } @@ -1679,7 +1729,7 @@ bool XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() { } void XdsClient::ChannelState::LrsCallState::OnStatusReceived( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { LrsCallState* lrs_calld = static_cast(arg); { MutexLock lock(&lrs_calld->xds_client()->mu_); @@ -1689,7 +1739,7 @@ void XdsClient::ChannelState::LrsCallState::OnStatusReceived( } void XdsClient::ChannelState::LrsCallState::OnStatusReceivedLocked( - grpc_error* error) { + grpc_error_handle error) { GPR_ASSERT(call_ != nullptr); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { char* status_details = grpc_slice_to_c_string(status_details_); @@ -1697,7 +1747,7 @@ void XdsClient::ChannelState::LrsCallState::OnStatusReceivedLocked( "[xds_client %p] LRS call status received. Status = %d, details " "= '%s', (chand: %p, calld: %p, call: %p), error '%s'", xds_client(), status_code_, status_details, chand(), this, call_, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); gpr_free(status_details); } // Ignore status from a stale call. @@ -1722,36 +1772,41 @@ bool XdsClient::ChannelState::LrsCallState::IsCurrentCallOnChannel() const { namespace { -grpc_millis GetRequestTimeout() { +grpc_millis GetRequestTimeout(const grpc_channel_args* args) { return grpc_channel_args_find_integer( - g_channel_args, GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS, + args, GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS, {15000, 0, INT_MAX}); } +grpc_channel_args* ModifyChannelArgs(const grpc_channel_args* args) { + absl::InlinedVector args_to_add = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_KEEPALIVE_TIME_MS), + 5 * 60 * GPR_MS_PER_SEC), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL), 1), + }; + return grpc_channel_args_copy_and_add(args, args_to_add.data(), + args_to_add.size()); +} + } // namespace -XdsClient::XdsClient(grpc_error** error) +XdsClient::XdsClient(std::unique_ptr bootstrap, + const grpc_channel_args* args) : DualRefCounted( GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_refcount_trace) ? "XdsClient" : nullptr), - request_timeout_(GetRequestTimeout()), + bootstrap_(std::move(bootstrap)), + args_(ModifyChannelArgs(args)), + request_timeout_(GetRequestTimeout(args)), interested_parties_(grpc_pollset_set_create()), - bootstrap_(XdsBootstrap::Create(this, &grpc_xds_client_trace, - g_fallback_bootstrap_config, error)), certificate_provider_store_(MakeOrphanable( - bootstrap_ == nullptr - ? CertificateProviderStore::PluginDefinitionMap() - : bootstrap_->certificate_providers())), - api_(this, &grpc_xds_client_trace, - bootstrap_ == nullptr ? nullptr : bootstrap_->node()) { + bootstrap_->certificate_providers())), + api_(this, &grpc_xds_client_trace, bootstrap_->node()) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, "[xds_client %p] creating xds client", this); } - if (*error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "[xds_client %p] failed to read bootstrap file: %s", - this, grpc_error_string(*error)); - return; - } // Create ChannelState object. chand_ = MakeOrphanable( WeakRef(DEBUG_LOCATION, "XdsClient+ChannelState"), bootstrap_->server()); @@ -1761,11 +1816,13 @@ XdsClient::~XdsClient() { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, "[xds_client %p] destroying xds client", this); } + grpc_channel_args_destroy(args_); grpc_pollset_set_destroy(interested_parties_); } void XdsClient::AddChannelzLinkage( channelz::ChannelNode* parent_channelz_node) { + MutexLock lock(&mu_); channelz::ChannelNode* xds_channelz_node = grpc_channel_get_channelz_node(chand_->channel()); if (xds_channelz_node != nullptr) { @@ -1775,6 +1832,7 @@ void XdsClient::AddChannelzLinkage( void XdsClient::RemoveChannelzLinkage( channelz::ChannelNode* parent_channelz_node) { + MutexLock lock(&mu_); channelz::ChannelNode* xds_channelz_node = grpc_channel_get_channelz_node(chand_->channel()); if (xds_channelz_node != nullptr) { @@ -1825,7 +1883,7 @@ void XdsClient::WatchListenerData( } w->OnListenerChanged(*listener_state.update); } - chand_->Subscribe(XdsApi::kLdsTypeUrl, listener_name_str); + chand_->SubscribeLocked(XdsApi::kLdsTypeUrl, listener_name_str); } void XdsClient::CancelListenerDataWatch(absl::string_view listener_name, @@ -1840,8 +1898,8 @@ void XdsClient::CancelListenerDataWatch(absl::string_view listener_name, listener_state.watchers.erase(it); if (listener_state.watchers.empty()) { listener_map_.erase(listener_name_str); - chand_->Unsubscribe(XdsApi::kLdsTypeUrl, listener_name_str, - delay_unsubscription); + chand_->UnsubscribeLocked(XdsApi::kLdsTypeUrl, listener_name_str, + delay_unsubscription); } } } @@ -1865,7 +1923,7 @@ void XdsClient::WatchRouteConfigData( } w->OnRouteConfigChanged(*route_config_state.update); } - chand_->Subscribe(XdsApi::kRdsTypeUrl, route_config_name_str); + chand_->SubscribeLocked(XdsApi::kRdsTypeUrl, route_config_name_str); } void XdsClient::CancelRouteConfigDataWatch(absl::string_view route_config_name, @@ -1881,8 +1939,8 @@ void XdsClient::CancelRouteConfigDataWatch(absl::string_view route_config_name, route_config_state.watchers.erase(it); if (route_config_state.watchers.empty()) { route_config_map_.erase(route_config_name_str); - chand_->Unsubscribe(XdsApi::kRdsTypeUrl, route_config_name_str, - delay_unsubscription); + chand_->UnsubscribeLocked(XdsApi::kRdsTypeUrl, route_config_name_str, + delay_unsubscription); } } } @@ -1904,7 +1962,7 @@ void XdsClient::WatchClusterData( } w->OnClusterChanged(cluster_state.update.value()); } - chand_->Subscribe(XdsApi::kCdsTypeUrl, cluster_name_str); + chand_->SubscribeLocked(XdsApi::kCdsTypeUrl, cluster_name_str); } void XdsClient::CancelClusterDataWatch(absl::string_view cluster_name, @@ -1919,8 +1977,8 @@ void XdsClient::CancelClusterDataWatch(absl::string_view cluster_name, cluster_state.watchers.erase(it); if (cluster_state.watchers.empty()) { cluster_map_.erase(cluster_name_str); - chand_->Unsubscribe(XdsApi::kCdsTypeUrl, cluster_name_str, - delay_unsubscription); + chand_->UnsubscribeLocked(XdsApi::kCdsTypeUrl, cluster_name_str, + delay_unsubscription); } } } @@ -1942,7 +2000,7 @@ void XdsClient::WatchEndpointData( } w->OnEndpointChanged(endpoint_state.update.value()); } - chand_->Subscribe(XdsApi::kEdsTypeUrl, eds_service_name_str); + chand_->SubscribeLocked(XdsApi::kEdsTypeUrl, eds_service_name_str); } void XdsClient::CancelEndpointDataWatch(absl::string_view eds_service_name, @@ -1957,8 +2015,8 @@ void XdsClient::CancelEndpointDataWatch(absl::string_view eds_service_name, endpoint_state.watchers.erase(it); if (endpoint_state.watchers.empty()) { endpoint_map_.erase(eds_service_name_str); - chand_->Unsubscribe(XdsApi::kEdsTypeUrl, eds_service_name_str, - delay_unsubscription); + chand_->UnsubscribeLocked(XdsApi::kEdsTypeUrl, eds_service_name_str, + delay_unsubscription); } } } @@ -2085,7 +2143,7 @@ void XdsClient::ResetBackoff() { } } -void XdsClient::NotifyOnErrorLocked(grpc_error* error) { +void XdsClient::NotifyOnErrorLocked(grpc_error_handle error) { for (const auto& p : listener_map_) { const ListenerState& listener_state = p.second; for (const auto& p : listener_state.watchers) { @@ -2194,6 +2252,80 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshotLocked( return snapshot_map; } +void XdsClient::UpdateResourceMetadataWithFailedParseResultLocked( + grpc_millis update_time, const XdsApi::AdsParseResult& result) { + // ADS update is rejected and the resource names in the failed update is + // available. + std::string details = grpc_error_std_string(result.parse_error); + for (auto& name : result.resource_names_failed) { + XdsApi::ResourceMetadata* resource_metadata = nullptr; + if (result.type_url == XdsApi::kLdsTypeUrl) { + auto it = listener_map_.find(name); + if (it != listener_map_.end()) { + resource_metadata = &it->second.meta; + } + } else if (result.type_url == XdsApi::kRdsTypeUrl) { + auto it = route_config_map_.find(name); + if (route_config_map_.find(name) != route_config_map_.end()) { + resource_metadata = &it->second.meta; + } + } else if (result.type_url == XdsApi::kCdsTypeUrl) { + auto it = cluster_map_.find(name); + if (cluster_map_.find(name) != cluster_map_.end()) { + resource_metadata = &it->second.meta; + } + } else if (result.type_url == XdsApi::kEdsTypeUrl) { + auto it = endpoint_map_.find(name); + if (endpoint_map_.find(name) != endpoint_map_.end()) { + resource_metadata = &it->second.meta; + } + } + if (resource_metadata == nullptr) { + return; + } + resource_metadata->client_status = XdsApi::ResourceMetadata::NACKED; + resource_metadata->failed_version = result.version; + resource_metadata->failed_details = details; + resource_metadata->failed_update_time = update_time; + } +} + +std::string XdsClient::DumpClientConfigBinary() { + MutexLock lock(&mu_); + XdsApi::ResourceTypeMetadataMap resource_type_metadata_map; + // Update per-xds-type version if available, this version corresponding to the + // last successful ADS update version. + for (auto& p : resource_version_map_) { + resource_type_metadata_map[p.first].version = p.second; + } + // Collect resource metadata from listeners + auto& lds_map = + resource_type_metadata_map[XdsApi::kLdsTypeUrl].resource_metadata_map; + for (auto& p : listener_map_) { + lds_map[p.first] = &p.second.meta; + } + // Collect resource metadata from route configs + auto& rds_map = + resource_type_metadata_map[XdsApi::kRdsTypeUrl].resource_metadata_map; + for (auto& p : route_config_map_) { + rds_map[p.first] = &p.second.meta; + } + // Collect resource metadata from clusters + auto& cds_map = + resource_type_metadata_map[XdsApi::kCdsTypeUrl].resource_metadata_map; + for (auto& p : cluster_map_) { + cds_map[p.first] = &p.second.meta; + } + // Collect resource metadata from endpoints + auto& eds_map = + resource_type_metadata_map[XdsApi::kEdsTypeUrl].resource_metadata_map; + for (auto& p : endpoint_map_) { + eds_map[p.first] = &p.second.meta; + } + // Assemble config dump messages + return api_.AssembleClientConfig(resource_type_metadata_map); +} + // // accessors for global state // @@ -2203,22 +2335,107 @@ void XdsClientGlobalInit() { XdsHttpFilterRegistry::Init(); } -void XdsClientGlobalShutdown() { - delete g_mu; - g_mu = nullptr; +// TODO(roth): Find a better way to clear the fallback config that does +// not require using ABSL_NO_THREAD_SAFETY_ANALYSIS. +void XdsClientGlobalShutdown() ABSL_NO_THREAD_SAFETY_ANALYSIS { gpr_free(g_fallback_bootstrap_config); g_fallback_bootstrap_config = nullptr; + delete g_mu; + g_mu = nullptr; XdsHttpFilterRegistry::Shutdown(); } -RefCountedPtr XdsClient::GetOrCreate(grpc_error** error) { - MutexLock lock(g_mu); - if (g_xds_client != nullptr) { - auto xds_client = g_xds_client->RefIfNonZero(); - if (xds_client != nullptr) return xds_client; +namespace { + +std::string GetBootstrapContents(const char* fallback_config, + grpc_error_handle* error) { + // First, try GRPC_XDS_BOOTSTRAP env var. + grpc_core::UniquePtr path(gpr_getenv("GRPC_XDS_BOOTSTRAP")); + if (path != nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { + gpr_log(GPR_INFO, + "Got bootstrap file location from GRPC_XDS_BOOTSTRAP " + "environment variable: %s", + path.get()); + } + grpc_slice contents; + *error = + grpc_load_file(path.get(), /*add_null_terminator=*/true, &contents); + if (*error != GRPC_ERROR_NONE) return ""; + std::string contents_str(StringViewFromSlice(contents)); + grpc_slice_unref_internal(contents); + return contents_str; + } + // Next, try GRPC_XDS_BOOTSTRAP_CONFIG env var. + grpc_core::UniquePtr env_config( + gpr_getenv("GRPC_XDS_BOOTSTRAP_CONFIG")); + if (env_config != nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { + gpr_log(GPR_INFO, + "Got bootstrap contents from GRPC_XDS_BOOTSTRAP_CONFIG " + "environment variable"); + } + return env_config.get(); + } + // Finally, try fallback config. + if (fallback_config != nullptr) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { + gpr_log(GPR_INFO, "Got bootstrap contents from fallback config"); + } + return fallback_config; + } + // No bootstrap config found. + *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Environment variables GRPC_XDS_BOOTSTRAP or GRPC_XDS_BOOTSTRAP_CONFIG " + "not defined"); + return ""; +} + +} // namespace + +RefCountedPtr XdsClient::GetOrCreate(const grpc_channel_args* args, + grpc_error_handle* error) { + RefCountedPtr xds_client; + // If getting bootstrap from channel args, create a local XdsClient + // instance for the channel or server instead of using the global instance. + const char* bootstrap_config = grpc_channel_args_find_string( + args, GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG); + if (bootstrap_config != nullptr) { + std::unique_ptr bootstrap = + XdsBootstrap::Create(bootstrap_config, error); + if (*error == GRPC_ERROR_NONE) { + grpc_channel_args* xds_channel_args = + grpc_channel_args_find_pointer( + args, + GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS); + return MakeRefCounted(std::move(bootstrap), xds_channel_args); + } + return nullptr; + } + // Otherwise, use the global instance. + { + MutexLock lock(g_mu); + if (g_xds_client != nullptr) { + auto xds_client = g_xds_client->RefIfNonZero(); + if (xds_client != nullptr) return xds_client; + } + // Find bootstrap contents. + std::string bootstrap_contents = + GetBootstrapContents(g_fallback_bootstrap_config, error); + if (*error != GRPC_ERROR_NONE) return nullptr; + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { + gpr_log(GPR_INFO, "xDS bootstrap contents: %s", + bootstrap_contents.c_str()); + } + // Parse bootstrap. + std::unique_ptr bootstrap = + XdsBootstrap::Create(bootstrap_contents, error); + if (*error != GRPC_ERROR_NONE) return nullptr; + // Instantiate XdsClient. + xds_client = + MakeRefCounted(std::move(bootstrap), g_channel_args); + g_xds_client = xds_client.get(); } - auto xds_client = MakeRefCounted(error); - g_xds_client = xds_client.get(); return xds_client; } @@ -2242,4 +2459,58 @@ void SetXdsFallbackBootstrapConfig(const char* config) { } // namespace internal +// +// embedding XdsClient in channel args +// + +#define GRPC_ARG_XDS_CLIENT "grpc.internal.xds_client" + +namespace { + +void* XdsClientArgCopy(void* p) { + XdsClient* xds_client = static_cast(p); + xds_client->Ref(DEBUG_LOCATION, "channel arg").release(); + return p; +} + +void XdsClientArgDestroy(void* p) { + XdsClient* xds_client = static_cast(p); + xds_client->Unref(DEBUG_LOCATION, "channel arg"); +} + +int XdsClientArgCmp(void* p, void* q) { return GPR_ICMP(p, q); } + +const grpc_arg_pointer_vtable kXdsClientArgVtable = { + XdsClientArgCopy, XdsClientArgDestroy, XdsClientArgCmp}; + +} // namespace + +grpc_arg XdsClient::MakeChannelArg() const { + return grpc_channel_arg_pointer_create(const_cast(GRPC_ARG_XDS_CLIENT), + const_cast(this), + &kXdsClientArgVtable); +} + +RefCountedPtr XdsClient::GetFromChannelArgs( + const grpc_channel_args& args) { + XdsClient* xds_client = + grpc_channel_args_find_pointer(&args, GRPC_ARG_XDS_CLIENT); + if (xds_client == nullptr) return nullptr; + return xds_client->Ref(DEBUG_LOCATION, "GetFromChannelArgs"); +} + } // namespace grpc_core + +// The returned bytes may contain NULL(0), so we can't use c-string. +grpc_slice grpc_dump_xds_configs() { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; + grpc_error_handle error = GRPC_ERROR_NONE; + auto xds_client = grpc_core::XdsClient::GetOrCreate(nullptr, &error); + if (error != GRPC_ERROR_NONE) { + // If we isn't using xDS, just return an empty string. + GRPC_ERROR_UNREF(error); + return grpc_empty_slice(); + } + return grpc_slice_from_cpp_string(xds_client->DumpClientConfigBinary()); +} diff --git a/src/core/ext/xds/xds_client.h b/src/core/ext/xds/xds_client.h index 0a74ec8d787..0ee84e7866d 100644 --- a/src/core/ext/xds/xds_client.h +++ b/src/core/ext/xds/xds_client.h @@ -48,7 +48,7 @@ class XdsClient : public DualRefCounted { public: virtual ~ListenerWatcherInterface() = default; virtual void OnListenerChanged(XdsApi::LdsUpdate listener) = 0; - virtual void OnError(grpc_error* error) = 0; + virtual void OnError(grpc_error_handle error) = 0; virtual void OnResourceDoesNotExist() = 0; }; @@ -57,7 +57,7 @@ class XdsClient : public DualRefCounted { public: virtual ~RouteConfigWatcherInterface() = default; virtual void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) = 0; - virtual void OnError(grpc_error* error) = 0; + virtual void OnError(grpc_error_handle error) = 0; virtual void OnResourceDoesNotExist() = 0; }; @@ -66,7 +66,7 @@ class XdsClient : public DualRefCounted { public: virtual ~ClusterWatcherInterface() = default; virtual void OnClusterChanged(XdsApi::CdsUpdate cluster_data) = 0; - virtual void OnError(grpc_error* error) = 0; + virtual void OnError(grpc_error_handle error) = 0; virtual void OnResourceDoesNotExist() = 0; }; @@ -75,19 +75,27 @@ class XdsClient : public DualRefCounted { public: virtual ~EndpointWatcherInterface() = default; virtual void OnEndpointChanged(XdsApi::EdsUpdate update) = 0; - virtual void OnError(grpc_error* error) = 0; + virtual void OnError(grpc_error_handle error) = 0; virtual void OnResourceDoesNotExist() = 0; }; // Factory function to get or create the global XdsClient instance. // If *error is not GRPC_ERROR_NONE upon return, then there was // an error initializing the client. - static RefCountedPtr GetOrCreate(grpc_error** error); + static RefCountedPtr GetOrCreate(const grpc_channel_args* args, + grpc_error_handle* error); - // Callers should not instantiate directly. Use GetOrCreate() instead. - explicit XdsClient(grpc_error** error); + // Most callers should not instantiate directly. Use GetOrCreate() instead. + XdsClient(std::unique_ptr bootstrap, + const grpc_channel_args* args); ~XdsClient() override; + const XdsBootstrap& bootstrap() const { + // bootstrap_ is guaranteed to be non-null since XdsClient::GetOrCreate() + // would return a null object if bootstrap_ was null. + return *bootstrap_; + } + CertificateProviderStore& certificate_provider_store() { return *certificate_provider_store_; } @@ -185,6 +193,20 @@ class XdsClient : public DualRefCounted { // Resets connection backoff state. void ResetBackoff(); + // Dumps the active xDS config in JSON format. + // Individual xDS resource is encoded as envoy.admin.v3.*ConfigDump. Returns + // envoy.service.status.v3.ClientConfig which also includes the config + // status (e.g., CLIENT_REQUESTED, CLIENT_ACKED, CLIENT_NACKED). + // + // Expected to be invoked by wrapper languages in their CSDS service + // implementation. + std::string DumpClientConfigBinary(); + + // Helpers for encoding the XdsClient object in channel args. + grpc_arg MakeChannelArg() const; + static RefCountedPtr GetFromChannelArgs( + const grpc_channel_args& args); + private: // Contains a channel to the xds server and all the data related to the // channel. Holds a ref to the xds client object. @@ -215,14 +237,17 @@ class XdsClient : public DualRefCounted { void MaybeStartLrsCall(); void StopLrsCall(); + bool HasAdsCall() const; bool HasActiveAdsCall() const; void StartConnectivityWatchLocked(); void CancelConnectivityWatchLocked(); - void Subscribe(const std::string& type_url, const std::string& name); - void Unsubscribe(const std::string& type_url, const std::string& name, - bool delay_unsubscription); + void SubscribeLocked(const std::string& type_url, const std::string& name) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + void UnsubscribeLocked(const std::string& type_url, const std::string& name, + bool delay_unsubscription) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); private: class StateWatcher; @@ -248,6 +273,7 @@ class XdsClient : public DualRefCounted { watchers; // The latest data seen from LDS. absl::optional update; + XdsApi::ResourceMetadata meta; }; struct RouteConfigState { @@ -256,6 +282,7 @@ class XdsClient : public DualRefCounted { watchers; // The latest data seen from RDS. absl::optional update; + XdsApi::ResourceMetadata meta; }; struct ClusterState { @@ -263,6 +290,7 @@ class XdsClient : public DualRefCounted { watchers; // The latest data seen from CDS. absl::optional update; + XdsApi::ResourceMetadata meta; }; struct EndpointState { @@ -271,6 +299,7 @@ class XdsClient : public DualRefCounted { watchers; // The latest data seen from EDS. absl::optional update; + XdsApi::ResourceMetadata meta; }; struct LoadReportState { @@ -288,42 +317,53 @@ class XdsClient : public DualRefCounted { }; // Sends an error notification to all watchers. - void NotifyOnErrorLocked(grpc_error* error); + void NotifyOnErrorLocked(grpc_error_handle error) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); XdsApi::ClusterLoadReportMap BuildLoadReportSnapshotLocked( - bool send_all_clusters, const std::set& clusters); + bool send_all_clusters, const std::set& clusters) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + + void UpdateResourceMetadataWithFailedParseResultLocked( + grpc_millis update_time, const XdsApi::AdsParseResult& result) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + std::unique_ptr bootstrap_; + grpc_channel_args* args_; const grpc_millis request_timeout_; grpc_pollset_set* interested_parties_; - std::unique_ptr bootstrap_; OrphanablePtr certificate_provider_store_; XdsApi api_; Mutex mu_; // The channel for communicating with the xds server. - OrphanablePtr chand_; + OrphanablePtr chand_ ABSL_GUARDED_BY(mu_); // One entry for each watched LDS resource. - std::map listener_map_; + std::map listener_map_ + ABSL_GUARDED_BY(mu_); // One entry for each watched RDS resource. std::map - route_config_map_; + route_config_map_ ABSL_GUARDED_BY(mu_); // One entry for each watched CDS resource. - std::map cluster_map_; + std::map cluster_map_ + ABSL_GUARDED_BY(mu_); // One entry for each watched EDS resource. - std::map endpoint_map_; + std::map endpoint_map_ + ABSL_GUARDED_BY(mu_); // Load report data. std::map< std::pair, LoadReportState> - load_report_map_; + load_report_map_ ABSL_GUARDED_BY(mu_); // Stores the most recent accepted resource version for each resource type. - std::map resource_version_map_; + std::map resource_version_map_ + ABSL_GUARDED_BY(mu_); - bool shutting_down_ = false; + bool shutting_down_ ABSL_GUARDED_BY(mu_) = false; }; namespace internal { @@ -336,4 +376,4 @@ void SetXdsFallbackBootstrapConfig(const char* config); } // namespace grpc_core -#endif /* GRPC_CORE_EXT_XDS_XDS_CLIENT_H */ +#endif // GRPC_CORE_EXT_XDS_XDS_CLIENT_H diff --git a/src/core/ext/xds/xds_client_stats.h b/src/core/ext/xds/xds_client_stats.h index 852dda26089..b300fc59256 100644 --- a/src/core/ext/xds/xds_client_stats.h +++ b/src/core/ext/xds/xds_client_stats.h @@ -149,7 +149,7 @@ class XdsClusterDropStats : public RefCounted { // dropped_requests can be accessed by both the picker (from data plane // mutex) and the load reporting thread (from the control plane combiner). Mutex mu_; - CategorizedDropsMap categorized_drops_; + CategorizedDropsMap categorized_drops_ ABSL_GUARDED_BY(mu_); }; // Locality stats for an xds cluster. @@ -231,7 +231,8 @@ class XdsClusterLocalityStats : public RefCounted { // call's recv_trailing_metadata (not from the control plane work serializer) // and the load reporting thread (from the control plane work serializer). Mutex backend_metrics_mu_; - std::map backend_metrics_; + std::map backend_metrics_ + ABSL_GUARDED_BY(backend_metrics_mu_); }; } // namespace grpc_core diff --git a/src/core/ext/xds/xds_http_fault_filter.cc b/src/core/ext/xds/xds_http_fault_filter.cc new file mode 100644 index 00000000000..64b7a2b47af --- /dev/null +++ b/src/core/ext/xds/xds_http_fault_filter.cc @@ -0,0 +1,226 @@ +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include + +#include "src/core/ext/xds/xds_http_fault_filter.h" + +#include + +#include + +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" +#include "envoy/extensions/filters/common/fault/v3/fault.upb.h" +#include "envoy/extensions/filters/http/fault/v3/fault.upb.h" +#include "envoy/extensions/filters/http/fault/v3/fault.upbdefs.h" +#include "envoy/type/v3/percent.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/duration.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "src/core/ext/filters/fault_injection/fault_injection_filter.h" +#include "src/core/ext/xds/xds_http_filters.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/json/json.h" +#include "src/core/lib/transport/status_conversion.h" +#include "upb/def.h" + +namespace grpc_core { + +const char* kXdsHttpFaultFilterConfigName = + "envoy.extensions.filters.http.fault.v3.HTTPFault"; + +namespace { + +uint32_t GetDenominator(const envoy_type_v3_FractionalPercent* fraction) { + if (fraction != nullptr) { + const auto denominator = + static_cast( + envoy_type_v3_FractionalPercent_denominator(fraction)); + switch (denominator) { + case envoy_type_v3_FractionalPercent_MILLION: + return 1000000; + case envoy_type_v3_FractionalPercent_TEN_THOUSAND: + return 10000; + case envoy_type_v3_FractionalPercent_HUNDRED: + default: + return 100; + } + } + // Use 100 as the default denominator + return 100; +} + +absl::StatusOr ParseHttpFaultIntoJson(upb_strview serialized_http_fault, + upb_arena* arena) { + auto* http_fault = envoy_extensions_filters_http_fault_v3_HTTPFault_parse( + serialized_http_fault.data, serialized_http_fault.size, arena); + if (http_fault == nullptr) { + return absl::InvalidArgumentError( + "could not parse fault injection filter config"); + } + // NOTE(lidiz): Here, we are manually translating the upb messages into the + // JSON form of the filter config as part of method config, which will be + // directly used later by service config. In this way, we can validate the + // filter configs, and NACK if needed. It also allows the service config to + // function independently without xDS, but not the other way around. + // NOTE(lidiz): please refer to FaultInjectionPolicy for ground truth + // definitions, located at: + // src/core/ext/filters/fault_injection/service_config_parser.h + Json::Object fault_injection_policy_json; + // Section 1: Parse the abort injection config + const auto* fault_abort = + envoy_extensions_filters_http_fault_v3_HTTPFault_abort(http_fault); + if (fault_abort != nullptr) { + grpc_status_code abort_grpc_status_code = GRPC_STATUS_OK; + // Try if gRPC status code is set first + int abort_grpc_status_code_raw = + envoy_extensions_filters_http_fault_v3_FaultAbort_grpc_status( + fault_abort); + if (abort_grpc_status_code_raw != 0) { + if (!grpc_status_code_from_int(abort_grpc_status_code_raw, + &abort_grpc_status_code)) { + return absl::InvalidArgumentError(absl::StrCat( + "invalid gRPC status code: ", abort_grpc_status_code_raw)); + } + } else { + // if gRPC status code is empty, check http status + int abort_http_status_code = + envoy_extensions_filters_http_fault_v3_FaultAbort_http_status( + fault_abort); + if (abort_http_status_code != 0 and abort_http_status_code != 200) { + abort_grpc_status_code = + grpc_http2_status_to_grpc_status(abort_http_status_code); + } + } + // Set the abort_code, even if it's OK + fault_injection_policy_json["abortCode"] = + grpc_status_code_to_string(abort_grpc_status_code); + // Set the headers if we enabled header abort injection control + if (envoy_extensions_filters_http_fault_v3_FaultAbort_has_header_abort( + fault_abort)) { + fault_injection_policy_json["abortCodeHeader"] = + "x-envoy-fault-abort-grpc-request"; + fault_injection_policy_json["abortPercentageHeader"] = + "x-envoy-fault-abort-percentage"; + } + // Set the fraction percent + auto* percent = + envoy_extensions_filters_http_fault_v3_FaultAbort_percentage( + fault_abort); + fault_injection_policy_json["abortPercentageNumerator"] = + Json(envoy_type_v3_FractionalPercent_numerator(percent)); + fault_injection_policy_json["abortPercentageDenominator"] = + Json(GetDenominator(percent)); + } + // Section 2: Parse the delay injection config + const auto* fault_delay = + envoy_extensions_filters_http_fault_v3_HTTPFault_delay(http_fault); + if (fault_delay != nullptr) { + // Parse the delay duration + const auto* delay_duration = + envoy_extensions_filters_common_fault_v3_FaultDelay_fixed_delay( + fault_delay); + if (delay_duration != nullptr) { + fault_injection_policy_json["delay"] = absl::StrFormat( + "%d.%09ds", google_protobuf_Duration_seconds(delay_duration), + google_protobuf_Duration_nanos(delay_duration)); + } + // Set the headers if we enabled header delay injection control + if (envoy_extensions_filters_common_fault_v3_FaultDelay_has_header_delay( + fault_delay)) { + fault_injection_policy_json["delayHeader"] = + "x-envoy-fault-delay-request"; + fault_injection_policy_json["delayPercentageHeader"] = + "x-envoy-fault-delay-request-percentage"; + } + // Set the fraction percent + auto* percent = + envoy_extensions_filters_common_fault_v3_FaultDelay_percentage( + fault_delay); + fault_injection_policy_json["delayPercentageNumerator"] = + Json(envoy_type_v3_FractionalPercent_numerator(percent)); + fault_injection_policy_json["delayPercentageDenominator"] = + Json(GetDenominator(percent)); + } + // Section 3: Parse the maximum active faults + const auto* max_fault_wrapper = + envoy_extensions_filters_http_fault_v3_HTTPFault_max_active_faults( + http_fault); + if (max_fault_wrapper != nullptr) { + fault_injection_policy_json["maxFaults"] = + google_protobuf_UInt32Value_value(max_fault_wrapper); + } + return fault_injection_policy_json; +} + +} // namespace + +void XdsHttpFaultFilter::PopulateSymtab(upb_symtab* symtab) const { + envoy_extensions_filters_http_fault_v3_HTTPFault_getmsgdef(symtab); +} + +absl::StatusOr +XdsHttpFaultFilter::GenerateFilterConfig(upb_strview serialized_filter_config, + upb_arena* arena) const { + absl::StatusOr parse_result = + ParseHttpFaultIntoJson(serialized_filter_config, arena); + if (!parse_result.ok()) { + return parse_result.status(); + } + return FilterConfig{kXdsHttpFaultFilterConfigName, std::move(*parse_result)}; +} + +absl::StatusOr +XdsHttpFaultFilter::GenerateFilterConfigOverride( + upb_strview serialized_filter_config, upb_arena* arena) const { + // HTTPFault filter has the same message type in HTTP connection manager's + // filter config and in overriding filter config field. + return GenerateFilterConfig(serialized_filter_config, arena); +} + +const grpc_channel_filter* XdsHttpFaultFilter::channel_filter() const { + return &FaultInjectionFilterVtable; +} + +grpc_channel_args* XdsHttpFaultFilter::ModifyChannelArgs( + grpc_channel_args* args) const { + grpc_arg args_to_add = grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_PARSE_FAULT_INJECTION_METHOD_CONFIG), 1); + grpc_channel_args* new_args = + grpc_channel_args_copy_and_add(args, &args_to_add, 1); + // Since this function takes the ownership of the channel args, it needs to + // deallocate the old ones to prevent leak. + grpc_channel_args_destroy(args); + return new_args; +} + +absl::StatusOr +XdsHttpFaultFilter::GenerateServiceConfig( + const FilterConfig& hcm_filter_config, + const FilterConfig* filter_config_override) const { + Json policy_json = filter_config_override != nullptr + ? filter_config_override->config + : hcm_filter_config.config; + // The policy JSON may be empty, that's allowed. + return ServiceConfigJsonEntry{"faultInjectionPolicy", policy_json.Dump()}; +} + +} // namespace grpc_core diff --git a/src/core/ext/xds/xds_http_fault_filter.h b/src/core/ext/xds/xds_http_fault_filter.h new file mode 100644 index 00000000000..60c49524328 --- /dev/null +++ b/src/core/ext/xds/xds_http_fault_filter.h @@ -0,0 +1,63 @@ +// +// Copyright 2021 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_XDS_HTTP_FAULT_FILTER_H +#define GRPC_CORE_EXT_XDS_XDS_HTTP_FAULT_FILTER_H + +#include + +#include + +#include "absl/status/statusor.h" +#include "src/core/ext/xds/xds_http_filters.h" +#include "upb/def.h" + +namespace grpc_core { + +extern const char* kXdsHttpFaultFilterConfigName; + +class XdsHttpFaultFilter : public XdsHttpFilterImpl { + public: + // Overrides the PopulateSymtab method + void PopulateSymtab(upb_symtab* symtab) const override; + + // Overrides the GenerateFilterConfig method + absl::StatusOr GenerateFilterConfig( + upb_strview serialized_filter_config, upb_arena* arena) const override; + + // Overrides the GenerateFilterConfigOverride method + absl::StatusOr GenerateFilterConfigOverride( + upb_strview serialized_filter_config, upb_arena* arena) const override; + + // Overrides the channel_filter method + const grpc_channel_filter* channel_filter() const override; + + // Overrides the ModifyChannelArgs method + grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) const override; + + // Overrides the GenerateServiceConfig method + absl::StatusOr GenerateServiceConfig( + const FilterConfig& hcm_filter_config, + const FilterConfig* filter_config_override) const override; + + bool IsSupportedOnClients() const override { return true; } + + bool IsSupportedOnServers() const override { return false; } +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_EXT_XDS_XDS_HTTP_FAULT_FILTER_H */ diff --git a/src/core/ext/xds/xds_http_filters.cc b/src/core/ext/xds/xds_http_filters.cc index 11b644339b6..9bd4858b2cb 100644 --- a/src/core/ext/xds/xds_http_filters.cc +++ b/src/core/ext/xds/xds_http_filters.cc @@ -20,6 +20,7 @@ #include "envoy/extensions/filters/http/router/v3/router.upb.h" #include "envoy/extensions/filters/http/router/v3/router.upbdefs.h" +#include "src/core/ext/xds/xds_http_fault_filter.h" namespace grpc_core { @@ -60,6 +61,10 @@ class XdsHttpRouterFilter : public XdsHttpFilterImpl { const FilterConfig* /*filter_config_override*/) const override { return absl::UnimplementedError("router filter should never be called"); } + + bool IsSupportedOnClients() const override { return true; } + + bool IsSupportedOnServers() const override { return true; } }; using FilterOwnerList = std::vector>; @@ -97,6 +102,8 @@ void XdsHttpFilterRegistry::Init() { g_filter_registry = new FilterRegistryMap; RegisterFilter(absl::make_unique(), {kXdsHttpRouterFilterConfigName}); + RegisterFilter(absl::make_unique(), + {kXdsHttpFaultFilterConfigName}); } void XdsHttpFilterRegistry::Shutdown() { diff --git a/src/core/ext/xds/xds_http_filters.h b/src/core/ext/xds/xds_http_filters.h index 61e96cde665..332419681ed 100644 --- a/src/core/ext/xds/xds_http_filters.h +++ b/src/core/ext/xds/xds_http_filters.h @@ -101,6 +101,12 @@ class XdsHttpFilterImpl { virtual absl::StatusOr GenerateServiceConfig( const FilterConfig& hcm_filter_config, const FilterConfig* filter_config_override) const = 0; + + // Returns true if the filter is supported on clients; false otherwise + virtual bool IsSupportedOnClients() const = 0; + + // Returns true if the filter is supported on servers; false otherwise + virtual bool IsSupportedOnServers() const = 0; }; class XdsHttpFilterRegistry { diff --git a/src/core/ext/xds/xds_server_config_fetcher.cc b/src/core/ext/xds/xds_server_config_fetcher.cc index b276b5b292c..962731f9eeb 100644 --- a/src/core/ext/xds/xds_server_config_fetcher.cc +++ b/src/core/ext/xds/xds_server_config_fetcher.cc @@ -18,12 +18,19 @@ #include +#include "absl/strings/str_replace.h" + #include "src/core/ext/xds/xds_certificate_provider.h" #include "src/core/ext/xds/xds_client.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gprpp/host_port.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/security/credentials/xds/xds_credentials.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" +#include "src/core/lib/uri/uri_parser.h" namespace grpc_core { @@ -32,10 +39,317 @@ TraceFlag grpc_xds_server_config_fetcher_trace(false, namespace { +class FilterChainMatchManager + : public grpc_server_config_fetcher::ConnectionManager { + public: + FilterChainMatchManager( + RefCountedPtr xds_client, + XdsApi::LdsUpdate::FilterChainMap filter_chain_map, + absl::optional default_filter_chain) + : xds_client_(xds_client), + filter_chain_map_(std::move(filter_chain_map)), + default_filter_chain_(std::move(default_filter_chain)) {} + + absl::StatusOr UpdateChannelArgsForConnection( + grpc_channel_args* args, grpc_endpoint* tcp) override; + + const XdsApi::LdsUpdate::FilterChainMap& filter_chain_map() const { + return filter_chain_map_; + } + + const absl::optional& + default_filter_chain() const { + return default_filter_chain_; + } + + private: + struct CertificateProviders { + // We need to save our own refs to the root and instance certificate + // providers since the xds certificate provider just stores a ref to their + // distributors. + RefCountedPtr root; + RefCountedPtr instance; + RefCountedPtr xds; + }; + + absl::StatusOr> + CreateOrGetXdsCertificateProviderFromFilterChainData( + const XdsApi::LdsUpdate::FilterChainData* filter_chain); + + const RefCountedPtr xds_client_; + const XdsApi::LdsUpdate::FilterChainMap filter_chain_map_; + const absl::optional + default_filter_chain_; + Mutex mu_; + std::map + certificate_providers_map_ ABSL_GUARDED_BY(mu_); +}; + +bool IsLoopbackIp(const grpc_resolved_address* address) { + const grpc_sockaddr* sock_addr = + reinterpret_cast(&address->addr); + if (sock_addr->sa_family == GRPC_AF_INET) { + const grpc_sockaddr_in* addr4 = + reinterpret_cast(sock_addr); + if (addr4->sin_addr.s_addr == grpc_htonl(INADDR_LOOPBACK)) { + return true; + } + } else if (sock_addr->sa_family == GRPC_AF_INET6) { + const grpc_sockaddr_in6* addr6 = + reinterpret_cast(sock_addr); + if (memcmp(&addr6->sin6_addr, &in6addr_loopback, + sizeof(in6addr_loopback)) == 0) { + return true; + } + } + return false; +} + +const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourcePort( + const XdsApi::LdsUpdate::FilterChainMap::SourcePortsMap& source_ports_map, + absl::string_view port_str) { + int port = 0; + if (!absl::SimpleAtoi(port_str, &port)) return nullptr; + auto it = source_ports_map.find(port); + if (it != source_ports_map.end()) { + return it->second.data.get(); + } + // Search for the catch-all port 0 since we didn't get a direct match + it = source_ports_map.find(0); + if (it != source_ports_map.end()) { + return it->second.data.get(); + } + return nullptr; +} + +const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourceIp( + const XdsApi::LdsUpdate::FilterChainMap::SourceIpVector& source_ip_vector, + const grpc_resolved_address* source_ip, absl::string_view port) { + const XdsApi::LdsUpdate::FilterChainMap::SourceIp* best_match = nullptr; + for (const auto& entry : source_ip_vector) { + // Special case for catch-all + if (!entry.prefix_range.has_value()) { + if (best_match == nullptr) { + best_match = &entry; + } + continue; + } + if (best_match != nullptr && best_match->prefix_range.has_value() && + best_match->prefix_range->prefix_len >= + entry.prefix_range->prefix_len) { + continue; + } + if (grpc_sockaddr_match_subnet(source_ip, &entry.prefix_range->address, + entry.prefix_range->prefix_len)) { + best_match = &entry; + } + } + if (best_match == nullptr) return nullptr; + return FindFilterChainDataForSourcePort(best_match->ports_map, port); +} + +const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourceType( + const XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceTypesArray& + source_types_array, + grpc_endpoint* tcp, absl::string_view destination_ip) { + auto source_uri = URI::Parse(grpc_endpoint_get_peer(tcp)); + if (!source_uri.ok() || + (source_uri->scheme() != "ipv4" && source_uri->scheme() != "ipv6")) { + return nullptr; + } + std::string host; + std::string port; + if (!SplitHostPort(source_uri->path(), &host, &port)) { + return nullptr; + } + grpc_resolved_address source_addr; + grpc_error_handle error = grpc_string_to_sockaddr( + &source_addr, host.c_str(), 0 /* port doesn't matter here */); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_DEBUG, "Could not parse string to socket address: %s", + host.c_str()); + GRPC_ERROR_UNREF(error); + return nullptr; + } + // Use kAny only if kSameIporLoopback and kExternal are empty + if (source_types_array[static_cast( + XdsApi::LdsUpdate::FilterChainMap:: + ConnectionSourceType::kSameIpOrLoopback)] + .empty() && + source_types_array[static_cast(XdsApi::LdsUpdate::FilterChainMap:: + ConnectionSourceType::kExternal)] + .empty()) { + return FindFilterChainDataForSourceIp( + source_types_array[static_cast( + XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::kAny)], + &source_addr, port); + } + if (IsLoopbackIp(&source_addr) || host == destination_ip) { + return FindFilterChainDataForSourceIp( + source_types_array[static_cast( + XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType:: + kSameIpOrLoopback)], + &source_addr, port); + } else { + return FindFilterChainDataForSourceIp( + source_types_array[static_cast( + XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType:: + kExternal)], + &source_addr, port); + } +} + +const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForDestinationIp( + const XdsApi::LdsUpdate::FilterChainMap::DestinationIpVector + destination_ip_vector, + grpc_endpoint* tcp) { + auto destination_uri = URI::Parse(grpc_endpoint_get_local_address(tcp)); + if (!destination_uri.ok() || (destination_uri->scheme() != "ipv4" && + destination_uri->scheme() != "ipv6")) { + return nullptr; + } + std::string host; + std::string port; + if (!SplitHostPort(destination_uri->path(), &host, &port)) { + return nullptr; + } + grpc_resolved_address destination_addr; + grpc_error_handle error = grpc_string_to_sockaddr( + &destination_addr, host.c_str(), 0 /* port doesn't matter here */); + if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_DEBUG, "Could not parse string to socket address: %s", + host.c_str()); + GRPC_ERROR_UNREF(error); + return nullptr; + } + const XdsApi::LdsUpdate::FilterChainMap::DestinationIp* best_match = nullptr; + for (const auto& entry : destination_ip_vector) { + // Special case for catch-all + if (!entry.prefix_range.has_value()) { + if (best_match == nullptr) { + best_match = &entry; + } + continue; + } + if (best_match != nullptr && best_match->prefix_range.has_value() && + best_match->prefix_range->prefix_len >= + entry.prefix_range->prefix_len) { + continue; + } + if (grpc_sockaddr_match_subnet(&destination_addr, + &entry.prefix_range->address, + entry.prefix_range->prefix_len)) { + best_match = &entry; + } + } + if (best_match == nullptr) return nullptr; + return FindFilterChainDataForSourceType(best_match->source_types_array, tcp, + host); +} + +absl::StatusOr> +FilterChainMatchManager::CreateOrGetXdsCertificateProviderFromFilterChainData( + const XdsApi::LdsUpdate::FilterChainData* filter_chain) { + MutexLock lock(&mu_); + auto it = certificate_providers_map_.find(filter_chain); + if (it != certificate_providers_map_.end()) { + return it->second.xds; + } + CertificateProviders certificate_providers; + // Configure root cert. + absl::string_view root_provider_instance_name = + filter_chain->downstream_tls_context.common_tls_context + .combined_validation_context + .validation_context_certificate_provider_instance.instance_name; + absl::string_view root_provider_cert_name = + filter_chain->downstream_tls_context.common_tls_context + .combined_validation_context + .validation_context_certificate_provider_instance.certificate_name; + if (!root_provider_instance_name.empty()) { + certificate_providers.root = + xds_client_->certificate_provider_store() + .CreateOrGetCertificateProvider(root_provider_instance_name); + if (certificate_providers.root == nullptr) { + return absl::NotFoundError( + absl::StrCat("Certificate provider instance name: \"", + root_provider_instance_name, "\" not recognized.")); + } + } + // Configure identity cert. + absl::string_view identity_provider_instance_name = + filter_chain->downstream_tls_context.common_tls_context + .tls_certificate_certificate_provider_instance.instance_name; + absl::string_view identity_provider_cert_name = + filter_chain->downstream_tls_context.common_tls_context + .tls_certificate_certificate_provider_instance.certificate_name; + if (!identity_provider_instance_name.empty()) { + certificate_providers.instance = + xds_client_->certificate_provider_store() + .CreateOrGetCertificateProvider(identity_provider_instance_name); + if (certificate_providers.instance == nullptr) { + return absl::NotFoundError( + absl::StrCat("Certificate provider instance name: \"", + identity_provider_instance_name, "\" not recognized.")); + } + } + certificate_providers.xds = MakeRefCounted(); + certificate_providers.xds->UpdateRootCertNameAndDistributor( + "", root_provider_cert_name, + certificate_providers.root == nullptr + ? nullptr + : certificate_providers.root->distributor()); + certificate_providers.xds->UpdateIdentityCertNameAndDistributor( + "", identity_provider_cert_name, + certificate_providers.instance == nullptr + ? nullptr + : certificate_providers.instance->distributor()); + certificate_providers.xds->UpdateRequireClientCertificate( + "", filter_chain->downstream_tls_context.require_client_certificate); + auto xds_certificate_provider = certificate_providers.xds; + certificate_providers_map_.emplace(filter_chain, + std::move(certificate_providers)); + return xds_certificate_provider; +} + +absl::StatusOr +FilterChainMatchManager::UpdateChannelArgsForConnection(grpc_channel_args* args, + grpc_endpoint* tcp) { + const auto* filter_chain = FindFilterChainDataForDestinationIp( + filter_chain_map_.destination_ip_vector, tcp); + if (filter_chain == nullptr && default_filter_chain_.has_value()) { + filter_chain = &default_filter_chain_.value(); + } + if (filter_chain == nullptr) { + grpc_channel_args_destroy(args); + return absl::UnavailableError("No matching filter chain found"); + } + // Nothing to update if credentials are not xDS. + grpc_server_credentials* server_creds = + grpc_find_server_credentials_in_args(args); + if (server_creds == nullptr || server_creds->type() != kCredentialsTypeXds) { + return args; + } + absl::StatusOr> result = + CreateOrGetXdsCertificateProviderFromFilterChainData(filter_chain); + if (!result.ok()) { + grpc_channel_args_destroy(args); + return result.status(); + } + RefCountedPtr xds_certificate_provider = + std::move(*result); + GPR_ASSERT(xds_certificate_provider != nullptr); + grpc_arg arg_to_add = xds_certificate_provider->MakeChannelArg(); + grpc_channel_args* updated_args = + grpc_channel_args_copy_and_add(args, &arg_to_add, 1); + grpc_channel_args_destroy(args); + return updated_args; +} + class XdsServerConfigFetcher : public grpc_server_config_fetcher { public: - explicit XdsServerConfigFetcher(RefCountedPtr xds_client) - : xds_client_(std::move(xds_client)) { + explicit XdsServerConfigFetcher(RefCountedPtr xds_client, + grpc_server_xds_status_notifier notifier) + : xds_client_(std::move(xds_client)), serving_status_notifier_(notifier) { GPR_ASSERT(xds_client_ != nullptr); } @@ -44,11 +358,12 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher { watcher) override { grpc_server_config_fetcher::WatcherInterface* watcher_ptr = watcher.get(); auto listener_watcher = absl::make_unique( - std::move(watcher), args, xds_client_); + std::move(watcher), args, xds_client_, serving_status_notifier_, + listening_address); auto* listener_watcher_ptr = listener_watcher.get(); - // TODO(yashykt): Get the resource name id from bootstrap - listening_address = absl::StrCat( - "grpc/server?xds.resource.listening_address=", listening_address); + listening_address = absl::StrReplaceAll( + xds_client_->bootstrap().server_listener_resource_name_template(), + {{"%s", listening_address}}); xds_client_->WatchListenerData(listening_address, std::move(listener_watcher)); MutexLock lock(&mu_); @@ -81,10 +396,14 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher { explicit ListenerWatcher( std::unique_ptr server_config_watcher, - grpc_channel_args* args, RefCountedPtr xds_client) + grpc_channel_args* args, RefCountedPtr xds_client, + grpc_server_xds_status_notifier serving_status_notifier, + std::string listening_address) : server_config_watcher_(std::move(server_config_watcher)), args_(args), - xds_client_(std::move(xds_client)) {} + xds_client_(std::move(xds_client)), + serving_status_notifier_(serving_status_notifier), + listening_address_(std::move(listening_address)) {} ~ListenerWatcher() override { grpc_channel_args_destroy(args_); } @@ -100,146 +419,90 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher { "[ListenerWatcher %p] Received LDS update from xds client %p: %s", this, xds_client_.get(), listener.ToString().c_str()); } - grpc_error* error = GRPC_ERROR_NONE; - bool update_needed = UpdateXdsCertificateProvider(listener, &error); - if (error != GRPC_ERROR_NONE) { - OnError(error); + if (listener.address != listening_address_) { + OnFatalError(absl::FailedPreconditionError( + "Address in LDS update does not match listening address")); return; } - // Only send an update, if something changed. - if (updated_once_ && !update_needed) { - return; + if (filter_chain_match_manager_ == nullptr) { + if (serving_status_notifier_.on_serving_status_update != nullptr) { + serving_status_notifier_.on_serving_status_update( + serving_status_notifier_.user_data, listening_address_.c_str(), + GRPC_STATUS_OK, ""); + } else { + gpr_log(GPR_INFO, + "xDS Listener resource obtained; will start serving on %s", + listening_address_.c_str()); + } } - updated_once_ = true; - grpc_channel_args* updated_args = nullptr; - if (xds_certificate_provider_ != nullptr) { - grpc_arg arg_to_add = xds_certificate_provider_->MakeChannelArg(); - updated_args = grpc_channel_args_copy_and_add(args_, &arg_to_add, 1); - } else { - updated_args = grpc_channel_args_copy(args_); + if (filter_chain_match_manager_ == nullptr || + !(listener.filter_chain_map == + filter_chain_match_manager_->filter_chain_map() && + listener.default_filter_chain == + filter_chain_match_manager_->default_filter_chain())) { + filter_chain_match_manager_ = MakeRefCounted( + xds_client_, std::move(listener.filter_chain_map), + std::move(listener.default_filter_chain)); + server_config_watcher_->UpdateConnectionManager( + filter_chain_match_manager_); } - server_config_watcher_->UpdateConfig(updated_args); } - void OnError(grpc_error* error) override { - gpr_log(GPR_ERROR, "ListenerWatcher:%p XdsClient reports error: %s", this, - grpc_error_string(error)); + void OnError(grpc_error_handle error) override { + if (filter_chain_match_manager_ != nullptr) { + gpr_log(GPR_ERROR, + "ListenerWatcher:%p XdsClient reports error: %s for %s; " + "ignoring in favor of existing resource", + this, grpc_error_std_string(error).c_str(), + listening_address_.c_str()); + } else { + if (serving_status_notifier_.on_serving_status_update != nullptr) { + serving_status_notifier_.on_serving_status_update( + serving_status_notifier_.user_data, listening_address_.c_str(), + GRPC_STATUS_UNAVAILABLE, grpc_error_std_string(error).c_str()); + } else { + gpr_log( + GPR_ERROR, + "ListenerWatcher:%p error obtaining xDS Listener resource: %s; " + "not serving on %s", + this, grpc_error_std_string(error).c_str(), + listening_address_.c_str()); + } + } GRPC_ERROR_UNREF(error); - // TODO(yashykt): We might want to bubble this error to the application. } - void OnResourceDoesNotExist() override { - gpr_log(GPR_ERROR, - "ListenerWatcher:%p XdsClient reports requested listener does " - "not exist", - this); - // TODO(yashykt): We might want to bubble this error to the application. - } - - private: - // Returns true if the xds certificate provider changed in a way that - // required a new security connector to be created, false otherwise. - bool UpdateXdsCertificateProvider(const XdsApi::LdsUpdate& listener, - grpc_error** error) { - // Early out if channel is not configured to use xDS security. - grpc_server_credentials* server_creds = - grpc_find_server_credentials_in_args(args_); - if (server_creds == nullptr || - server_creds->type() != kCredentialsTypeXds) { - xds_certificate_provider_ = nullptr; - return false; - } - if (xds_certificate_provider_ == nullptr) { - xds_certificate_provider_ = MakeRefCounted(); + void OnFatalError(absl::Status status) { + gpr_log( + GPR_ERROR, + "ListenerWatcher:%p Encountered fatal error %s; not serving on %s", + this, status.ToString().c_str(), listening_address_.c_str()); + if (filter_chain_match_manager_ != nullptr) { + // The server has started listening already, so we need to gracefully + // stop serving. + server_config_watcher_->StopServing(); + filter_chain_match_manager_.reset(); } - // Configure root cert. - absl::string_view root_provider_instance_name = - listener.filter_chains[0] - .downstream_tls_context.common_tls_context - .combined_validation_context - .validation_context_certificate_provider_instance.instance_name; - absl::string_view root_provider_cert_name = - listener.filter_chains[0] - .downstream_tls_context.common_tls_context - .combined_validation_context - .validation_context_certificate_provider_instance - .certificate_name; - RefCountedPtr new_root_provider; - if (!root_provider_instance_name.empty()) { - new_root_provider = - xds_client_->certificate_provider_store() - .CreateOrGetCertificateProvider(root_provider_instance_name); - if (new_root_provider == nullptr) { - *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( - absl::StrCat("Certificate provider instance name: \"", - root_provider_instance_name, "\" not recognized.") - .c_str()); - return false; - } + if (serving_status_notifier_.on_serving_status_update != nullptr) { + serving_status_notifier_.on_serving_status_update( + serving_status_notifier_.user_data, listening_address_.c_str(), + static_cast(status.raw_code()), + std::string(status.message()).c_str()); } - // Configure identity cert. - absl::string_view identity_provider_instance_name = - listener.filter_chains[0] - .downstream_tls_context.common_tls_context - .tls_certificate_certificate_provider_instance.instance_name; - absl::string_view identity_provider_cert_name = - listener.filter_chains[0] - .downstream_tls_context.common_tls_context - .tls_certificate_certificate_provider_instance.certificate_name; - RefCountedPtr new_identity_provider; - if (!identity_provider_instance_name.empty()) { - new_identity_provider = xds_client_->certificate_provider_store() - .CreateOrGetCertificateProvider( - identity_provider_instance_name); - if (new_identity_provider == nullptr) { - *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( - absl::StrCat("Certificate provider instance name: \"", - identity_provider_instance_name, - "\" not recognized.") - .c_str()); - return false; - } - } - bool security_connector_update_required = false; - if (((new_root_provider == nullptr) != - (root_certificate_provider_ == nullptr)) || - ((new_identity_provider == nullptr) != - (identity_certificate_provider_ == nullptr)) || - (listener.filter_chains[0] - .downstream_tls_context.require_client_certificate != - xds_certificate_provider_->GetRequireClientCertificate(""))) { - security_connector_update_required = true; - } - if (root_certificate_provider_ != new_root_provider) { - root_certificate_provider_ = std::move(new_root_provider); - } - if (identity_certificate_provider_ != new_identity_provider) { - identity_certificate_provider_ = std::move(new_identity_provider); - } - xds_certificate_provider_->UpdateRootCertNameAndDistributor( - "", root_provider_cert_name, - root_certificate_provider_ == nullptr - ? nullptr - : root_certificate_provider_->distributor()); - xds_certificate_provider_->UpdateIdentityCertNameAndDistributor( - "", identity_provider_cert_name, - identity_certificate_provider_ == nullptr - ? nullptr - : identity_certificate_provider_->distributor()); - xds_certificate_provider_->UpdateRequireClientCertificate( - "", listener.filter_chains[0] - .downstream_tls_context.require_client_certificate); - return security_connector_update_required; } + void OnResourceDoesNotExist() override { + OnFatalError(absl::NotFoundError("Requested listener does not exist")); + } + + private: std::unique_ptr server_config_watcher_; grpc_channel_args* args_; RefCountedPtr xds_client_; - RefCountedPtr root_certificate_provider_; - RefCountedPtr identity_certificate_provider_; - RefCountedPtr xds_certificate_provider_; - bool updated_once_ = false; + grpc_server_xds_status_notifier serving_status_notifier_; + std::string listening_address_; + RefCountedPtr filter_chain_match_manager_; }; struct WatcherState { @@ -248,26 +511,36 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher { }; RefCountedPtr xds_client_; + grpc_server_xds_status_notifier serving_status_notifier_; Mutex mu_; std::map - watchers_; + watchers_ ABSL_GUARDED_BY(mu_); }; } // namespace } // namespace grpc_core -grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create() { +grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create( + grpc_server_xds_status_notifier notifier, const grpc_channel_args* args) { grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_server_config_fetcher_xds_create()", 0, ()); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::RefCountedPtr xds_client = - grpc_core::XdsClient::GetOrCreate(&error); + grpc_core::XdsClient::GetOrCreate(args, &error); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Failed to create xds client: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); return nullptr; } - return new grpc_core::XdsServerConfigFetcher(std::move(xds_client)); + if (xds_client->bootstrap() + .server_listener_resource_name_template() + .empty()) { + gpr_log(GPR_ERROR, + "server_listener_resource_name_template not provided in bootstrap " + "file."); + return nullptr; + } + return new grpc_core::XdsServerConfigFetcher(std::move(xds_client), notifier); } diff --git a/src/core/lib/iomgr/parse_address.cc b/src/core/lib/address_utils/parse_address.cc similarity index 90% rename from src/core/lib/iomgr/parse_address.cc rename to src/core/lib/address_utils/parse_address.cc index 9afac74fd41..98dd1bcb87f 100644 --- a/src/core/lib/iomgr/parse_address.cc +++ b/src/core/lib/address_utils/parse_address.cc @@ -18,7 +18,7 @@ #include -#include "src/core/lib/iomgr/parse_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include #include @@ -52,10 +52,10 @@ bool grpc_parse_unix(const grpc_core::URI& uri, uri.scheme().c_str()); return false; } - grpc_error* error = + grpc_error_handle error = grpc_core::UnixSockaddrPopulate(uri.path(), resolved_addr); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "%s", grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); return false; } @@ -69,10 +69,10 @@ bool grpc_parse_unix_abstract(const grpc_core::URI& uri, uri.scheme().c_str()); return false; } - grpc_error* error = + grpc_error_handle error = grpc_core::UnixAbstractSockaddrPopulate(uri.path(), resolved_addr); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "%s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "%s", grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); return false; } @@ -81,8 +81,8 @@ bool grpc_parse_unix_abstract(const grpc_core::URI& uri, namespace grpc_core { -grpc_error* UnixSockaddrPopulate(absl::string_view path, - grpc_resolved_address* resolved_addr) { +grpc_error_handle UnixSockaddrPopulate(absl::string_view path, + grpc_resolved_address* resolved_addr) { struct sockaddr_un* un = reinterpret_cast(resolved_addr->addr); const size_t maxlen = sizeof(un->sun_path) - 1; @@ -99,8 +99,8 @@ grpc_error* UnixSockaddrPopulate(absl::string_view path, return GRPC_ERROR_NONE; } -grpc_error* UnixAbstractSockaddrPopulate(absl::string_view path, - grpc_resolved_address* resolved_addr) { +grpc_error_handle UnixAbstractSockaddrPopulate( + absl::string_view path, grpc_resolved_address* resolved_addr) { struct sockaddr_un* un = reinterpret_cast(resolved_addr->addr); const size_t maxlen = sizeof(un->sun_path) - 1; @@ -122,25 +122,25 @@ grpc_error* UnixAbstractSockaddrPopulate(absl::string_view path, #else /* GRPC_HAVE_UNIX_SOCKET */ -bool grpc_parse_unix(const grpc_core::URI& uri, - grpc_resolved_address* resolved_addr) { +bool grpc_parse_unix(const grpc_core::URI& /* uri */, + grpc_resolved_address* /* resolved_addr */) { abort(); } -bool grpc_parse_unix_abstract(const grpc_core::URI& uri, - grpc_resolved_address* resolved_addr) { +bool grpc_parse_unix_abstract(const grpc_core::URI& /* uri */, + grpc_resolved_address* /* resolved_addr */) { abort(); } namespace grpc_core { -grpc_error* UnixSockaddrPopulate(absl::string_view path, - grpc_resolved_address* resolved_addr) { +grpc_error_handle UnixSockaddrPopulate( + absl::string_view /* path */, grpc_resolved_address* /* resolved_addr */) { abort(); } -grpc_error* UnixAbstractSockaddrPopulate(absl::string_view path, - grpc_resolved_address* resolved_addr) { +grpc_error_handle UnixAbstractSockaddrPopulate( + absl::string_view /* path */, grpc_resolved_address* /* resolved_addr */) { abort(); } diff --git a/src/core/lib/iomgr/parse_address.h b/src/core/lib/address_utils/parse_address.h similarity index 86% rename from src/core/lib/iomgr/parse_address.h rename to src/core/lib/address_utils/parse_address.h index 870afefa4eb..92409b7e813 100644 --- a/src/core/lib/iomgr/parse_address.h +++ b/src/core/lib/address_utils/parse_address.h @@ -16,8 +16,8 @@ * */ -#ifndef GRPC_CORE_LIB_IOMGR_PARSE_ADDRESS_H -#define GRPC_CORE_LIB_IOMGR_PARSE_ADDRESS_H +#ifndef GRPC_CORE_LIB_ADDRESS_UTILS_PARSE_ADDRESS_H +#define GRPC_CORE_LIB_ADDRESS_UTILS_PARSE_ADDRESS_H #include @@ -64,14 +64,14 @@ uint16_t grpc_strhtons(const char* port); namespace grpc_core { /** Populate \a resolved_addr to be a unix socket at |path| */ -grpc_error* UnixSockaddrPopulate(absl::string_view path, - grpc_resolved_address* resolved_addr); +grpc_error_handle UnixSockaddrPopulate(absl::string_view path, + grpc_resolved_address* resolved_addr); /** Populate \a resolved_addr to be a unix socket in the abstract namespace * at |path| */ -grpc_error* UnixAbstractSockaddrPopulate(absl::string_view path, - grpc_resolved_address* resolved_addr); +grpc_error_handle UnixAbstractSockaddrPopulate( + absl::string_view path, grpc_resolved_address* resolved_addr); } // namespace grpc_core -#endif /* GRPC_CORE_LIB_IOMGR_PARSE_ADDRESS_H */ +#endif /* GRPC_CORE_LIB_ADDRESS_UTILS_PARSE_ADDRESS_H */ diff --git a/src/core/lib/iomgr/sockaddr_utils.cc b/src/core/lib/address_utils/sockaddr_utils.cc similarity index 69% rename from src/core/lib/iomgr/sockaddr_utils.cc rename to src/core/lib/address_utils/sockaddr_utils.cc index 692893c0f39..888cd1aa09a 100644 --- a/src/core/lib/iomgr/sockaddr_utils.cc +++ b/src/core/lib/address_utils/sockaddr_utils.cc @@ -18,7 +18,7 @@ #include -#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include #include @@ -198,8 +198,8 @@ std::string grpc_sockaddr_to_string(const grpc_resolved_address* resolved_addr, return out; } -void grpc_string_to_sockaddr(grpc_resolved_address* out, const char* addr, - int port) { +grpc_error_handle grpc_string_to_sockaddr(grpc_resolved_address* out, + const char* addr, int port) { memset(out, 0, sizeof(grpc_resolved_address)); grpc_sockaddr_in6* addr6 = reinterpret_cast(out->addr); grpc_sockaddr_in* addr4 = reinterpret_cast(out->addr); @@ -210,9 +210,11 @@ void grpc_string_to_sockaddr(grpc_resolved_address* out, const char* addr, addr4->sin_family = GRPC_AF_INET; out->len = sizeof(grpc_sockaddr_in); } else { - GPR_ASSERT(0); + return GRPC_ERROR_CREATE_FROM_COPIED_STRING( + absl::StrCat("Failed to parse address:", addr).c_str()); } grpc_sockaddr_set_port(out, port); + return GRPC_ERROR_NONE; } std::string grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) { @@ -294,3 +296,104 @@ int grpc_sockaddr_set_port(grpc_resolved_address* resolved_addr, int port) { return 0; } } + +std::string grpc_sockaddr_get_packed_host( + const grpc_resolved_address* resolved_addr) { + const grpc_sockaddr* addr = + reinterpret_cast(resolved_addr->addr); + if (addr->sa_family == GRPC_AF_INET) { + const grpc_sockaddr_in* addr4 = + reinterpret_cast(addr); + const char* addr_bytes = reinterpret_cast(&addr4->sin_addr); + return std::string(addr_bytes, 4); + } else if (addr->sa_family == GRPC_AF_INET6) { + const grpc_sockaddr_in6* addr6 = + reinterpret_cast(addr); + const char* addr_bytes = reinterpret_cast(&addr6->sin6_addr); + return std::string(addr_bytes, 16); + } else { + GPR_ASSERT(false); + } +} + +void grpc_sockaddr_mask_bits(grpc_resolved_address* address, + uint32_t mask_bits) { + grpc_sockaddr* addr = reinterpret_cast(address->addr); + if (addr->sa_family == GRPC_AF_INET) { + grpc_sockaddr_in* addr4 = reinterpret_cast(addr); + if (mask_bits == 0) { + memset(&addr4->sin_addr, 0, sizeof(addr4->sin_addr)); + return; + } else if (mask_bits >= 32) { + return; + } + uint32_t mask_ip_addr = (~(uint32_t(0))) << (32 - mask_bits); + addr4->sin_addr.s_addr &= grpc_htonl(mask_ip_addr); + } else if (addr->sa_family == GRPC_AF_INET6) { + grpc_sockaddr_in6* addr6 = reinterpret_cast(addr); + if (mask_bits == 0) { + memset(&addr6->sin6_addr, 0, sizeof(addr6->sin6_addr)); + return; + } else if (mask_bits >= 128) { + return; + } + // We cannot use s6_addr32 since it is not defined on all platforms that we + // need it on. + uint32_t address_parts[4]; + GPR_ASSERT(sizeof(addr6->sin6_addr) == sizeof(address_parts)); + memcpy(address_parts, &addr6->sin6_addr, sizeof(grpc_in6_addr)); + if (mask_bits <= 32) { + uint32_t mask_ip_addr = (~(uint32_t(0))) << (32 - mask_bits); + address_parts[0] &= grpc_htonl(mask_ip_addr); + memset(&address_parts[1], 0, sizeof(uint32_t)); + memset(&address_parts[2], 0, sizeof(uint32_t)); + memset(&address_parts[3], 0, sizeof(uint32_t)); + } else if (mask_bits <= 64) { + mask_bits -= 32; + uint32_t mask_ip_addr = (~(uint32_t(0))) << (32 - mask_bits); + address_parts[1] &= grpc_htonl(mask_ip_addr); + memset(&address_parts[2], 0, sizeof(uint32_t)); + memset(&address_parts[3], 0, sizeof(uint32_t)); + } else if (mask_bits <= 96) { + mask_bits -= 64; + uint32_t mask_ip_addr = (~(uint32_t(0))) << (32 - mask_bits); + address_parts[2] &= grpc_htonl(mask_ip_addr); + memset(&address_parts[3], 0, sizeof(uint32_t)); + } else { + mask_bits -= 96; + uint32_t mask_ip_addr = (~(uint32_t(0))) << (32 - mask_bits); + address_parts[3] &= grpc_htonl(mask_ip_addr); + } + memcpy(&addr6->sin6_addr, address_parts, sizeof(grpc_in6_addr)); + } +} + +bool grpc_sockaddr_match_subnet(const grpc_resolved_address* address, + const grpc_resolved_address* subnet_address, + uint32_t mask_bits) { + auto* addr = reinterpret_cast(address->addr); + auto* subnet_addr = + reinterpret_cast(subnet_address->addr); + if (addr->sa_family != subnet_addr->sa_family) return false; + grpc_resolved_address masked_address; + memcpy(&masked_address, address, sizeof(grpc_resolved_address)); + addr = reinterpret_cast((&masked_address)->addr); + grpc_sockaddr_mask_bits(&masked_address, mask_bits); + if (addr->sa_family == GRPC_AF_INET) { + auto* addr4 = reinterpret_cast(addr); + auto* subnet_addr4 = reinterpret_cast(subnet_addr); + if (memcmp(&addr4->sin_addr, &subnet_addr4->sin_addr, + sizeof(addr4->sin_addr)) == 0) { + return true; + } + } else if (addr->sa_family == GRPC_AF_INET6) { + auto* addr6 = reinterpret_cast(addr); + auto* subnet_addr6 = + reinterpret_cast(subnet_addr); + if (memcmp(&addr6->sin6_addr, &subnet_addr6->sin6_addr, + sizeof(addr6->sin6_addr)) == 0) { + return true; + } + } + return false; +} diff --git a/src/core/lib/iomgr/sockaddr_utils.h b/src/core/lib/address_utils/sockaddr_utils.h similarity index 67% rename from src/core/lib/iomgr/sockaddr_utils.h rename to src/core/lib/address_utils/sockaddr_utils.h index ba91e56d008..e8bf79fd3fe 100644 --- a/src/core/lib/iomgr/sockaddr_utils.h +++ b/src/core/lib/address_utils/sockaddr_utils.h @@ -16,8 +16,8 @@ * */ -#ifndef GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H -#define GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H +#ifndef GRPC_CORE_LIB_ADDRESS_UTILS_SOCKADDR_UTILS_H +#define GRPC_CORE_LIB_ADDRESS_UTILS_SOCKADDR_UTILS_H #include @@ -64,10 +64,12 @@ int grpc_sockaddr_set_port(grpc_resolved_address* addr, int port); // If the normalize flag is enabled, ::ffff:0.0.0.0/96 IPv6 addresses are // displayed as plain IPv4. std::string grpc_sockaddr_to_string(const grpc_resolved_address* addr, - bool normalize); + bool normalize) GRPC_MUST_USE_RESULT; -void grpc_string_to_sockaddr(grpc_resolved_address* out, const char* addr, - int port); +// Newer form of grpc_string_to_sockaddr which returns an error instead of +// crashing if \a addr is not IPv6/IPv6 +grpc_error_handle grpc_string_to_sockaddr(grpc_resolved_address* out, + const char* addr, int port); /* Returns the URI string corresponding to \a addr */ std::string grpc_sockaddr_to_uri(const grpc_resolved_address* addr); @@ -77,4 +79,22 @@ const char* grpc_sockaddr_get_uri_scheme(const grpc_resolved_address* addr); int grpc_sockaddr_get_family(const grpc_resolved_address* resolved_addr); -#endif /* GRPC_CORE_LIB_IOMGR_SOCKADDR_UTILS_H */ +std::string grpc_sockaddr_get_packed_host( + const grpc_resolved_address* resolved_addr); + +// Applies a mask of \a mask_bits to IPv4/IPv6 addresses. Has no effect if the +// address type is not IPv4/IPv6. +void grpc_sockaddr_mask_bits(grpc_resolved_address* address, + uint32_t mask_bits); + +// If \a address is IPv4/IPv6, checks if the IP address falls in the CIDR +// specified by \a subnet_address and \a mask_bits. +// Returns false if \a address is not an IPv4/IPv6 address. The ports (if set) +// are ignored for matching purposes. Note that, \a subnet_address should be +// normalized, i.e., `grpc_sockaddr_mask_bits` should have been called on it if +// necessary. +bool grpc_sockaddr_match_subnet(const grpc_resolved_address* address, + const grpc_resolved_address* subnet_address, + uint32_t mask_bits); + +#endif /* GRPC_CORE_LIB_ADDRESS_UTILS_SOCKADDR_UTILS_H */ diff --git a/src/core/lib/channel/channel_stack.cc b/src/core/lib/channel/channel_stack.cc index 60b83667c54..122d7a916fb 100644 --- a/src/core/lib/channel/channel_stack.cc +++ b/src/core/lib/channel/channel_stack.cc @@ -98,7 +98,7 @@ grpc_call_element* grpc_call_stack_element(grpc_call_stack* call_stack, return CALL_ELEMS_FROM_STACK(call_stack) + index; } -grpc_error* grpc_channel_stack_init( +grpc_error_handle grpc_channel_stack_init( int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg, const grpc_channel_filter** filters, size_t filter_count, const grpc_channel_args* channel_args, grpc_transport* optional_transport, @@ -120,7 +120,7 @@ grpc_error* grpc_channel_stack_init( sizeof(grpc_channel_element)); /* init per-filter data */ - grpc_error* first_error = GRPC_ERROR_NONE; + grpc_error_handle first_error = GRPC_ERROR_NONE; for (i = 0; i < filter_count; i++) { args.channel_stack = stack; args.channel_args = channel_args; @@ -129,7 +129,8 @@ grpc_error* grpc_channel_stack_init( args.is_last = i == (filter_count - 1); elems[i].filter = filters[i]; elems[i].channel_data = user_data; - grpc_error* error = elems[i].filter->init_channel_elem(&elems[i], &args); + grpc_error_handle error = + elems[i].filter->init_channel_elem(&elems[i], &args); if (error != GRPC_ERROR_NONE) { if (first_error == GRPC_ERROR_NONE) { first_error = error; @@ -161,10 +162,10 @@ void grpc_channel_stack_destroy(grpc_channel_stack* stack) { } } -grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack, - int initial_refs, grpc_iomgr_cb_func destroy, - void* destroy_arg, - const grpc_call_element_args* elem_args) { +grpc_error_handle grpc_call_stack_init( + grpc_channel_stack* channel_stack, int initial_refs, + grpc_iomgr_cb_func destroy, void* destroy_arg, + const grpc_call_element_args* elem_args) { grpc_channel_element* channel_elems = CHANNEL_ELEMS_FROM_STACK(channel_stack); size_t count = channel_stack->count; grpc_call_element* call_elems; @@ -178,7 +179,7 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(count * sizeof(grpc_call_element)); /* init per-filter data */ - grpc_error* first_error = GRPC_ERROR_NONE; + grpc_error_handle first_error = GRPC_ERROR_NONE; for (size_t i = 0; i < count; i++) { call_elems[i].filter = channel_elems[i].filter; call_elems[i].channel_data = channel_elems[i].channel_data; @@ -187,7 +188,7 @@ grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack, GPR_ROUND_UP_TO_ALIGNMENT_SIZE(call_elems[i].filter->sizeof_call_data); } for (size_t i = 0; i < count; i++) { - grpc_error* error = + grpc_error_handle error = call_elems[i].filter->init_call_elem(&call_elems[i], elem_args); if (error != GRPC_ERROR_NONE) { if (first_error == GRPC_ERROR_NONE) { diff --git a/src/core/lib/channel/channel_stack.h b/src/core/lib/channel/channel_stack.h index 1573ae1e056..4832303caba 100644 --- a/src/core/lib/channel/channel_stack.h +++ b/src/core/lib/channel/channel_stack.h @@ -125,8 +125,8 @@ struct grpc_channel_filter { transport and is on the server. Most filters want to ignore this argument. Implementations may assume that elem->call_data is all zeros. */ - grpc_error* (*init_call_elem)(grpc_call_element* elem, - const grpc_call_element_args* args); + grpc_error_handle (*init_call_elem)(grpc_call_element* elem, + const grpc_call_element_args* args); void (*set_pollset_or_pollset_set)(grpc_call_element* elem, grpc_polling_entity* pollent); /* Destroy per call data. @@ -148,8 +148,8 @@ struct grpc_channel_filter { useful for asserting correct configuration by upper layer code. The filter does not need to do any chaining. Implementations may assume that elem->channel_data is all zeros. */ - grpc_error* (*init_channel_elem)(grpc_channel_element* elem, - grpc_channel_element_args* args); + grpc_error_handle (*init_channel_elem)(grpc_channel_element* elem, + grpc_channel_element_args* args); /* Destroy per channel data. The filter does not need to do any chaining */ void (*destroy_channel_elem)(grpc_channel_element* elem); @@ -218,7 +218,7 @@ grpc_call_element* grpc_call_stack_element(grpc_call_stack* stack, size_t i); size_t grpc_channel_stack_size(const grpc_channel_filter** filters, size_t filter_count); /* Initialize a channel stack given some filters */ -grpc_error* grpc_channel_stack_init( +grpc_error_handle grpc_channel_stack_init( int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg, const grpc_channel_filter** filters, size_t filter_count, const grpc_channel_args* args, grpc_transport* optional_transport, @@ -229,10 +229,11 @@ void grpc_channel_stack_destroy(grpc_channel_stack* stack); /* Initialize a call stack given a channel stack. transport_server_data is expected to be NULL on a client, or an opaque transport owned pointer on the server. */ -grpc_error* grpc_call_stack_init(grpc_channel_stack* channel_stack, - int initial_refs, grpc_iomgr_cb_func destroy, - void* destroy_arg, - const grpc_call_element_args* elem_args); +grpc_error_handle grpc_call_stack_init(grpc_channel_stack* channel_stack, + int initial_refs, + grpc_iomgr_cb_func destroy, + void* destroy_arg, + const grpc_call_element_args* elem_args); /* Set a pollset or a pollset_set for a call stack: must occur before the first * op is started */ void grpc_call_stack_set_pollset_or_pollset_set(grpc_call_stack* call_stack, diff --git a/src/core/lib/channel/channel_stack_builder.cc b/src/core/lib/channel/channel_stack_builder.cc index 8b3008f2217..7f7cf75328b 100644 --- a/src/core/lib/channel/channel_stack_builder.cc +++ b/src/core/lib/channel/channel_stack_builder.cc @@ -267,7 +267,7 @@ void grpc_channel_stack_builder_destroy(grpc_channel_stack_builder* builder) { gpr_free(builder); } -grpc_error* grpc_channel_stack_builder_finish( +grpc_error_handle grpc_channel_stack_builder_finish( grpc_channel_stack_builder* builder, size_t prefix_bytes, int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg, void** result) { // count the number of filters @@ -294,7 +294,7 @@ grpc_error* grpc_channel_stack_builder_finish( grpc_channel_stack* channel_stack = reinterpret_cast( static_cast(*result) + prefix_bytes); // and initialize it - grpc_error* error = grpc_channel_stack_init( + grpc_error_handle error = grpc_channel_stack_init( initial_refs, destroy, destroy_arg == nullptr ? *result : destroy_arg, filters, num_filters, builder->args, builder->transport, builder->name, channel_stack); diff --git a/src/core/lib/channel/channel_stack_builder.h b/src/core/lib/channel/channel_stack_builder.h index 89c30e0c5ea..6782a1484cd 100644 --- a/src/core/lib/channel/channel_stack_builder.h +++ b/src/core/lib/channel/channel_stack_builder.h @@ -156,7 +156,7 @@ void grpc_channel_stack_builder_iterator_destroy( /// Returns the base pointer of the allocated block /// \a initial_refs, \a destroy, \a destroy_arg are as per /// grpc_channel_stack_init -grpc_error* grpc_channel_stack_builder_finish( +grpc_error_handle grpc_channel_stack_builder_finish( grpc_channel_stack_builder* builder, size_t prefix_bytes, int initial_refs, grpc_iomgr_cb_func destroy, void* destroy_arg, void** result); diff --git a/src/core/lib/channel/channelz.cc b/src/core/lib/channel/channelz.cc index 188203cbbbe..452d6641113 100644 --- a/src/core/lib/channel/channelz.cc +++ b/src/core/lib/channel/channelz.cc @@ -20,16 +20,19 @@ #include "src/core/lib/channel/channelz.h" +#include +#include +#include + +#include "absl/strings/escaping.h" #include "absl/strings/strip.h" #include #include #include #include -#include -#include -#include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channelz_registry.h" #include "src/core/lib/channel/status_util.h" #include "src/core/lib/gpr/string.h" @@ -39,6 +42,7 @@ #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/slice/b64.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/channel.h" @@ -336,6 +340,83 @@ Json ServerNode::RenderJson() { return object; } +// +// SocketNode::Security::Tls +// + +Json SocketNode::Security::Tls::RenderJson() { + Json::Object data; + if (type == NameType::kStandardName) { + data["standard_name"] = name; + } else if (type == NameType::kOtherName) { + data["other_name"] = name; + } + if (!local_certificate.empty()) { + data["local_certificate"] = absl::Base64Escape(local_certificate); + } + if (!remote_certificate.empty()) { + data["remote_certificate"] = absl::Base64Escape(remote_certificate); + } + return data; +} + +// +// SocketNode::Security +// + +Json SocketNode::Security::RenderJson() { + Json::Object data; + switch (type) { + case ModelType::kUnset: + break; + case ModelType::kTls: + if (tls) { + data["tls"] = tls->RenderJson(); + } + break; + case ModelType::kOther: + if (other) { + data["other"] = *other; + } + break; + } + return data; +} + +namespace { + +void* SecurityArgCopy(void* p) { + SocketNode::Security* xds_certificate_provider = + static_cast(p); + return xds_certificate_provider->Ref().release(); +} + +void SecurityArgDestroy(void* p) { + SocketNode::Security* xds_certificate_provider = + static_cast(p); + xds_certificate_provider->Unref(); +} + +int SecurityArgCmp(void* p, void* q) { return GPR_ICMP(p, q); } + +const grpc_arg_pointer_vtable kChannelArgVtable = { + SecurityArgCopy, SecurityArgDestroy, SecurityArgCmp}; + +} // namespace + +grpc_arg SocketNode::Security::MakeChannelArg() const { + return grpc_channel_arg_pointer_create( + const_cast(GRPC_ARG_CHANNELZ_SECURITY), + const_cast(this), &kChannelArgVtable); +} + +RefCountedPtr SocketNode::Security::GetFromChannelArgs( + const grpc_channel_args* args) { + Security* security = grpc_channel_args_find_pointer( + args, GRPC_ARG_CHANNELZ_SECURITY); + return security != nullptr ? security->Ref() : nullptr; +} + // // SocketNode // @@ -356,13 +437,22 @@ void PopulateSocketAddressJson(Json::Object* json, const char* name, if (!port.empty()) { port_num = atoi(port.data()); } - char* b64_host = grpc_base64_encode(host.data(), host.size(), false, false); - data["tcpip_address"] = Json::Object{ - {"port", port_num}, - {"ip_address", b64_host}, - }; - gpr_free(b64_host); - } else if (uri.ok() && uri->scheme() == "unix") { + grpc_resolved_address resolved_host; + grpc_error_handle error = + grpc_string_to_sockaddr(&resolved_host, host.c_str(), port_num); + if (error == GRPC_ERROR_NONE) { + std::string packed_host = grpc_sockaddr_get_packed_host(&resolved_host); + std::string b64_host = absl::Base64Escape(packed_host); + data["tcpip_address"] = Json::Object{ + {"port", port_num}, + {"ip_address", b64_host}, + }; + (*json)[name] = std::move(data); + return; + } + GRPC_ERROR_UNREF(error); + } + if (uri.ok() && uri->scheme() == "unix") { data["uds_address"] = Json::Object{ {"filename", uri->path()}, }; @@ -376,10 +466,12 @@ void PopulateSocketAddressJson(Json::Object* json, const char* name, } // namespace -SocketNode::SocketNode(std::string local, std::string remote, std::string name) +SocketNode::SocketNode(std::string local, std::string remote, std::string name, + RefCountedPtr security) : BaseNode(EntityType::kSocket, std::move(name)), local_(std::move(local)), - remote_(std::move(remote)) {} + remote_(std::move(remote)), + security_(std::move(security)) {} void SocketNode::RecordStreamStartedFromLocal() { streams_started_.FetchAdd(1, MemoryOrder::RELAXED); @@ -467,6 +559,10 @@ Json SocketNode::RenderJson() { }}, {"data", std::move(data)}, }; + if (security_ != nullptr && + security_->type != SocketNode::Security::ModelType::kUnset) { + object["security"] = security_->RenderJson(); + } PopulateSocketAddressJson(&object, "remote", remote_.c_str()); PopulateSocketAddressJson(&object, "local", local_.c_str()); return object; diff --git a/src/core/lib/channel/channelz.h b/src/core/lib/channel/channelz.h index 3c558735e6f..a0a449ef8b0 100644 --- a/src/core/lib/channel/channelz.h +++ b/src/core/lib/channel/channelz.h @@ -27,6 +27,7 @@ #include #include "absl/container/inlined_vector.h" +#include "absl/types/optional.h" #include "src/core/lib/channel/channel_trace.h" #include "src/core/lib/gpr/time_precise.h" @@ -268,10 +269,37 @@ class ServerNode : public BaseNode { std::map> child_listen_sockets_; }; +#define GRPC_ARG_CHANNELZ_SECURITY "grpc.internal.channelz_security" + // Handles channelz bookkeeping for sockets class SocketNode : public BaseNode { public: - SocketNode(std::string local, std::string remote, std::string name); + struct Security : public RefCounted { + struct Tls { + enum class NameType { kUnset = 0, kStandardName = 1, kOtherName = 2 }; + NameType type = NameType::kUnset; + // Holds the value of standard_name or other_names if type is not kUnset. + std::string name; + std::string local_certificate; + std::string remote_certificate; + + Json RenderJson(); + }; + enum class ModelType { kUnset = 0, kTls = 1, kOther = 2 }; + ModelType type = ModelType::kUnset; + absl::optional tls; + absl::optional other; + + Json RenderJson(); + + grpc_arg MakeChannelArg() const; + + static RefCountedPtr GetFromChannelArgs( + const grpc_channel_args* args); + }; + + SocketNode(std::string local, std::string remote, std::string name, + RefCountedPtr security); ~SocketNode() override {} Json RenderJson() override; @@ -305,6 +333,7 @@ class SocketNode : public BaseNode { Atomic last_message_received_cycle_{0}; std::string local_; std::string remote_; + RefCountedPtr const security_; }; // Handles channelz bookkeeping for listen sockets diff --git a/src/core/lib/channel/channelz_registry.cc b/src/core/lib/channel/channelz_registry.cc index 6eea6eb5824..c76b5b43795 100644 --- a/src/core/lib/channel/channelz_registry.cc +++ b/src/core/lib/channel/channelz_registry.cc @@ -181,18 +181,24 @@ void ChannelzRegistry::InternalLogAllEntities() { } // namespace grpc_core char* grpc_channelz_get_top_channels(intptr_t start_channel_id) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; return gpr_strdup( grpc_core::channelz::ChannelzRegistry::GetTopChannels(start_channel_id) .c_str()); } char* grpc_channelz_get_servers(intptr_t start_server_id) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; return gpr_strdup( grpc_core::channelz::ChannelzRegistry::GetServers(start_server_id) .c_str()); } char* grpc_channelz_get_server(intptr_t server_id) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; grpc_core::RefCountedPtr server_node = grpc_core::channelz::ChannelzRegistry::Get(server_id); if (server_node == nullptr || @@ -209,6 +215,8 @@ char* grpc_channelz_get_server(intptr_t server_id) { char* grpc_channelz_get_server_sockets(intptr_t server_id, intptr_t start_socket_id, intptr_t max_results) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; // Validate inputs before handing them of to the renderer. grpc_core::RefCountedPtr base_node = grpc_core::channelz::ChannelzRegistry::Get(server_id); @@ -226,6 +234,8 @@ char* grpc_channelz_get_server_sockets(intptr_t server_id, } char* grpc_channelz_get_channel(intptr_t channel_id) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; grpc_core::RefCountedPtr channel_node = grpc_core::channelz::ChannelzRegistry::Get(channel_id); if (channel_node == nullptr || @@ -242,6 +252,8 @@ char* grpc_channelz_get_channel(intptr_t channel_id) { } char* grpc_channelz_get_subchannel(intptr_t subchannel_id) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; grpc_core::RefCountedPtr subchannel_node = grpc_core::channelz::ChannelzRegistry::Get(subchannel_id); if (subchannel_node == nullptr || @@ -256,6 +268,8 @@ char* grpc_channelz_get_subchannel(intptr_t subchannel_id) { } char* grpc_channelz_get_socket(intptr_t socket_id) { + grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; + grpc_core::ExecCtx exec_ctx; grpc_core::RefCountedPtr socket_node = grpc_core::channelz::ChannelzRegistry::Get(socket_id); if (socket_node == nullptr || diff --git a/src/core/lib/channel/connected_channel.cc b/src/core/lib/channel/connected_channel.cc index be74d9e88bb..12b3d786097 100644 --- a/src/core/lib/channel/connected_channel.cc +++ b/src/core/lib/channel/connected_channel.cc @@ -53,13 +53,13 @@ typedef struct connected_channel_call_data { callback_state recv_trailing_metadata_ready; } call_data; -static void run_in_call_combiner(void* arg, grpc_error* error) { +static void run_in_call_combiner(void* arg, grpc_error_handle error) { callback_state* state = static_cast(arg); GRPC_CALL_COMBINER_START(state->call_combiner, state->original_closure, GRPC_ERROR_REF(error), state->reason); } -static void run_cancel_in_call_combiner(void* arg, grpc_error* error) { +static void run_cancel_in_call_combiner(void* arg, grpc_error_handle error) { run_in_call_combiner(arg, error); gpr_free(arg); } @@ -146,7 +146,7 @@ static void connected_channel_start_transport_op(grpc_channel_element* elem, } /* Constructor for call_data */ -static grpc_error* connected_channel_init_call_elem( +static grpc_error_handle connected_channel_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* args) { call_data* calld = static_cast(elem->call_data); channel_data* chand = static_cast(elem->channel_data); @@ -179,7 +179,7 @@ static void connected_channel_destroy_call_elem( } /* Constructor for channel_data */ -static grpc_error* connected_channel_init_channel_elem( +static grpc_error_handle connected_channel_init_channel_elem( grpc_channel_element* elem, grpc_channel_element_args* args) { channel_data* cd = static_cast(elem->channel_data); GPR_ASSERT(args->is_last); diff --git a/src/core/lib/channel/handshaker.cc b/src/core/lib/channel/handshaker.cc index 000a7d2e26b..632d2864e31 100644 --- a/src/core/lib/channel/handshaker.cc +++ b/src/core/lib/channel/handshaker.cc @@ -55,44 +55,6 @@ std::string HandshakerArgsString(HandshakerArgs* args) { HandshakeManager::HandshakeManager() {} -/// Add \a mgr to the server side list of all pending handshake managers, the -/// list starts with \a *head. -// Not thread-safe. Caller needs to synchronize. -void HandshakeManager::AddToPendingMgrList(HandshakeManager** head) { - GPR_ASSERT(prev_ == nullptr); - GPR_ASSERT(next_ == nullptr); - next_ = *head; - if (*head) { - (*head)->prev_ = this; - } - *head = this; -} - -/// Remove \a mgr from the server side list of all pending handshake managers. -// Not thread-safe. Caller needs to synchronize. -void HandshakeManager::RemoveFromPendingMgrList(HandshakeManager** head) { - if (next_ != nullptr) { - next_->prev_ = prev_; - } - if (prev_ != nullptr) { - prev_->next_ = next_; - } else { - GPR_ASSERT(*head == this); - *head = next_; - } -} - -/// Shutdown all pending handshake managers starting at head on the server -/// side. Not thread-safe. Caller needs to synchronize. -void HandshakeManager::ShutdownAllPending(grpc_error* why) { - auto* head = this; - while (head != nullptr) { - head->Shutdown(GRPC_ERROR_REF(why)); - head = head->next_; - } - GRPC_ERROR_UNREF(why); -} - void HandshakeManager::Add(RefCountedPtr handshaker) { if (GRPC_TRACE_FLAG_ENABLED(grpc_handshaker_trace)) { gpr_log( @@ -106,7 +68,7 @@ void HandshakeManager::Add(RefCountedPtr handshaker) { HandshakeManager::~HandshakeManager() { handshakers_.clear(); } -void HandshakeManager::Shutdown(grpc_error* why) { +void HandshakeManager::Shutdown(grpc_error_handle why) { { MutexLock lock(&mu_); // Shutdown the handshaker that's currently in progress, if any. @@ -121,12 +83,12 @@ void HandshakeManager::Shutdown(grpc_error* why) { // Helper function to call either the next handshaker or the // on_handshake_done callback. // Returns true if we've scheduled the on_handshake_done callback. -bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) { +bool HandshakeManager::CallNextHandshakerLocked(grpc_error_handle error) { if (GRPC_TRACE_FLAG_ENABLED(grpc_handshaker_trace)) { gpr_log(GPR_INFO, "handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR ", args=%s", - this, grpc_error_string(error), is_shutdown_, index_, + this, grpc_error_std_string(error).c_str(), is_shutdown_, index_, HandshakerArgsString(&args_).c_str()); } GPR_ASSERT(index_ <= handshakers_.size()); @@ -159,7 +121,7 @@ bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) { gpr_log(GPR_INFO, "handshake_manager %p: handshaking complete -- scheduling " "on_handshake_done with error=%s", - this, grpc_error_string(error)); + this, grpc_error_std_string(error).c_str()); } // Cancel deadline timer, since we're invoking the on_handshake_done // callback now. @@ -180,7 +142,8 @@ bool HandshakeManager::CallNextHandshakerLocked(grpc_error* error) { return is_shutdown_; } -void HandshakeManager::CallNextHandshakerFn(void* arg, grpc_error* error) { +void HandshakeManager::CallNextHandshakerFn(void* arg, + grpc_error_handle error) { auto* mgr = static_cast(arg); bool done; { @@ -195,7 +158,7 @@ void HandshakeManager::CallNextHandshakerFn(void* arg, grpc_error* error) { } } -void HandshakeManager::OnTimeoutFn(void* arg, grpc_error* error) { +void HandshakeManager::OnTimeoutFn(void* arg, grpc_error_handle error) { auto* mgr = static_cast(arg); if (error == GRPC_ERROR_NONE) { // Timer fired, rather than being cancelled mgr->Shutdown(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshake timed out")); @@ -213,7 +176,6 @@ void HandshakeManager::DoHandshake(grpc_endpoint* endpoint, { MutexLock lock(&mu_); GPR_ASSERT(index_ == 0); - GPR_ASSERT(!is_shutdown_); // Construct handshaker args. These will be passed through all // handshakers and eventually be freed by the on_handshake_done callback. args_.endpoint = endpoint; diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h index 3dc6da85966..b6b69da57d9 100644 --- a/src/core/lib/channel/handshaker.h +++ b/src/core/lib/channel/handshaker.h @@ -78,7 +78,7 @@ struct HandshakerArgs { class Handshaker : public RefCounted { public: ~Handshaker() override = default; - virtual void Shutdown(grpc_error* why) = 0; + virtual void Shutdown(grpc_error_handle why) = 0; virtual void DoHandshake(grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, HandshakerArgs* args) = 0; @@ -94,26 +94,13 @@ class HandshakeManager : public RefCounted { HandshakeManager(); ~HandshakeManager() override; - /// Add \a mgr to the server side list of all pending handshake managers, the - /// list starts with \a *head. - // Not thread-safe. Caller needs to synchronize. - void AddToPendingMgrList(HandshakeManager** head); - - /// Remove \a mgr from the server side list of all pending handshake managers. - // Not thread-safe. Caller needs to synchronize. - void RemoveFromPendingMgrList(HandshakeManager** head); - - /// Shutdown all pending handshake managers starting at head on the server - /// side. Not thread-safe. Caller needs to synchronize. - void ShutdownAllPending(grpc_error* why); - /// Adds a handshaker to the handshake manager. /// Takes ownership of \a handshaker. void Add(RefCountedPtr handshaker); /// Shuts down the handshake manager (e.g., to clean up when the operation is /// aborted in the middle). - void Shutdown(grpc_error* why); + void Shutdown(grpc_error_handle why); /// Invokes handshakers in the order they were added. /// Takes ownership of \a endpoint, and then passes that ownership to @@ -133,14 +120,14 @@ class HandshakeManager : public RefCounted { grpc_iomgr_cb_func on_handshake_done, void* user_data); private: - bool CallNextHandshakerLocked(grpc_error* error); + bool CallNextHandshakerLocked(grpc_error_handle error); // A function used as the handshaker-done callback when chaining // handshakers together. - static void CallNextHandshakerFn(void* arg, grpc_error* error); + static void CallNextHandshakerFn(void* arg, grpc_error_handle error); // Callback invoked when deadline is exceeded. - static void OnTimeoutFn(void* arg, grpc_error* error); + static void OnTimeoutFn(void* arg, grpc_error_handle error); static const size_t HANDSHAKERS_INIT_SIZE = 2; @@ -161,10 +148,6 @@ class HandshakeManager : public RefCounted { grpc_closure on_handshake_done_; // Handshaker args. HandshakerArgs args_; - // Links to the previous and next managers in a list of all pending handshakes - // Used at server side only. - HandshakeManager* prev_ = nullptr; - HandshakeManager* next_ = nullptr; }; } // namespace grpc_core diff --git a/src/core/lib/channel/status_util.cc b/src/core/lib/channel/status_util.cc index 39f310a165b..0c60030d5a9 100644 --- a/src/core/lib/channel/status_util.cc +++ b/src/core/lib/channel/status_util.cc @@ -75,8 +75,6 @@ const char* grpc_status_code_to_string(grpc_status_code status) { return "ALREADY_EXISTS"; case GRPC_STATUS_PERMISSION_DENIED: return "PERMISSION_DENIED"; - case GRPC_STATUS_UNAUTHENTICATED: - return "UNAUTHENTICATED"; case GRPC_STATUS_RESOURCE_EXHAUSTED: return "RESOURCE_EXHAUSTED"; case GRPC_STATUS_FAILED_PRECONDITION: @@ -93,7 +91,19 @@ const char* grpc_status_code_to_string(grpc_status_code status) { return "UNAVAILABLE"; case GRPC_STATUS_DATA_LOSS: return "DATA_LOSS"; + case GRPC_STATUS_UNAUTHENTICATED: + return "UNAUTHENTICATED"; default: return "UNKNOWN"; } } + +bool grpc_status_code_from_int(int status_int, grpc_status_code* status) { + // The range of status code enum is [0, 16], 0 is OK, 16 is UNAUTHENTICATED. + if (status_int < GRPC_STATUS_OK || status_int > GRPC_STATUS_UNAUTHENTICATED) { + *status = GRPC_STATUS_UNKNOWN; + return false; + } + *status = static_cast(status_int); + return true; +} diff --git a/src/core/lib/channel/status_util.h b/src/core/lib/channel/status_util.h index 5409de6b3c9..969033ad6b6 100644 --- a/src/core/lib/channel/status_util.h +++ b/src/core/lib/channel/status_util.h @@ -34,6 +34,11 @@ bool grpc_status_code_from_string(const char* status_str, /// Returns the string form of \a status, or "UNKNOWN" if invalid. const char* grpc_status_code_to_string(grpc_status_code status); +// Converts an int to grpc_status_code. If the int is not a valid status code, +// sets the code to GRPC_STATUS_UNKNOWN and returns false. Otherwise, returns +// true. +bool grpc_status_code_from_int(int status_int, grpc_status_code* status); + namespace grpc_core { namespace internal { diff --git a/src/core/lib/event_engine/slice_allocator.cc b/src/core/lib/event_engine/slice_allocator.cc new file mode 100644 index 00000000000..3ea615acdd7 --- /dev/null +++ b/src/core/lib/event_engine/slice_allocator.cc @@ -0,0 +1,59 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include "grpc/event_engine/slice_allocator.h" + +#include + +#include "absl/status/status.h" + +#include "src/core/lib/iomgr/resource_quota.h" + +namespace grpc_event_engine { +namespace experimental { + +SliceAllocator::SliceAllocator(grpc_resource_user* user) + : resource_user_(user) { + grpc_resource_user_ref(resource_user_); +}; + +SliceAllocator::~SliceAllocator() { grpc_resource_user_unref(resource_user_); }; + +absl::Status SliceAllocator::Allocate(size_t size, SliceBuffer* dest, + SliceAllocator::AllocateCallback cb) { + // TODO(hork): implement + (void)size; + (void)dest; + (void)cb; + return absl::OkStatus(); +}; + +SliceAllocatorFactory::SliceAllocatorFactory(grpc_resource_quota* quota) + : resource_quota_(quota) { + grpc_resource_quota_ref_internal(resource_quota_); +}; + +SliceAllocatorFactory::~SliceAllocatorFactory() { + grpc_resource_quota_unref_internal(resource_quota_); +} + +SliceAllocator SliceAllocatorFactory::CreateSliceAllocator( + absl::string_view peer_name) { + return SliceAllocator( + grpc_resource_user_create(resource_quota_, peer_name.data())); +} + +} // namespace experimental +} // namespace grpc_event_engine diff --git a/src/core/lib/event_engine/sockaddr.cc b/src/core/lib/event_engine/sockaddr.cc new file mode 100644 index 00000000000..811d351936a --- /dev/null +++ b/src/core/lib/event_engine/sockaddr.cc @@ -0,0 +1,38 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#include + +#include "grpc/event_engine/event_engine.h" +#include "grpc/event_engine/port.h" +#include "grpc/support/log.h" + +namespace grpc_event_engine { +namespace experimental { + +EventEngine::ResolvedAddress::ResolvedAddress(const sockaddr* address, + socklen_t size) { + GPR_ASSERT(size <= sizeof(address_)); + memcpy(&address_, address, size); +} + +const struct sockaddr* EventEngine::ResolvedAddress::address() const { + return reinterpret_cast(address_); +} + +socklen_t EventEngine::ResolvedAddress::size() const { return size_; } + +} // namespace experimental +} // namespace grpc_event_engine diff --git a/src/core/lib/gpr/sync_abseil.cc b/src/core/lib/gpr/sync_abseil.cc index 56b1cc7b4a2..0da9caa9d24 100644 --- a/src/core/lib/gpr/sync_abseil.cc +++ b/src/core/lib/gpr/sync_abseil.cc @@ -62,8 +62,7 @@ void gpr_mu_unlock(gpr_mu* mu) ABSL_NO_THREAD_SAFETY_ANALYSIS { int gpr_mu_trylock(gpr_mu* mu) { GPR_TIMER_SCOPE("gpr_mu_trylock", 0); - int ret = reinterpret_cast(mu)->TryLock() == true; - return ret; + return reinterpret_cast(mu)->TryLock(); } /*----------------------------------------*/ @@ -89,10 +88,8 @@ int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) { abs_deadline = gpr_convert_clock_type(abs_deadline, GPR_CLOCK_REALTIME); timespec ts = {static_cast(abs_deadline.tv_sec), static_cast(abs_deadline.tv_nsec)}; - int ret = reinterpret_cast(cv)->WaitWithDeadline( - reinterpret_cast(mu), - absl::TimeFromTimespec(ts)) == true; - return ret; + return reinterpret_cast(cv)->WaitWithDeadline( + reinterpret_cast(mu), absl::TimeFromTimespec(ts)); } void gpr_cv_signal(gpr_cv* cv) { diff --git a/src/core/lib/gprpp/atomic.h b/src/core/lib/gprpp/atomic.h index 4a53d2cfa55..dd99d9ed4d7 100644 --- a/src/core/lib/gprpp/atomic.h +++ b/src/core/lib/gprpp/atomic.h @@ -81,8 +81,8 @@ class Atomic { // Atomically increment a counter only if the counter value is not zero. // Returns true if increment took place; false if counter is zero. - bool IncrementIfNonzero(MemoryOrder load_order = MemoryOrder::ACQUIRE) { - T count = storage_.load(static_cast(load_order)); + bool IncrementIfNonzero() { + T count = storage_.load(std::memory_order_acquire); do { // If zero, we are done (without an increment). If not, we must do a CAS // to maintain the contract: do not increment the counter if it is already @@ -91,7 +91,7 @@ class Atomic { return false; } } while (!CompareExchangeWeak(&count, count + 1, MemoryOrder::ACQ_REL, - load_order)); + MemoryOrder::ACQUIRE)); return true; } diff --git a/src/core/lib/gprpp/dual_ref_counted.h b/src/core/lib/gprpp/dual_ref_counted.h index 57ee1a9fe09..5217bfa1067 100644 --- a/src/core/lib/gprpp/dual_ref_counted.h +++ b/src/core/lib/gprpp/dual_ref_counted.h @@ -195,7 +195,7 @@ class DualRefCounted : public Orphanable { #ifndef NDEBUG const uint32_t weak_refs = GetWeakRefs(prev_ref_pair); const uint32_t strong_refs = GetStrongRefs(prev_ref_pair); - if (trace_ != nullptr) { + if (trace != nullptr) { gpr_log(GPR_INFO, "%s:%p %s:%d weak_unref %d -> %d (refs=%d) %s", trace, this, location.file(), location.line(), weak_refs, weak_refs - 1, strong_refs, reason); diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h index 47e2aadc374..a8def8c94d6 100644 --- a/src/core/lib/gprpp/ref_counted.h +++ b/src/core/lib/gprpp/ref_counted.h @@ -215,31 +215,45 @@ class NonPolymorphicRefCount { ~NonPolymorphicRefCount() = default; }; +// Behavior of RefCounted<> upon ref count reaching 0. +enum UnrefBehavior { + // Default behavior: Delete the object. + kUnrefDelete, + // Do not delete the object upon unref. This is useful in cases where all + // existing objects must be tracked in a registry but the object's entry in + // the registry cannot be removed from the object's dtor due to + // synchronization issues. In this case, the registry can be cleaned up + // later by identifying entries for which RefIfNonZero() returns null. + kUnrefNoDelete, + // Call the object's dtor but do not delete it. This is useful for cases + // where the object is stored in memory allocated elsewhere (e.g., the call + // arena). + kUnrefCallDtor, +}; + namespace internal { -template +template class Delete; template -class Delete { +class Delete { public: explicit Delete(T* t) { delete t; } }; template -class Delete { +class Delete { public: explicit Delete(T* /*t*/) {} }; +template +class Delete { + public: + explicit Delete(T* t) { t->~T(); } +}; } // namespace internal // A base class for reference-counted objects. // New objects should be created via new and start with a refcount of 1. -// When the refcount reaches 0, the object will be deleted via delete. -// -// If DeleteUponUnref is false, deletion will not occur when the ref -// count reaches 0. This is useful in cases where all existing objects -// must be tracked in a registry but the object's entry in the registry -// cannot be removed from the object's dtor due to synchronization issues. -// In this case, the registry can be cleaned up later by identifying -// entries for which RefIfNonZero() returns null. +// When the refcount reaches 0, executes the specified UnrefBehavior. // // This will commonly be used by CRTP (curiously-recurring template pattern) // e.g., class MyClass : public RefCounted @@ -264,7 +278,7 @@ class Delete { // ch->Unref(); // template + UnrefBehavior UnrefBehaviorArg = kUnrefDelete> class RefCounted : public Impl { public: // Note: Depending on the Impl used, this dtor can be implicitly virtual. @@ -287,12 +301,12 @@ class RefCounted : public Impl { // friend of this class. void Unref() { if (GPR_UNLIKELY(refs_.Unref())) { - internal::Delete(static_cast(this)); + internal::Delete(static_cast(this)); } } void Unref(const DebugLocation& location, const char* reason) { if (GPR_UNLIKELY(refs_.Unref(location, reason))) { - internal::Delete(static_cast(this)); + internal::Delete(static_cast(this)); } } diff --git a/src/core/lib/gprpp/ref_counted_ptr.h b/src/core/lib/gprpp/ref_counted_ptr.h index fd3bfbda87c..4ee1b950818 100644 --- a/src/core/lib/gprpp/ref_counted_ptr.h +++ b/src/core/lib/gprpp/ref_counted_ptr.h @@ -83,6 +83,7 @@ class RefCountedPtr { } // Copy assignment. + // NOLINTNEXTLINE(bugprone-unhandled-self-assignment) RefCountedPtr& operator=(const RefCountedPtr& other) { // Note: Order of reffing and unreffing is important here in case value_ // and other.value_ are the same object. @@ -235,6 +236,7 @@ class WeakRefCountedPtr { } // Copy assignment. + // NOLINTNEXTLINE(bugprone-unhandled-self-assignment) WeakRefCountedPtr& operator=(const WeakRefCountedPtr& other) { // Note: Order of reffing and unreffing is important here in case value_ // and other.value_ are the same object. diff --git a/src/core/lib/gprpp/status_helper.cc b/src/core/lib/gprpp/status_helper.cc new file mode 100644 index 00000000000..8266e167466 --- /dev/null +++ b/src/core/lib/gprpp/status_helper.cc @@ -0,0 +1,407 @@ +// +// +// Copyright 2021 the gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include + +#include "src/core/lib/gprpp/status_helper.h" +#include "src/core/lib/gprpp/time_util.h" + +#include + +#include "absl/strings/cord.h" +#include "absl/strings/escaping.h" +#include "absl/strings/match.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" +#include "absl/time/clock.h" + +#include "google/protobuf/any.upb.h" +#include "google/rpc/status.upb.h" +#include "upb/upb.hpp" + +namespace grpc_core { + +namespace { + +#define TYPE_URL_PREFIX "type.googleapis.com/grpc.status." +#define TYPE_INT_TAG "int." +#define TYPE_STR_TAG "str." +#define TYPE_TIME_TAG "time." +#define TYPE_CHILDREN_TAG "children" +#define TYPE_URL(name) (TYPE_URL_PREFIX name) +const absl::string_view kTypeUrlPrefix = TYPE_URL_PREFIX; +const absl::string_view kTypeIntTag = TYPE_INT_TAG; +const absl::string_view kTypeStrTag = TYPE_STR_TAG; +const absl::string_view kTypeTimeTag = TYPE_TIME_TAG; +const absl::string_view kTypeChildrenTag = TYPE_CHILDREN_TAG; +const absl::string_view kChildrenPropertyUrl = TYPE_URL(TYPE_CHILDREN_TAG); + +const char* GetStatusIntPropertyUrl(StatusIntProperty key) { + switch (key) { + case StatusIntProperty::kErrorNo: + return TYPE_URL(TYPE_INT_TAG "errno"); + case StatusIntProperty::kFileLine: + return TYPE_URL(TYPE_INT_TAG "file_line"); + case StatusIntProperty::kStreamId: + return TYPE_URL(TYPE_INT_TAG "stream_id"); + case StatusIntProperty::kRpcStatus: + return TYPE_URL(TYPE_INT_TAG "grpc_status"); + case StatusIntProperty::kOffset: + return TYPE_URL(TYPE_INT_TAG "offset"); + case StatusIntProperty::kIndex: + return TYPE_URL(TYPE_INT_TAG "index"); + case StatusIntProperty::kSize: + return TYPE_URL(TYPE_INT_TAG "size"); + case StatusIntProperty::kHttp2Error: + return TYPE_URL(TYPE_INT_TAG "http2_error"); + case StatusIntProperty::kTsiCode: + return TYPE_URL(TYPE_INT_TAG "tsi_code"); + case StatusIntProperty::kWsaError: + return TYPE_URL(TYPE_INT_TAG "wsa_error"); + case StatusIntProperty::kFd: + return TYPE_URL(TYPE_INT_TAG "fd"); + case StatusIntProperty::kHttpStatus: + return TYPE_URL(TYPE_INT_TAG "http_status"); + case StatusIntProperty::kOccurredDuringWrite: + return TYPE_URL(TYPE_INT_TAG "occurred_during_write"); + case StatusIntProperty::ChannelConnectivityState: + return TYPE_URL(TYPE_INT_TAG "channel_connectivity_state"); + case StatusIntProperty::kLbPolicyDrop: + return TYPE_URL(TYPE_INT_TAG "lb_policy_drop"); + } + GPR_UNREACHABLE_CODE(return "unknown"); +} + +const char* GetStatusStrPropertyUrl(StatusStrProperty key) { + switch (key) { + case StatusStrProperty::kDescription: + return TYPE_URL(TYPE_STR_TAG "description"); + case StatusStrProperty::kFile: + return TYPE_URL(TYPE_STR_TAG "file"); + case StatusStrProperty::kOsError: + return TYPE_URL(TYPE_STR_TAG "os_error"); + case StatusStrProperty::kSyscall: + return TYPE_URL(TYPE_STR_TAG "syscall"); + case StatusStrProperty::kTargetAddress: + return TYPE_URL(TYPE_STR_TAG "target_address"); + case StatusStrProperty::kGrpcMessage: + return TYPE_URL(TYPE_STR_TAG "grpc_message"); + case StatusStrProperty::kRawBytes: + return TYPE_URL(TYPE_STR_TAG "raw_bytes"); + case StatusStrProperty::kTsiError: + return TYPE_URL(TYPE_STR_TAG "tsi_error"); + case StatusStrProperty::kFilename: + return TYPE_URL(TYPE_STR_TAG "filename"); + case StatusStrProperty::kKey: + return TYPE_URL(TYPE_STR_TAG "key"); + case StatusStrProperty::kValue: + return TYPE_URL(TYPE_STR_TAG "value"); + } + GPR_UNREACHABLE_CODE(return "unknown"); +} + +const char* GetStatusTimePropertyUrl(StatusTimeProperty key) { + switch (key) { + case StatusTimeProperty::kCreated: + return TYPE_URL(TYPE_TIME_TAG "created_time"); + } + GPR_UNREACHABLE_CODE(return "unknown"); +} + +void EncodeUInt32ToBytes(uint32_t v, char* buf) { + buf[0] = v & 0xFF; + buf[1] = (v >> 8) & 0xFF; + buf[2] = (v >> 16) & 0xFF; + buf[3] = (v >> 24) & 0xFF; +} + +uint32_t DecodeUInt32FromBytes(const char* buf) { + return buf[0] | (uint32_t(buf[1]) << 8) | (uint32_t(buf[2]) << 16) | + (uint32_t(buf[3]) << 24); +} + +std::vector ParseChildren(absl::Cord children) { + std::vector result; + upb::Arena arena; + // Cord is flattened to iterate the buffer easily at the cost of memory copy. + // TODO(veblush): Optimize this once CordReader is introduced. + absl::string_view buf = children.Flatten(); + size_t cur = 0; + while (buf.size() - cur >= sizeof(uint32_t)) { + size_t msg_size = DecodeUInt32FromBytes(buf.data() + cur); + cur += sizeof(uint32_t); + GPR_ASSERT(buf.size() - cur >= msg_size); + google_rpc_Status* msg = + google_rpc_Status_parse(buf.data() + cur, msg_size, arena.ptr()); + cur += msg_size; + result.push_back(internal::StatusFromProto(msg)); + } + return result; +} + +} // namespace + +absl::Status StatusCreate(absl::StatusCode code, absl::string_view msg, + const DebugLocation& location, + std::initializer_list children) { + absl::Status s(code, msg); + if (location.file() != nullptr) { + StatusSetStr(&s, StatusStrProperty::kFile, location.file()); + } + if (location.line() != -1) { + StatusSetInt(&s, StatusIntProperty::kFileLine, location.line()); + } + StatusSetTime(&s, StatusTimeProperty::kCreated, absl::Now()); + for (const absl::Status& child : children) { + if (!child.ok()) { + StatusAddChild(&s, child); + } + } + return s; +} + +void StatusSetInt(absl::Status* status, StatusIntProperty key, intptr_t value) { + status->SetPayload(GetStatusIntPropertyUrl(key), + absl::Cord(std::to_string(value))); +} + +absl::optional StatusGetInt(const absl::Status& status, + StatusIntProperty key) { + absl::optional p = + status.GetPayload(GetStatusIntPropertyUrl(key)); + if (p.has_value()) { + absl::optional sv = p->TryFlat(); + intptr_t value; + if (sv.has_value()) { + if (absl::SimpleAtoi(*sv, &value)) { + return value; + } + } else { + if (absl::SimpleAtoi(std::string(*p), &value)) { + return value; + } + } + } + return {}; +} + +void StatusSetStr(absl::Status* status, StatusStrProperty key, + absl::string_view value) { + status->SetPayload(GetStatusStrPropertyUrl(key), absl::Cord(value)); +} + +absl::optional StatusGetStr(const absl::Status& status, + StatusStrProperty key) { + absl::optional p = + status.GetPayload(GetStatusStrPropertyUrl(key)); + if (p.has_value()) { + return std::string(*p); + } + return {}; +} + +void StatusSetTime(absl::Status* status, StatusTimeProperty key, + absl::Time time) { + status->SetPayload(GetStatusTimePropertyUrl(key), + absl::Cord(absl::string_view( + reinterpret_cast(&time), sizeof(time)))); +} + +absl::optional StatusGetTime(const absl::Status& status, + StatusTimeProperty key) { + absl::optional p = + status.GetPayload(GetStatusTimePropertyUrl(key)); + if (p.has_value()) { + absl::optional sv = p->TryFlat(); + if (sv.has_value()) { + return *reinterpret_cast(sv->data()); + } else { + std::string s = std::string(*p); + return *reinterpret_cast(s.c_str()); + } + } + return {}; +} + +void StatusAddChild(absl::Status* status, absl::Status child) { + upb::Arena arena; + // Serialize msg to buf + google_rpc_Status* msg = internal::StatusToProto(child, arena.ptr()); + size_t buf_len = 0; + char* buf = google_rpc_Status_serialize(msg, arena.ptr(), &buf_len); + // Append (msg-length and msg) to children payload + absl::optional old_children = + status->GetPayload(kChildrenPropertyUrl); + absl::Cord children; + if (old_children.has_value()) { + children = *old_children; + } + char head_buf[sizeof(uint32_t)]; + EncodeUInt32ToBytes(buf_len, head_buf); + children.Append(absl::string_view(head_buf, sizeof(uint32_t))); + children.Append(absl::string_view(buf, buf_len)); + status->SetPayload(kChildrenPropertyUrl, std::move(children)); +} + +std::vector StatusGetChildren(absl::Status status) { + absl::optional children = status.GetPayload(kChildrenPropertyUrl); + return children.has_value() ? ParseChildren(*children) + : std::vector(); +} + +std::string StatusToString(const absl::Status& status) { + if (status.ok()) { + return "OK"; + } + std::string head; + absl::StrAppend(&head, absl::StatusCodeToString(status.code())); + if (!status.message().empty()) { + absl::StrAppend(&head, ":", status.message()); + } + std::vector kvs; + absl::optional children; + status.ForEachPayload([&](absl::string_view type_url, + const absl::Cord& payload) { + if (absl::StartsWith(type_url, kTypeUrlPrefix)) { + type_url.remove_prefix(kTypeUrlPrefix.size()); + if (type_url == kTypeChildrenTag) { + children = payload; + return; + } + absl::string_view payload_view; + std::string payload_storage; + if (payload.TryFlat().has_value()) { + payload_view = payload.TryFlat().value(); + } else { + payload_storage = std::string(payload); + payload_view = payload_storage; + } + if (absl::StartsWith(type_url, kTypeIntTag)) { + type_url.remove_prefix(kTypeIntTag.size()); + kvs.push_back(absl::StrCat(type_url, ":", payload_view)); + } else if (absl::StartsWith(type_url, kTypeStrTag)) { + type_url.remove_prefix(kTypeStrTag.size()); + kvs.push_back(absl::StrCat(type_url, ":\"", + absl::CHexEscape(payload_view), "\"")); + } else if (absl::StartsWith(type_url, kTypeTimeTag)) { + type_url.remove_prefix(kTypeTimeTag.size()); + absl::Time t = + *reinterpret_cast(payload_view.data()); + kvs.push_back(absl::StrCat(type_url, ":\"", absl::FormatTime(t), "\"")); + } else { + kvs.push_back(absl::StrCat(type_url, ":\"", + absl::CHexEscape(payload_view), "\"")); + } + } else { + absl::optional payload_view = payload.TryFlat(); + std::string payload_str = absl::CHexEscape( + payload_view.has_value() ? *payload_view : std::string(payload)); + kvs.push_back(absl::StrCat(type_url, ":\"", payload_str, "\"")); + } + }); + if (children.has_value()) { + std::vector children_status = ParseChildren(*children); + std::vector children_text; + children_text.reserve(children_status.size()); + for (const absl::Status& child_status : children_status) { + children_text.push_back(StatusToString(child_status)); + } + kvs.push_back( + absl::StrCat("children:[", absl::StrJoin(children_text, ", "), "]")); + } + return kvs.empty() ? head + : absl::StrCat(head, " {", absl::StrJoin(kvs, ", "), "}"); +} + +namespace internal { + +google_rpc_Status* StatusToProto(absl::Status status, upb_arena* arena) { + google_rpc_Status* msg = google_rpc_Status_new(arena); + google_rpc_Status_set_code(msg, int32_t(status.code())); + google_rpc_Status_set_message( + msg, upb_strview_make(status.message().data(), status.message().size())); + status.ForEachPayload([&](absl::string_view type_url, + const absl::Cord& payload) { + google_protobuf_Any* any = google_rpc_Status_add_details(msg, arena); + char* type_url_buf = + reinterpret_cast(upb_arena_malloc(arena, type_url.size())); + memcpy(type_url_buf, type_url.data(), type_url.size()); + google_protobuf_Any_set_type_url( + any, upb_strview_make(type_url_buf, type_url.size())); + absl::optional v_view = payload.TryFlat(); + if (v_view.has_value()) { + google_protobuf_Any_set_value( + any, upb_strview_make(v_view->data(), v_view->size())); + } else { + char* buf = + reinterpret_cast(upb_arena_malloc(arena, payload.size())); + char* cur = buf; + for (absl::string_view chunk : payload.Chunks()) { + memcpy(cur, chunk.data(), chunk.size()); + cur += chunk.size(); + } + google_protobuf_Any_set_value(any, upb_strview_make(buf, payload.size())); + } + }); + return msg; +} + +absl::Status StatusFromProto(google_rpc_Status* msg) { + int32_t code = google_rpc_Status_code(msg); + upb_strview message = google_rpc_Status_message(msg); + absl::Status status(static_cast(code), + absl::string_view(message.data, message.size)); + size_t detail_len; + const google_protobuf_Any* const* details = + google_rpc_Status_details(msg, &detail_len); + for (size_t i = 0; i < detail_len; i++) { + upb_strview type_url = google_protobuf_Any_type_url(details[i]); + upb_strview value = google_protobuf_Any_value(details[i]); + status.SetPayload(absl::string_view(type_url.data, type_url.size), + absl::Cord(absl::string_view(value.data, value.size))); + } + return status; +} + +uintptr_t StatusAllocPtr(absl::Status s) { + // This relies the fact that absl::Status has only one member, StatusRep* + // so the sizeof(absl::Status) has the same size of intptr_t and StatusRep* + // can be stolen using placement allocation. + static_assert(sizeof(intptr_t) == sizeof(absl::Status), + "absl::Status should be as big as intptr_t"); + // This does two things; + // 1. Copies StatusRep* of absl::Status to ptr + // 2. Increases the counter of StatusRep if it's not inlined + uintptr_t ptr; + new (&ptr) absl::Status(s); + return ptr; +} + +void StatusFreePtr(uintptr_t ptr) { + // Decreases the counter of StatusRep if it's not inlined. + reinterpret_cast(&ptr)->~Status(); +} + +absl::Status StatusGetFromPtr(uintptr_t ptr) { + // Constructs Status from ptr having the address of StatusRep. + return *reinterpret_cast(&ptr); +} + +} // namespace internal + +} // namespace grpc_core diff --git a/src/core/lib/gprpp/status_helper.h b/src/core/lib/gprpp/status_helper.h new file mode 100644 index 00000000000..50bcdffeee6 --- /dev/null +++ b/src/core/lib/gprpp/status_helper.h @@ -0,0 +1,180 @@ +// +// +// Copyright 2021 the gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#ifndef GRPC_CORE_LIB_GPRPP_STATUS_HELPER_H +#define GRPC_CORE_LIB_GPRPP_STATUS_HELPER_H + +#include + +#include "absl/status/status.h" +#include "absl/time/time.h" + +#include "src/core/lib/gprpp/debug_location.h" + +extern "C" { +struct google_rpc_Status; +struct upb_arena; +} + +namespace grpc_core { + +/// This enum should have the same value of grpc_error_ints +// TODO(veblush): Use camel-case names once migration to absl::Status is done. +enum class StatusIntProperty { + /// 'errno' from the operating system + kErrorNo, + /// __LINE__ from the call site creating the error + kFileLine, + /// stream identifier: for errors that are associated with an individual + /// wire stream + kStreamId, + /// grpc status code representing this error + // TODO(veblush): Remove this after grpc_error is replaced with absl::Status + kRpcStatus, + /// offset into some binary blob (usually represented by + /// RAW_BYTES) where the error occurred + kOffset, + /// context sensitive index associated with the error + kIndex, + /// context sensitive size associated with the error + kSize, + /// http2 error code associated with the error (see the HTTP2 RFC) + kHttp2Error, + /// TSI status code associated with the error + kTsiCode, + /// WSAGetLastError() reported when this error occurred + kWsaError, + /// File descriptor associated with this error + kFd, + /// HTTP status (i.e. 404) + kHttpStatus, + /// chttp2: did the error occur while a write was in progress + kOccurredDuringWrite, + /// channel connectivity state associated with the error + ChannelConnectivityState, + /// LB policy drop + kLbPolicyDrop, +}; + +/// This enum should have the same value of grpc_error_strs +// TODO(veblush): Use camel-case names once migration to absl::Status is done. +enum class StatusStrProperty { + /// top-level textual description of this error + kDescription, + /// source file in which this error occurred + kFile, + /// operating system description of this error + kOsError, + /// syscall that generated this error + kSyscall, + /// peer that we were trying to communicate when this error occurred + kTargetAddress, + /// grpc status message associated with this error + kGrpcMessage, + /// hex dump (or similar) with the data that generated this error + kRawBytes, + /// tsi error string associated with this error + kTsiError, + /// filename that we were trying to read/write when this error occurred + kFilename, + /// key associated with the error + kKey, + /// value associated with the error + kValue, +}; + +/// This enum should have the same value of grpc_error_times +enum class StatusTimeProperty { + /// timestamp of error creation + kCreated, +}; + +/// Creates a status with given additional information +absl::Status StatusCreate( + absl::StatusCode code, absl::string_view msg, const DebugLocation& location, + std::initializer_list children) GRPC_MUST_USE_RESULT; + +/// Sets the int property to the status +void StatusSetInt(absl::Status* status, StatusIntProperty key, intptr_t value); + +/// Gets the int property from the status +absl::optional StatusGetInt( + const absl::Status& status, StatusIntProperty key) GRPC_MUST_USE_RESULT; + +/// Sets the str property to the status +void StatusSetStr(absl::Status* status, StatusStrProperty key, + absl::string_view value); + +/// Gets the str property from the status +absl::optional StatusGetStr( + const absl::Status& status, StatusStrProperty key) GRPC_MUST_USE_RESULT; + +/// Sets the time property to the status +void StatusSetTime(absl::Status* status, StatusTimeProperty key, + absl::Time time); + +/// Gets the time property from the status +absl::optional StatusGetTime( + const absl::Status& status, StatusTimeProperty key) GRPC_MUST_USE_RESULT; + +/// Adds a child status to status +void StatusAddChild(absl::Status* status, absl::Status child); + +/// Returns all children status from a status +std::vector StatusGetChildren(absl::Status status) + GRPC_MUST_USE_RESULT; + +/// Returns a string representation from status +/// Error status will be like +/// STATUS[:MESSAGE] [{PAYLOADS[, children:[CHILDREN-STATUS-LISTS]]}] +/// e.g. +/// CANCELLATION:SampleMessage {errno:'2021', line:'54', children:[ABORTED]} +std::string StatusToString(const absl::Status& status) GRPC_MUST_USE_RESULT; + +namespace internal { + +/// Builds a upb message, google_rpc_Status from a status +/// This is for internal implementation & test only +google_rpc_Status* StatusToProto(absl::Status status, + upb_arena* arena) GRPC_MUST_USE_RESULT; + +/// Builds a status from a upb message, google_rpc_Status +/// This is for internal implementation & test only +absl::Status StatusFromProto(google_rpc_Status* msg) GRPC_MUST_USE_RESULT; + +/// The same value of grpc_core::internal::StatusAllocPtr(absl::OkStatus()) +static constexpr uintptr_t kOkStatusPtr = 0; + +/// Returns ptr where the given status is copied into. +/// This ptr can be used to get Status later and should be freed by +/// StatusFreePtr. This shouldn't be used except migration purpose. +uintptr_t StatusAllocPtr(absl::Status s); + +/// Frees the allocated status at ptr. +/// This shouldn't be used except migration purpose. +void StatusFreePtr(uintptr_t ptr); + +/// Get the status from ptr. +/// This shouldn't be used except migration purpose. +absl::Status StatusGetFromPtr(uintptr_t ptr); + +} // namespace internal + +} // namespace grpc_core + +#endif // GRPC_CORE_LIB_GPRPP_STATUS_HELPER_H diff --git a/src/core/lib/http/httpcli.cc b/src/core/lib/http/httpcli.cc index 8d024dd3ac5..e3d2fbef1a6 100644 --- a/src/core/lib/http/httpcli.cc +++ b/src/core/lib/http/httpcli.cc @@ -30,6 +30,7 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/memory.h" @@ -38,7 +39,6 @@ #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/slice/slice_internal.h" @@ -62,7 +62,7 @@ struct internal_request { grpc_closure on_read; grpc_closure done_write; grpc_closure connected; - grpc_error* overall_error; + grpc_error_handle overall_error; grpc_resource_quota* resource_quota; }; static grpc_httpcli_get_override g_get_override = nullptr; @@ -86,9 +86,9 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context* context) { grpc_pollset_set_destroy(context->pollset_set); } -static void next_address(internal_request* req, grpc_error* due_to_error); +static void next_address(internal_request* req, grpc_error_handle due_to_error); -static void finish(internal_request* req, grpc_error* error) { +static void finish(internal_request* req, grpc_error_handle error) { grpc_polling_entity_del_from_pollset_set(req->pollent, req->context->pollset_set); grpc_core::ExecCtx::Run(DEBUG_LOCATION, req->on_done, error); @@ -110,7 +110,7 @@ static void finish(internal_request* req, grpc_error* error) { gpr_free(req); } -static void append_error(internal_request* req, grpc_error* error) { +static void append_error(internal_request* req, grpc_error_handle error) { if (req->overall_error == GRPC_ERROR_NONE) { req->overall_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed HTTP/1 client request"); @@ -127,14 +127,14 @@ static void do_read(internal_request* req) { grpc_endpoint_read(req->ep, &req->incoming, &req->on_read, /*urgent=*/true); } -static void on_read(void* user_data, grpc_error* error) { +static void on_read(void* user_data, grpc_error_handle error) { internal_request* req = static_cast(user_data); size_t i; for (i = 0; i < req->incoming.count; i++) { if (GRPC_SLICE_LENGTH(req->incoming.slices[i])) { req->have_read_byte = 1; - grpc_error* err = grpc_http_parser_parse( + grpc_error_handle err = grpc_http_parser_parse( &req->parser, req->incoming.slices[i], nullptr); if (err != GRPC_ERROR_NONE) { finish(req, err); @@ -154,7 +154,7 @@ static void on_read(void* user_data, grpc_error* error) { static void on_written(internal_request* req) { do_read(req); } -static void done_write(void* arg, grpc_error* error) { +static void done_write(void* arg, grpc_error_handle error) { internal_request* req = static_cast(arg); if (error == GRPC_ERROR_NONE) { on_written(req); @@ -182,7 +182,7 @@ static void on_handshake_done(void* arg, grpc_endpoint* ep) { start_write(req); } -static void on_connected(void* arg, grpc_error* error) { +static void on_connected(void* arg, grpc_error_handle error) { internal_request* req = static_cast(arg); if (!req->ep) { @@ -194,7 +194,7 @@ static void on_connected(void* arg, grpc_error* error) { req->deadline, on_handshake_done); } -static void next_address(internal_request* req, grpc_error* error) { +static void next_address(internal_request* req, grpc_error_handle error) { grpc_resolved_address* addr; if (error != GRPC_ERROR_NONE) { append_error(req, error); @@ -216,7 +216,7 @@ static void next_address(internal_request* req, grpc_error* error) { &args, addr, req->deadline); } -static void on_resolved(void* arg, grpc_error* error) { +static void on_resolved(void* arg, grpc_error_handle error) { internal_request* req = static_cast(arg); if (error != GRPC_ERROR_NONE) { finish(req, GRPC_ERROR_REF(error)); diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc index 3ef4a4d073f..e26f99b4bc5 100644 --- a/src/core/lib/http/httpcli_security_connector.cc +++ b/src/core/lib/http/httpcli_security_connector.cc @@ -91,7 +91,7 @@ class grpc_httpcli_ssl_channel_security_connector final void check_peer(tsi_peer peer, grpc_endpoint* /*ep*/, grpc_core::RefCountedPtr* /*auth_context*/, grpc_closure* on_peer_checked) override { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; /* Check the peer name. */ if (secure_peer_name_ != nullptr && @@ -105,6 +105,11 @@ class grpc_httpcli_ssl_channel_security_connector final tsi_peer_destruct(&peer); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other_sc) const override { auto* other = reinterpret_cast( @@ -115,13 +120,13 @@ class grpc_httpcli_ssl_channel_security_connector final bool check_call_host(absl::string_view /*host*/, grpc_auth_context* /*auth_context*/, grpc_closure* /*on_call_host_checked*/, - grpc_error** error) override { + grpc_error_handle* error) override { *error = GRPC_ERROR_NONE; return true; } void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/, - grpc_error* error) override { + grpc_error_handle error) override { GRPC_ERROR_UNREF(error); } @@ -160,13 +165,12 @@ struct on_done_closure { void* arg; grpc_core::RefCountedPtr handshake_mgr; }; -static void on_handshake_done(void* arg, grpc_error* error) { +static void on_handshake_done(void* arg, grpc_error_handle error) { auto* args = static_cast(arg); on_done_closure* c = static_cast(args->user_data); if (error != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(error); - gpr_log(GPR_ERROR, "Secure transport setup failed: %s", msg); - + gpr_log(GPR_ERROR, "Secure transport setup failed: %s", + grpc_error_std_string(error).c_str()); c->func(c->arg, nullptr); } else { grpc_channel_args_destroy(args->args); diff --git a/src/core/lib/http/parser.cc b/src/core/lib/http/parser.cc index 3a0b2be4a85..c47a0177d28 100644 --- a/src/core/lib/http/parser.cc +++ b/src/core/lib/http/parser.cc @@ -37,7 +37,7 @@ static char* buf2str(void* buffer, size_t length) { return out; } -static grpc_error* handle_response_line(grpc_http_parser* parser) { +static grpc_error_handle handle_response_line(grpc_http_parser* parser) { uint8_t* beg = parser->cur_line; uint8_t* cur = beg; uint8_t* end = beg + parser->cur_line_length; @@ -90,7 +90,7 @@ static grpc_error* handle_response_line(grpc_http_parser* parser) { return GRPC_ERROR_NONE; } -static grpc_error* handle_request_line(grpc_http_parser* parser) { +static grpc_error_handle handle_request_line(grpc_http_parser* parser) { uint8_t* beg = parser->cur_line; uint8_t* cur = beg; uint8_t* end = beg + parser->cur_line_length; @@ -161,7 +161,7 @@ static grpc_error* handle_request_line(grpc_http_parser* parser) { return GRPC_ERROR_NONE; } -static grpc_error* handle_first_line(grpc_http_parser* parser) { +static grpc_error_handle handle_first_line(grpc_http_parser* parser) { switch (parser->type) { case GRPC_HTTP_REQUEST: return handle_request_line(parser); @@ -172,14 +172,14 @@ static grpc_error* handle_first_line(grpc_http_parser* parser) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Should never reach here")); } -static grpc_error* add_header(grpc_http_parser* parser) { +static grpc_error_handle add_header(grpc_http_parser* parser) { uint8_t* beg = parser->cur_line; uint8_t* cur = beg; uint8_t* end = beg + parser->cur_line_length; size_t* hdr_count = nullptr; grpc_http_header** hdrs = nullptr; grpc_http_header hdr = {nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; GPR_ASSERT(cur != end); @@ -235,9 +235,9 @@ done: return error; } -static grpc_error* finish_line(grpc_http_parser* parser, - bool* found_body_start) { - grpc_error* err; +static grpc_error_handle finish_line(grpc_http_parser* parser, + bool* found_body_start) { + grpc_error_handle err; switch (parser->state) { case GRPC_HTTP_FIRST_LINE: err = handle_first_line(parser); @@ -264,7 +264,7 @@ static grpc_error* finish_line(grpc_http_parser* parser, return GRPC_ERROR_NONE; } -static grpc_error* addbyte_body(grpc_http_parser* parser, uint8_t byte) { +static grpc_error_handle addbyte_body(grpc_http_parser* parser, uint8_t byte) { size_t* body_length = nullptr; char** body = nullptr; @@ -313,8 +313,8 @@ static bool check_line(grpc_http_parser* parser) { return false; } -static grpc_error* addbyte(grpc_http_parser* parser, uint8_t byte, - bool* found_body_start) { +static grpc_error_handle addbyte(grpc_http_parser* parser, uint8_t byte, + bool* found_body_start) { switch (parser->state) { case GRPC_HTTP_FIRST_LINE: case GRPC_HTTP_HEADERS: @@ -371,12 +371,12 @@ void grpc_http_response_destroy(grpc_http_response* response) { gpr_free(response->hdrs); } -grpc_error* grpc_http_parser_parse(grpc_http_parser* parser, - const grpc_slice& slice, - size_t* start_of_body) { +grpc_error_handle grpc_http_parser_parse(grpc_http_parser* parser, + const grpc_slice& slice, + size_t* start_of_body) { for (size_t i = 0; i < GRPC_SLICE_LENGTH(slice); i++) { bool found_body_start = false; - grpc_error* err = + grpc_error_handle err = addbyte(parser, GRPC_SLICE_START_PTR(slice)[i], &found_body_start); if (err != GRPC_ERROR_NONE) return err; if (found_body_start && start_of_body != nullptr) *start_of_body = i + 1; @@ -384,7 +384,7 @@ grpc_error* grpc_http_parser_parse(grpc_http_parser* parser, return GRPC_ERROR_NONE; } -grpc_error* grpc_http_parser_eof(grpc_http_parser* parser) { +grpc_error_handle grpc_http_parser_eof(grpc_http_parser* parser) { if (parser->state != GRPC_HTTP_BODY) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Did not finish headers"); } diff --git a/src/core/lib/http/parser.h b/src/core/lib/http/parser.h index 2da21903e63..613b9726118 100644 --- a/src/core/lib/http/parser.h +++ b/src/core/lib/http/parser.h @@ -100,10 +100,10 @@ void grpc_http_parser_init(grpc_http_parser* parser, grpc_http_type type, void grpc_http_parser_destroy(grpc_http_parser* parser); /* Sets \a start_of_body to the offset in \a slice of the start of the body. */ -grpc_error* grpc_http_parser_parse(grpc_http_parser* parser, - const grpc_slice& slice, - size_t* start_of_body); -grpc_error* grpc_http_parser_eof(grpc_http_parser* parser); +grpc_error_handle grpc_http_parser_parse(grpc_http_parser* parser, + const grpc_slice& slice, + size_t* start_of_body); +grpc_error_handle grpc_http_parser_eof(grpc_http_parser* parser); void grpc_http_request_destroy(grpc_http_request* request); void grpc_http_response_destroy(grpc_http_response* response); diff --git a/src/core/lib/iomgr/buffer_list.cc b/src/core/lib/iomgr/buffer_list.cc index e1b87da4d0c..f92fc9b18c2 100644 --- a/src/core/lib/iomgr/buffer_list.cc +++ b/src/core/lib/iomgr/buffer_list.cc @@ -40,14 +40,14 @@ void fill_gpr_from_timestamp(gpr_timespec* gts, const struct timespec* ts) { } void default_timestamps_callback(void* /*arg*/, grpc_core::Timestamps* /*ts*/, - grpc_error* /*shudown_err*/) { + grpc_error_handle /*shudown_err*/) { gpr_log(GPR_DEBUG, "Timestamps callback has not been registered"); } /** The saved callback function that will be invoked when we get all the * timestamps that we are going to get for a TracedBuffer. */ void (*timestamps_callback)(void*, grpc_core::Timestamps*, - grpc_error* shutdown_err) = + grpc_error_handle shutdown_err) = default_timestamps_callback; /* Used to extract individual opt stats from cmsg, so as to avoid troubles with @@ -268,7 +268,7 @@ void TracedBuffer::ProcessTimestamp(TracedBuffer** head, } void TracedBuffer::Shutdown(TracedBuffer** head, void* remaining, - grpc_error* shutdown_err) { + grpc_error_handle shutdown_err) { GPR_DEBUG_ASSERT(head != nullptr); TracedBuffer* elem = *head; while (elem != nullptr) { @@ -284,9 +284,8 @@ void TracedBuffer::Shutdown(TracedBuffer** head, void* remaining, GRPC_ERROR_UNREF(shutdown_err); } -void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, - grpc_core::Timestamps*, - grpc_error* error)) { +void grpc_tcp_set_write_timestamps_callback( + void (*fn)(void*, grpc_core::Timestamps*, grpc_error_handle error)) { timestamps_callback = fn; } } /* namespace grpc_core */ @@ -294,9 +293,8 @@ void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, #else /* GRPC_LINUX_ERRQUEUE */ namespace grpc_core { -void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, - grpc_core::Timestamps*, - grpc_error* error)) { +void grpc_tcp_set_write_timestamps_callback( + void (*fn)(void*, grpc_core::Timestamps*, grpc_error_handle error)) { // Cast value of fn to void to avoid unused parameter warning. // Can't comment out the name because some compilers and formatters don't // like the sequence */* , which would arise from */*fn*/. diff --git a/src/core/lib/iomgr/buffer_list.h b/src/core/lib/iomgr/buffer_list.h index f8faf7cb087..982c4c6b67f 100644 --- a/src/core/lib/iomgr/buffer_list.h +++ b/src/core/lib/iomgr/buffer_list.h @@ -135,7 +135,7 @@ class TracedBuffer { /** Cleans the list by calling the callback for each traced buffer in the list * with timestamps that it has. */ static void Shutdown(grpc_core::TracedBuffer** head, void* remaining, - grpc_error* shutdown_err); + grpc_error_handle shutdown_err); private: uint32_t seq_no_; /* The sequence number for the last byte in the buffer */ @@ -148,7 +148,7 @@ class TracedBuffer { public: /* Phony shutdown function */ static void Shutdown(grpc_core::TracedBuffer** /*head*/, void* /*remaining*/, - grpc_error* shutdown_err) { + grpc_error_handle shutdown_err) { GRPC_ERROR_UNREF(shutdown_err); } }; @@ -156,9 +156,8 @@ class TracedBuffer { /** Sets the callback function to call when timestamps for a write are * collected. The callback does not own a reference to error. */ -void grpc_tcp_set_write_timestamps_callback(void (*fn)(void*, - grpc_core::Timestamps*, - grpc_error* error)); +void grpc_tcp_set_write_timestamps_callback( + void (*fn)(void*, grpc_core::Timestamps*, grpc_error_handle error)); } /* namespace grpc_core */ diff --git a/src/core/lib/iomgr/call_combiner.cc b/src/core/lib/iomgr/call_combiner.cc index 043b3bb4032..44ffb12722d 100644 --- a/src/core/lib/iomgr/call_combiner.cc +++ b/src/core/lib/iomgr/call_combiner.cc @@ -32,15 +32,15 @@ DebugOnlyTraceFlag grpc_call_combiner_trace(false, "call_combiner"); namespace { -grpc_error* DecodeCancelStateError(gpr_atm cancel_state) { +grpc_error_handle DecodeCancelStateError(gpr_atm cancel_state) { if (cancel_state & 1) { - return reinterpret_cast(cancel_state & - ~static_cast(1)); + return reinterpret_cast(cancel_state & + ~static_cast(1)); } return GRPC_ERROR_NONE; } -gpr_atm EncodeCancelStateError(grpc_error* error) { +gpr_atm EncodeCancelStateError(grpc_error_handle error) { return static_cast(1) | reinterpret_cast(error); } @@ -60,7 +60,7 @@ CallCombiner::~CallCombiner() { } #ifdef GRPC_TSAN_ENABLED -void CallCombiner::TsanClosure(void* arg, grpc_error* error) { +void CallCombiner::TsanClosure(void* arg, grpc_error_handle error) { CallCombiner* self = static_cast(arg); // We ref-count the lock, and check if it's already taken. // If it was taken, we should do nothing. Otherwise, we will mark it as @@ -91,7 +91,8 @@ void CallCombiner::TsanClosure(void* arg, grpc_error* error) { } #endif -void CallCombiner::ScheduleClosure(grpc_closure* closure, grpc_error* error) { +void CallCombiner::ScheduleClosure(grpc_closure* closure, + grpc_error_handle error) { #ifdef GRPC_TSAN_ENABLED original_closure_ = closure; ExecCtx::Run(DEBUG_LOCATION, &tsan_closure_, error); @@ -110,14 +111,15 @@ void CallCombiner::ScheduleClosure(grpc_closure* closure, grpc_error* error) { #define DEBUG_FMT_ARGS #endif -void CallCombiner::Start(grpc_closure* closure, grpc_error* error, +void CallCombiner::Start(grpc_closure* closure, grpc_error_handle error, DEBUG_ARGS const char* reason) { GPR_TIMER_SCOPE("CallCombiner::Start", 0); if (GRPC_TRACE_FLAG_ENABLED(grpc_call_combiner_trace)) { gpr_log(GPR_INFO, "==> CallCombiner::Start() [%p] closure=%p [" DEBUG_FMT_STR "%s] error=%s", - this, closure DEBUG_FMT_ARGS, reason, grpc_error_string(error)); + this, closure DEBUG_FMT_ARGS, reason, + grpc_error_std_string(error).c_str()); } size_t prev_size = static_cast(gpr_atm_full_fetch_add(&size_, (gpr_atm)1)); @@ -176,7 +178,8 @@ void CallCombiner::Stop(DEBUG_ARGS const char* reason) { } if (GRPC_TRACE_FLAG_ENABLED(grpc_call_combiner_trace)) { gpr_log(GPR_INFO, " EXECUTING FROM QUEUE: closure=%p error=%s", - closure, grpc_error_string(closure->error_data.error)); + closure, + grpc_error_std_string(closure->error_data.error).c_str()); } ScheduleClosure(closure, closure->error_data.error); break; @@ -191,7 +194,7 @@ void CallCombiner::SetNotifyOnCancel(grpc_closure* closure) { while (true) { // Decode original state. gpr_atm original_state = gpr_atm_acq_load(&cancel_state_); - grpc_error* original_error = DecodeCancelStateError(original_state); + grpc_error_handle original_error = DecodeCancelStateError(original_state); // If error is set, invoke the cancellation closure immediately. // Otherwise, store the new closure. if (original_error != GRPC_ERROR_NONE) { @@ -229,11 +232,11 @@ void CallCombiner::SetNotifyOnCancel(grpc_closure* closure) { } } -void CallCombiner::Cancel(grpc_error* error) { +void CallCombiner::Cancel(grpc_error_handle error) { GRPC_STATS_INC_CALL_COMBINER_CANCELLED(); while (true) { gpr_atm original_state = gpr_atm_acq_load(&cancel_state_); - grpc_error* original_error = DecodeCancelStateError(original_state); + grpc_error_handle original_error = DecodeCancelStateError(original_state); if (original_error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(error); break; diff --git a/src/core/lib/iomgr/call_combiner.h b/src/core/lib/iomgr/call_combiner.h index 44acd9fe870..e5429cca825 100644 --- a/src/core/lib/iomgr/call_combiner.h +++ b/src/core/lib/iomgr/call_combiner.h @@ -58,7 +58,7 @@ class CallCombiner { #define GRPC_CALL_COMBINER_STOP(call_combiner, reason) \ (call_combiner)->Stop(__FILE__, __LINE__, (reason)) /// Starts processing \a closure. - void Start(grpc_closure* closure, grpc_error* error, const char* file, + void Start(grpc_closure* closure, grpc_error_handle error, const char* file, int line, const char* reason); /// Yields the call combiner to the next closure in the queue, if any. void Stop(const char* file, int line, const char* reason); @@ -68,7 +68,8 @@ class CallCombiner { #define GRPC_CALL_COMBINER_STOP(call_combiner, reason) \ (call_combiner)->Stop((reason)) /// Starts processing \a closure. - void Start(grpc_closure* closure, grpc_error* error, const char* reason); + void Start(grpc_closure* closure, grpc_error_handle error, + const char* reason); /// Yields the call combiner to the next closure in the queue, if any. void Stop(const char* reason); #endif @@ -94,26 +95,22 @@ class CallCombiner { /// cancellation; this effectively unregisters the previously set closure. /// However, most filters will not need to explicitly unregister their /// callbacks, as this is done automatically when the call is destroyed. - /// Filters that schedule the cancellation closure on ExecCtx do not need - /// to take a ref on the call stack to guarantee closure liveness. This is - /// done by explicitly flushing ExecCtx after the unregistration during - /// call destruction. void SetNotifyOnCancel(grpc_closure* closure); /// Indicates that the call has been cancelled. - void Cancel(grpc_error* error); + void Cancel(grpc_error_handle error); private: - void ScheduleClosure(grpc_closure* closure, grpc_error* error); + void ScheduleClosure(grpc_closure* closure, grpc_error_handle error); #ifdef GRPC_TSAN_ENABLED - static void TsanClosure(void* arg, grpc_error* error); + static void TsanClosure(void* arg, grpc_error_handle error); #endif gpr_atm size_ = 0; // size_t, num closures in queue or currently executing MultiProducerSingleConsumerQueue queue_; // Either 0 (if not cancelled and no cancellation closure set), // a grpc_closure* (if the lowest bit is 0), - // or a grpc_error* (if the lowest bit is 1). + // or a grpc_error_handle (if the lowest bit is 1). gpr_atm cancel_state_ = 0; #ifdef GRPC_TSAN_ENABLED // A fake ref-counted lock that is kept alive after the destruction of @@ -150,7 +147,7 @@ class CallCombinerClosureList { // Adds a closure to the list. The closure must eventually result in // the call combiner being yielded. - void Add(grpc_closure* closure, grpc_error* error, const char* reason) { + void Add(grpc_closure* closure, grpc_error_handle error, const char* reason) { closures_.emplace_back(closure, error, reason); } @@ -176,7 +173,8 @@ class CallCombinerClosureList { "CallCombinerClosureList executing closure while already " "holding call_combiner %p: closure=%p error=%s reason=%s", call_combiner, closures_[0].closure, - grpc_error_string(closures_[0].error), closures_[0].reason); + grpc_error_std_string(closures_[0].error).c_str(), + closures_[0].reason); } // This will release the call combiner. ExecCtx::Run(DEBUG_LOCATION, closures_[0].closure, closures_[0].error); @@ -199,10 +197,10 @@ class CallCombinerClosureList { private: struct CallCombinerClosure { grpc_closure* closure; - grpc_error* error; + grpc_error_handle error; const char* reason; - CallCombinerClosure(grpc_closure* closure, grpc_error* error, + CallCombinerClosure(grpc_closure* closure, grpc_error_handle error, const char* reason) : closure(closure), error(error), reason(reason) {} }; diff --git a/src/core/lib/iomgr/cfstream_handle.cc b/src/core/lib/iomgr/cfstream_handle.cc index 2f70a2995be..fb112316e30 100644 --- a/src/core/lib/iomgr/cfstream_handle.cc +++ b/src/core/lib/iomgr/cfstream_handle.cc @@ -62,7 +62,7 @@ void CFStreamHandle::ReadCallback(CFReadStreamRef stream, void* client_callback_info) { grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; - grpc_error* error; + grpc_error_handle error; CFErrorRef stream_error; CFStreamHandle* handle = static_cast(client_callback_info); if (grpc_tcp_trace.enabled()) { @@ -97,7 +97,7 @@ void CFStreamHandle::WriteCallback(CFWriteStreamRef stream, void* clientCallBackInfo) { grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; - grpc_error* error; + grpc_error_handle error; CFErrorRef stream_error; CFStreamHandle* handle = static_cast(clientCallBackInfo); if (grpc_tcp_trace.enabled()) { @@ -171,7 +171,7 @@ void CFStreamHandle::NotifyOnWrite(grpc_closure* closure) { write_event_.NotifyOn(closure); } -void CFStreamHandle::Shutdown(grpc_error* error) { +void CFStreamHandle::Shutdown(grpc_error_handle error) { open_event_.SetShutdown(GRPC_ERROR_REF(error)); read_event_.SetShutdown(GRPC_ERROR_REF(error)); write_event_.SetShutdown(GRPC_ERROR_REF(error)); diff --git a/src/core/lib/iomgr/cfstream_handle.h b/src/core/lib/iomgr/cfstream_handle.h index b0f0664a04f..2358758f147 100644 --- a/src/core/lib/iomgr/cfstream_handle.h +++ b/src/core/lib/iomgr/cfstream_handle.h @@ -53,7 +53,7 @@ class CFStreamHandle : public GrpcLibraryInitHolder { void NotifyOnOpen(grpc_closure* closure); void NotifyOnRead(grpc_closure* closure); void NotifyOnWrite(grpc_closure* closure); - void Shutdown(grpc_error* error); + void Shutdown(grpc_error_handle error); void Ref(const char* file = "", int line = 0, const char* reason = nullptr); void Unref(const char* file = "", int line = 0, const char* reason = nullptr); diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h index 6bb65340d1a..b429c9e3ebd 100644 --- a/src/core/lib/iomgr/closure.h +++ b/src/core/lib/iomgr/closure.h @@ -50,7 +50,7 @@ typedef struct grpc_closure_list { * describing what went wrong. * Error contract: it is not the cb's job to unref this error; * the closure scheduler will do that after the cb returns */ -typedef void (*grpc_iomgr_cb_func)(void* arg, grpc_error* error); +typedef void (*grpc_iomgr_cb_func)(void* arg, grpc_error_handle error); /** A closure over a grpc_iomgr_cb_func. */ struct grpc_closure { @@ -72,7 +72,7 @@ struct grpc_closure { /** Once queued, the result of the closure. Before then: scratch space */ union { - grpc_error* error; + grpc_error_handle error; uintptr_t scratch; } error_data; @@ -126,7 +126,7 @@ struct wrapped_closure { void* cb_arg; grpc_closure wrapper; }; -inline void closure_wrapper(void* arg, grpc_error* error) { +inline void closure_wrapper(void* arg, grpc_error_handle error) { wrapped_closure* wc = static_cast(arg); grpc_iomgr_cb_func cb = wc->cb; void* cb_arg = wc->cb_arg; @@ -175,7 +175,8 @@ inline void grpc_closure_list_init(grpc_closure_list* closure_list) { and set \a closure's result to \a error Returns true if \a list becomes non-empty */ inline bool grpc_closure_list_append(grpc_closure_list* closure_list, - grpc_closure* closure, grpc_error* error) { + grpc_closure* closure, + grpc_error_handle error) { if (closure == nullptr) { GRPC_ERROR_UNREF(error); return false; @@ -194,7 +195,7 @@ inline bool grpc_closure_list_append(grpc_closure_list* closure_list, /** force all success bits in \a list to false */ inline void grpc_closure_list_fail_all(grpc_closure_list* list, - grpc_error* forced_failure) { + grpc_error_handle forced_failure) { for (grpc_closure* c = list->head; c != nullptr; c = c->next_data.next) { if (c->error_data.error == GRPC_ERROR_NONE) { c->error_data.error = GRPC_ERROR_REF(forced_failure); @@ -227,7 +228,7 @@ namespace grpc_core { class Closure { public: static void Run(const DebugLocation& location, grpc_closure* closure, - grpc_error* error) { + grpc_error_handle error) { (void)location; if (closure == nullptr) { GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/iomgr/combiner.cc b/src/core/lib/iomgr/combiner.cc index aa5a2ea44f4..48237e5a102 100644 --- a/src/core/lib/iomgr/combiner.cc +++ b/src/core/lib/iomgr/combiner.cc @@ -46,11 +46,12 @@ grpc_core::DebugOnlyTraceFlag grpc_combiner_trace(false, "combiner"); #define STATE_ELEM_COUNT_LOW_BIT 2 static void combiner_exec(grpc_core::Combiner* lock, grpc_closure* closure, - grpc_error* error); + grpc_error_handle error); static void combiner_finally_exec(grpc_core::Combiner* lock, - grpc_closure* closure, grpc_error* error); + grpc_closure* closure, + grpc_error_handle error); -static void offload(void* arg, grpc_error* error); +static void offload(void* arg, grpc_error_handle error); grpc_core::Combiner* grpc_combiner_create(void) { grpc_core::Combiner* lock = new grpc_core::Combiner(); @@ -126,7 +127,7 @@ static void push_first_on_exec_ctx(grpc_core::Combiner* lock) { } static void combiner_exec(grpc_core::Combiner* lock, grpc_closure* cl, - grpc_error* error) { + grpc_error_handle error) { GPR_TIMER_SCOPE("combiner.execute", 0); GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_ITEMS(); gpr_atm last = gpr_atm_full_fetch_add(&lock->state, STATE_ELEM_COUNT_LOW_BIT); @@ -167,7 +168,7 @@ static void move_next() { } } -static void offload(void* arg, grpc_error* /*error*/) { +static void offload(void* arg, grpc_error_handle /*error*/) { grpc_core::Combiner* lock = static_cast(arg); push_last_on_exec_ctx(lock); } @@ -230,7 +231,7 @@ bool grpc_combiner_continue_exec_ctx() { } GPR_TIMER_SCOPE("combiner.exec1", 0); grpc_closure* cl = reinterpret_cast(n); - grpc_error* cl_err = cl->error_data.error; + grpc_error_handle cl_err = cl->error_data.error; #ifndef NDEBUG cl->scheduled = false; #endif @@ -246,7 +247,7 @@ bool grpc_combiner_continue_exec_ctx() { GRPC_COMBINER_TRACE( gpr_log(GPR_INFO, "C:%p execute_final[%d] c=%p", lock, loops, c)); grpc_closure* next = c->next_data.next; - grpc_error* error = c->error_data.error; + grpc_error_handle error = c->error_data.error; #ifndef NDEBUG c->scheduled = false; #endif @@ -297,10 +298,11 @@ bool grpc_combiner_continue_exec_ctx() { return true; } -static void enqueue_finally(void* closure, grpc_error* error); +static void enqueue_finally(void* closure, grpc_error_handle error); static void combiner_finally_exec(grpc_core::Combiner* lock, - grpc_closure* closure, grpc_error* error) { + grpc_closure* closure, + grpc_error_handle error) { GPR_ASSERT(lock != nullptr); GPR_TIMER_SCOPE("combiner.execute_finally", 0); GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_FINAL_ITEMS(); @@ -322,7 +324,7 @@ static void combiner_finally_exec(grpc_core::Combiner* lock, grpc_closure_list_append(&lock->final_list, closure, error); } -static void enqueue_finally(void* closure, grpc_error* error) { +static void enqueue_finally(void* closure, grpc_error_handle error) { grpc_closure* cl = static_cast(closure); combiner_finally_exec( reinterpret_cast(cl->error_data.scratch), cl, @@ -330,11 +332,11 @@ static void enqueue_finally(void* closure, grpc_error* error) { } namespace grpc_core { -void Combiner::Run(grpc_closure* closure, grpc_error* error) { +void Combiner::Run(grpc_closure* closure, grpc_error_handle error) { combiner_exec(this, closure, error); } -void Combiner::FinallyRun(grpc_closure* closure, grpc_error* error) { +void Combiner::FinallyRun(grpc_closure* closure, grpc_error_handle error) { combiner_finally_exec(this, closure, error); } } // namespace grpc_core diff --git a/src/core/lib/iomgr/combiner.h b/src/core/lib/iomgr/combiner.h index 32712066bef..efa2bce6823 100644 --- a/src/core/lib/iomgr/combiner.h +++ b/src/core/lib/iomgr/combiner.h @@ -32,9 +32,9 @@ namespace grpc_core { // use ExecCtx class Combiner { public: - void Run(grpc_closure* closure, grpc_error* error); + void Run(grpc_closure* closure, grpc_error_handle error); // TODO(yashkt) : Remove this method - void FinallyRun(grpc_closure* closure, grpc_error* error); + void FinallyRun(grpc_closure* closure, grpc_error_handle error); Combiner* next_combiner_on_this_exec_ctx = nullptr; MultiProducerSingleConsumerQueue queue; // either: diff --git a/src/core/lib/iomgr/endpoint.cc b/src/core/lib/iomgr/endpoint.cc index 8954f9dc066..4c84501a822 100644 --- a/src/core/lib/iomgr/endpoint.cc +++ b/src/core/lib/iomgr/endpoint.cc @@ -46,7 +46,7 @@ void grpc_endpoint_delete_from_pollset_set(grpc_endpoint* ep, ep->vtable->delete_from_pollset_set(ep, pollset_set); } -void grpc_endpoint_shutdown(grpc_endpoint* ep, grpc_error* why) { +void grpc_endpoint_shutdown(grpc_endpoint* ep, grpc_error_handle why) { ep->vtable->shutdown(ep, why); } diff --git a/src/core/lib/iomgr/endpoint.h b/src/core/lib/iomgr/endpoint.h index b6e6086f14f..4db5e3def24 100644 --- a/src/core/lib/iomgr/endpoint.h +++ b/src/core/lib/iomgr/endpoint.h @@ -44,7 +44,7 @@ struct grpc_endpoint_vtable { void (*add_to_pollset)(grpc_endpoint* ep, grpc_pollset* pollset); void (*add_to_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); void (*delete_from_pollset_set)(grpc_endpoint* ep, grpc_pollset_set* pollset); - void (*shutdown)(grpc_endpoint* ep, grpc_error* why); + void (*shutdown)(grpc_endpoint* ep, grpc_error_handle why); void (*destroy)(grpc_endpoint* ep); grpc_resource_user* (*get_resource_user)(grpc_endpoint* ep); absl::string_view (*get_peer)(grpc_endpoint* ep); @@ -86,7 +86,7 @@ void grpc_endpoint_write(grpc_endpoint* ep, grpc_slice_buffer* slices, /* Causes any pending and future read/write callbacks to run immediately with success==0 */ -void grpc_endpoint_shutdown(grpc_endpoint* ep, grpc_error* why); +void grpc_endpoint_shutdown(grpc_endpoint* ep, grpc_error_handle why); void grpc_endpoint_destroy(grpc_endpoint* ep); /* Add an endpoint to a pollset or pollset_set, so that when the pollset is diff --git a/src/core/lib/iomgr/endpoint_cfstream.cc b/src/core/lib/iomgr/endpoint_cfstream.cc index 75cd0f09d1a..63945065fe7 100644 --- a/src/core/lib/iomgr/endpoint_cfstream.cc +++ b/src/core/lib/iomgr/endpoint_cfstream.cc @@ -29,13 +29,13 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/cfstream_handle.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/error_cfstream.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" @@ -106,8 +106,8 @@ static void CFStreamUnref(CFStreamEndpoint* ep) { static void CFStreamRef(CFStreamEndpoint* ep) { gpr_ref(&ep->refcount); } #endif -static grpc_error* CFStreamAnnotateError(grpc_error* src_error, - CFStreamEndpoint* ep) { +static grpc_error_handle CFStreamAnnotateError(grpc_error_handle src_error, + CFStreamEndpoint* ep) { return grpc_error_set_str( grpc_error_set_int(src_error, GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), @@ -115,13 +115,12 @@ static grpc_error* CFStreamAnnotateError(grpc_error* src_error, grpc_slice_from_copied_string(ep->peer_string.c_str())); } -static void CallReadCb(CFStreamEndpoint* ep, grpc_error* error) { +static void CallReadCb(CFStreamEndpoint* ep, grpc_error_handle error) { if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CFStream endpoint:%p call_read_cb %p %p:%p", ep, ep->read_cb, ep->read_cb->cb, ep->read_cb->cb_arg); size_t i; - const char* str = grpc_error_string(error); - gpr_log(GPR_DEBUG, "read: error=%s", str); + gpr_log(GPR_DEBUG, "read: error=%s", grpc_error_std_string(error).c_str()); for (i = 0; i < ep->read_slices->count; i++) { char* dump = grpc_dump_slice(ep->read_slices->slices[i], @@ -137,12 +136,11 @@ static void CallReadCb(CFStreamEndpoint* ep, grpc_error* error) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, error); } -static void CallWriteCb(CFStreamEndpoint* ep, grpc_error* error) { +static void CallWriteCb(CFStreamEndpoint* ep, grpc_error_handle error) { if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CFStream endpoint:%p call_write_cb %p %p:%p", ep, ep->write_cb, ep->write_cb->cb, ep->write_cb->cb_arg); - const char* str = grpc_error_string(error); - gpr_log(GPR_DEBUG, "write: error=%s", str); + gpr_log(GPR_DEBUG, "write: error=%s", grpc_error_std_string(error).c_str()); } grpc_closure* cb = ep->write_cb; ep->write_cb = nullptr; @@ -150,7 +148,7 @@ static void CallWriteCb(CFStreamEndpoint* ep, grpc_error* error) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, error); } -static void ReadAction(void* arg, grpc_error* error) { +static void ReadAction(void* arg, grpc_error_handle error) { CFStreamEndpoint* ep = static_cast(arg); GPR_ASSERT(ep->read_cb != nullptr); if (error) { @@ -192,7 +190,7 @@ static void ReadAction(void* arg, grpc_error* error) { } } -static void WriteAction(void* arg, grpc_error* error) { +static void WriteAction(void* arg, grpc_error_handle error) { CFStreamEndpoint* ep = static_cast(arg); GPR_ASSERT(ep->write_cb != nullptr); if (error) { @@ -242,7 +240,7 @@ static void WriteAction(void* arg, grpc_error* error) { grpc_slice_unref_internal(slice); } -static void CFStreamReadAllocationDone(void* arg, grpc_error* error) { +static void CFStreamReadAllocationDone(void* arg, grpc_error_handle error) { CFStreamEndpoint* ep = static_cast(arg); if (error == GRPC_ERROR_NONE) { ep->stream_sync->NotifyOnRead(&ep->read_action); @@ -286,7 +284,7 @@ static void CFStreamWrite(grpc_endpoint* ep, grpc_slice_buffer* slices, ep_impl->stream_sync->NotifyOnWrite(&ep_impl->write_action); } -void CFStreamShutdown(grpc_endpoint* ep, grpc_error* why) { +void CFStreamShutdown(grpc_endpoint* ep, grpc_error_handle why) { CFStreamEndpoint* ep_impl = reinterpret_cast(ep); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CFStream endpoint:%p shutdown (%p)", ep_impl, why); diff --git a/src/core/lib/iomgr/endpoint_pair_windows.cc b/src/core/lib/iomgr/endpoint_pair_windows.cc index 9962809a27b..c1113e1e55b 100644 --- a/src/core/lib/iomgr/endpoint_pair_windows.cc +++ b/src/core/lib/iomgr/endpoint_pair_windows.cc @@ -21,9 +21,9 @@ #include "src/core/lib/iomgr/port.h" #ifdef GRPC_WINSOCK_SOCKET +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/endpoint_pair.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include #include diff --git a/src/core/lib/iomgr/error.cc b/src/core/lib/iomgr/error.cc index 091014593ee..378bdf72954 100644 --- a/src/core/lib/iomgr/error.cc +++ b/src/core/lib/iomgr/error.cc @@ -41,6 +41,114 @@ grpc_core::DebugOnlyTraceFlag grpc_trace_error_refcount(false, "error_refcount"); grpc_core::DebugOnlyTraceFlag grpc_trace_closure(false, "closure"); +static gpr_atm g_error_creation_allowed = true; + +void grpc_disable_error_creation() { + gpr_atm_no_barrier_store(&g_error_creation_allowed, false); +} + +void grpc_enable_error_creation() { + gpr_atm_no_barrier_store(&g_error_creation_allowed, true); +} + +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + +absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg, + const grpc_core::DebugLocation& location, + size_t children_count, absl::Status* children) { + absl::Status s = StatusCreate(code, msg, location, {}); + for (size_t i = 0; i < children_count; ++i) { + if (!children[i].ok()) { + StatusAddChild(&s, children[i]); + } + } + return s; +} + +std::string grpc_error_std_string(const absl::Status& error) { + return grpc_core::StatusToString(error); +} + +absl::Status grpc_os_error(const grpc_core::DebugLocation& location, int err, + const char* call_name) { + absl::Status s = + StatusCreate(absl::StatusCode::kUnknown, "OS Error", location, {}); + grpc_core::StatusSetInt(&s, grpc_core::StatusIntProperty::ERRNO, err); + grpc_core::StatusSetStr(&s, grpc_core::StatusStrProperty::OS_ERROR, + strerror(err)); + grpc_core::StatusSetStr(&s, grpc_core::StatusStrProperty::SYSCALL, call_name); + return s; +} + +#ifdef GPR_WINDOWS +absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err, + const char* call_name) { + char* utf8_message = gpr_format_message(err); + absl::Status s = + StatusCreate(absl::StatusCode::kUnknown, "WSA Error", location, {}); + StatusSetInt(&s, StatusIntProperty::WSA_ERROR, err); + StatusSetStr(&s, StatusStrProperty::OS_ERROR, utf8_message); + StatusSetStr(&s, StatusStrProperty::SYSCALL, call_name); +} +#endif + +grpc_error_handle grpc_error_set_int(grpc_error_handle src, + grpc_error_ints which, intptr_t value) { + grpc_core::StatusSetInt( + &src, static_cast(which), value); + return src; +} + +bool grpc_error_get_int(grpc_error_handle error, grpc_error_ints which, + intptr_t* p) { + absl::optional value = grpc_core::StatusGetInt( + error, static_cast(which)); + if (value.has_value()) { + *p = *value; + return true; + } else { + return false; + } +} + +grpc_error_handle grpc_error_set_str(grpc_error_handle src, + grpc_error_strs which, + const grpc_slice& str) { + grpc_core::StatusSetStr( + &src, static_cast(which), + std::string(reinterpret_cast(GRPC_SLICE_START_PTR(str)), + GRPC_SLICE_LENGTH(str))); + return src; +} + +bool grpc_error_get_str(grpc_error_handle error, grpc_error_strs which, + grpc_slice* s) { + absl::optional value = grpc_core::StatusGetStr( + error, static_cast(which)); + if (value.has_value()) { + *s = grpc_slice_from_copied_buffer(value->c_str(), value->size()); + return true; + } else { + return false; + } +} + +grpc_error_handle grpc_error_add_child(grpc_error_handle src, + grpc_error_handle child) { + grpc_core::StatusAddChild(&src, child); + return src; +} + +bool grpc_log_error(const char* what, grpc_error_handle error, const char* file, + int line) { + GPR_DEBUG_ASSERT(error != GRPC_ERROR_NONE); + gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "%s: %s", what, + grpc_core::StatusToString(error).c_str()); + return false; +} + +#else // GRPC_ERROR_IS_ABSEIL_STATUS + static const char* error_int_name(grpc_error_ints key) { switch (key) { case GRPC_ERROR_INT_ERRNO: @@ -61,20 +169,18 @@ static const char* error_int_name(grpc_error_ints key) { return "http2_error"; case GRPC_ERROR_INT_TSI_CODE: return "tsi_code"; - case GRPC_ERROR_INT_SECURITY_STATUS: - return "security_status"; case GRPC_ERROR_INT_FD: return "fd"; case GRPC_ERROR_INT_WSA_ERROR: return "wsa_error"; case GRPC_ERROR_INT_HTTP_STATUS: return "http_status"; - case GRPC_ERROR_INT_LIMIT: - return "limit"; case GRPC_ERROR_INT_OCCURRED_DURING_WRITE: return "occurred_during_write"; case GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE: return "channel_connectivity_state"; + case GRPC_ERROR_INT_LB_POLICY_DROP: + return "lb_policy_drop"; case GRPC_ERROR_INT_MAX: GPR_UNREACHABLE_CODE(return "unknown"); } @@ -105,8 +211,6 @@ static const char* error_str_name(grpc_error_strs key) { return "tsi_error"; case GRPC_ERROR_STR_FILENAME: return "filename"; - case GRPC_ERROR_STR_QUEUED_BUFFERS: - return "queued_buffers"; case GRPC_ERROR_STR_MAX: GPR_UNREACHABLE_CODE(return "unknown"); } @@ -124,7 +228,8 @@ static const char* error_time_name(grpc_error_times key) { } #ifndef NDEBUG -grpc_error* grpc_error_do_ref(grpc_error* err, const char* file, int line) { +grpc_error_handle grpc_error_do_ref(grpc_error_handle err, const char* file, + int line) { if (grpc_trace_error_refcount.enabled()) { gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err, gpr_atm_no_barrier_load(&err->atomics.refs.count), @@ -134,13 +239,13 @@ grpc_error* grpc_error_do_ref(grpc_error* err, const char* file, int line) { return err; } #else -grpc_error* grpc_error_do_ref(grpc_error* err) { +grpc_error_handle grpc_error_do_ref(grpc_error_handle err) { gpr_ref(&err->atomics.refs); return err; } #endif -static void unref_errs(grpc_error* err) { +static void unref_errs(grpc_error_handle err) { uint8_t slot = err->first_err; while (slot != UINT8_MAX) { grpc_linked_error* lerr = @@ -152,7 +257,7 @@ static void unref_errs(grpc_error* err) { } } -static void unref_strs(grpc_error* err) { +static void unref_strs(grpc_error_handle err) { for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { uint8_t slot = err->strs[which]; if (slot != UINT8_MAX) { @@ -162,7 +267,7 @@ static void unref_strs(grpc_error* err) { } } -static void error_destroy(grpc_error* err) { +static void error_destroy(grpc_error_handle err) { GPR_ASSERT(!grpc_error_is_special(err)); unref_errs(err); unref_strs(err); @@ -172,7 +277,7 @@ static void error_destroy(grpc_error* err) { } #ifndef NDEBUG -void grpc_error_do_unref(grpc_error* err, const char* file, int line) { +void grpc_error_do_unref(grpc_error_handle err, const char* file, int line) { if (grpc_trace_error_refcount.enabled()) { gpr_log(GPR_DEBUG, "%p: %" PRIdPTR " -> %" PRIdPTR " [%s:%d]", err, gpr_atm_no_barrier_load(&err->atomics.refs.count), @@ -183,14 +288,14 @@ void grpc_error_do_unref(grpc_error* err, const char* file, int line) { } } #else -void grpc_error_do_unref(grpc_error* err) { +void grpc_error_do_unref(grpc_error_handle err) { if (gpr_unref(&err->atomics.refs)) { error_destroy(err); } } #endif -static uint8_t get_placement(grpc_error** err, size_t size) { +static uint8_t get_placement(grpc_error_handle* err, size_t size) { GPR_ASSERT(*err); uint8_t slots = static_cast(size / sizeof(intptr_t)); if ((*err)->arena_size + slots > (*err)->arena_capacity) { @@ -200,9 +305,9 @@ static uint8_t get_placement(grpc_error** err, size_t size) { return UINT8_MAX; } #ifndef NDEBUG - grpc_error* orig = *err; + grpc_error_handle orig = *err; #endif - *err = static_cast(gpr_realloc( + *err = static_cast(gpr_realloc( *err, sizeof(grpc_error) + (*err)->arena_capacity * sizeof(intptr_t))); #ifndef NDEBUG if (grpc_trace_error_refcount.enabled()) { @@ -217,7 +322,7 @@ static uint8_t get_placement(grpc_error** err, size_t size) { return placement; } -static void internal_set_int(grpc_error** err, grpc_error_ints which, +static void internal_set_int(grpc_error_handle* err, grpc_error_ints which, intptr_t value) { uint8_t slot = (*err)->ints[which]; if (slot == UINT8_MAX) { @@ -232,7 +337,7 @@ static void internal_set_int(grpc_error** err, grpc_error_ints which, (*err)->arena[slot] = value; } -static void internal_set_str(grpc_error** err, grpc_error_strs which, +static void internal_set_str(grpc_error_handle* err, grpc_error_strs which, const grpc_slice& value) { uint8_t slot = (*err)->strs[which]; if (slot == UINT8_MAX) { @@ -253,7 +358,7 @@ static void internal_set_str(grpc_error** err, grpc_error_strs which, } static char* fmt_time(gpr_timespec tm); -static void internal_set_time(grpc_error** err, grpc_error_times which, +static void internal_set_time(grpc_error_handle* err, grpc_error_times which, gpr_timespec value) { uint8_t slot = (*err)->times[which]; if (slot == UINT8_MAX) { @@ -270,7 +375,8 @@ static void internal_set_time(grpc_error** err, grpc_error_times which, memcpy((*err)->arena + slot, &value, sizeof(value)); } -static void internal_add_error(grpc_error** err, grpc_error* new_err) { +static void internal_add_error(grpc_error_handle* err, + grpc_error_handle new_err) { grpc_linked_error new_last = {new_err, UINT8_MAX}; uint8_t slot = get_placement(err, sizeof(grpc_linked_error)); if (slot == UINT8_MAX) { @@ -306,25 +412,16 @@ static void internal_add_error(grpc_error** err, grpc_error* new_err) { // It is very common to include and extra int and string in an error #define SURPLUS_CAPACITY (2 * SLOTS_PER_INT + SLOTS_PER_TIME) -static gpr_atm g_error_creation_allowed = true; - -void grpc_disable_error_creation() { - gpr_atm_no_barrier_store(&g_error_creation_allowed, false); -} - -void grpc_enable_error_creation() { - gpr_atm_no_barrier_store(&g_error_creation_allowed, true); -} - -grpc_error* grpc_error_create(const char* file, int line, - const grpc_slice& desc, grpc_error** referencing, - size_t num_referencing) { +grpc_error_handle grpc_error_create(const char* file, int line, + const grpc_slice& desc, + grpc_error_handle* referencing, + size_t num_referencing) { GPR_TIMER_SCOPE("grpc_error_create", 0); uint8_t initial_arena_capacity = static_cast( DEFAULT_ERROR_CAPACITY + static_cast(num_referencing * SLOTS_PER_LINKED_ERROR) + SURPLUS_CAPACITY); - grpc_error* err = static_cast( + grpc_error_handle err = static_cast( gpr_malloc(sizeof(*err) + initial_arena_capacity * sizeof(intptr_t))); if (err == nullptr) { // TODO(ctiller): make gpr_malloc return NULL return GRPC_ERROR_OOM; @@ -370,7 +467,7 @@ grpc_error* grpc_error_create(const char* file, int line, return err; } -static void ref_strs(grpc_error* err) { +static void ref_strs(grpc_error_handle err) { for (size_t i = 0; i < GRPC_ERROR_STR_MAX; ++i) { uint8_t slot = err->strs[i]; if (slot != UINT8_MAX) { @@ -380,7 +477,7 @@ static void ref_strs(grpc_error* err) { } } -static void ref_errs(grpc_error* err) { +static void ref_errs(grpc_error_handle err) { uint8_t slot = err->first_err; while (slot != UINT8_MAX) { grpc_linked_error* lerr = @@ -390,9 +487,9 @@ static void ref_errs(grpc_error* err) { } } -static grpc_error* copy_error_and_unref(grpc_error* in) { +static grpc_error_handle copy_error_and_unref(grpc_error_handle in) { GPR_TIMER_SCOPE("copy_error_and_unref", 0); - grpc_error* out; + grpc_error_handle out; if (grpc_error_is_special(in)) { out = GRPC_ERROR_CREATE_FROM_STATIC_STRING("unknown"); if (in == GRPC_ERROR_NONE) { @@ -417,7 +514,7 @@ static grpc_error* copy_error_and_unref(grpc_error* in) { static_cast SLOTS_PER_STR) { new_arena_capacity = static_cast(3 * new_arena_capacity / 2); } - out = static_cast( + out = static_cast( gpr_malloc(sizeof(*in) + new_arena_capacity * sizeof(intptr_t))); #ifndef NDEBUG if (grpc_trace_error_refcount.enabled()) { @@ -441,10 +538,10 @@ static grpc_error* copy_error_and_unref(grpc_error* in) { return out; } -grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which, - intptr_t value) { +grpc_error_handle grpc_error_set_int(grpc_error_handle src, + grpc_error_ints which, intptr_t value) { GPR_TIMER_SCOPE("grpc_error_set_int", 0); - grpc_error* new_err = copy_error_and_unref(src); + grpc_error_handle new_err = copy_error_and_unref(src); internal_set_int(&new_err, which, value); return new_err; } @@ -464,7 +561,8 @@ const special_error_status_map error_status_map[] = { strlen("Cancelled")}, // GRPC_ERROR_CANCELLED }; -bool grpc_error_get_int(grpc_error* err, grpc_error_ints which, intptr_t* p) { +bool grpc_error_get_int(grpc_error_handle err, grpc_error_ints which, + intptr_t* p) { GPR_TIMER_SCOPE("grpc_error_get_int", 0); if (grpc_error_is_special(err)) { if (which != GRPC_ERROR_INT_GRPC_STATUS) return false; @@ -479,15 +577,16 @@ bool grpc_error_get_int(grpc_error* err, grpc_error_ints which, intptr_t* p) { return false; } -grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which, - const grpc_slice& str) { +grpc_error_handle grpc_error_set_str(grpc_error_handle src, + grpc_error_strs which, + const grpc_slice& str) { GPR_TIMER_SCOPE("grpc_error_set_str", 0); - grpc_error* new_err = copy_error_and_unref(src); + grpc_error_handle new_err = copy_error_and_unref(src); internal_set_str(&new_err, which, str); return new_err; } -bool grpc_error_get_str(grpc_error* err, grpc_error_strs which, +bool grpc_error_get_str(grpc_error_handle err, grpc_error_strs which, grpc_slice* str) { if (grpc_error_is_special(err)) { if (which != GRPC_ERROR_STR_GRPC_MESSAGE) return false; @@ -508,14 +607,15 @@ bool grpc_error_get_str(grpc_error* err, grpc_error_strs which, } } -grpc_error* grpc_error_add_child(grpc_error* src, grpc_error* child) { +grpc_error_handle grpc_error_add_child(grpc_error_handle src, + grpc_error_handle child) { GPR_TIMER_SCOPE("grpc_error_add_child", 0); if (src != GRPC_ERROR_NONE) { if (child == GRPC_ERROR_NONE) { /* \a child is empty. Simply return the ref to \a src */ return src; } else if (child != src) { - grpc_error* new_err = copy_error_and_unref(src); + grpc_error_handle new_err = copy_error_and_unref(src); internal_add_error(&new_err, child); return new_err; } else { @@ -616,7 +716,7 @@ static char* fmt_int(intptr_t p) { return s; } -static void collect_ints_kvs(grpc_error* err, kv_pairs* kvs) { +static void collect_ints_kvs(grpc_error_handle err, kv_pairs* kvs) { for (size_t which = 0; which < GRPC_ERROR_INT_MAX; ++which) { uint8_t slot = err->ints[which]; if (slot != UINT8_MAX) { @@ -640,7 +740,7 @@ static char* fmt_str(const grpc_slice& slice) { return s; } -static void collect_strs_kvs(grpc_error* err, kv_pairs* kvs) { +static void collect_strs_kvs(grpc_error_handle err, kv_pairs* kvs) { for (size_t which = 0; which < GRPC_ERROR_STR_MAX; ++which) { uint8_t slot = err->strs[which]; if (slot != UINT8_MAX) { @@ -675,7 +775,7 @@ static char* fmt_time(gpr_timespec tm) { return out; } -static void collect_times_kvs(grpc_error* err, kv_pairs* kvs) { +static void collect_times_kvs(grpc_error_handle err, kv_pairs* kvs) { for (size_t which = 0; which < GRPC_ERROR_TIME_MAX; ++which) { uint8_t slot = err->times[which]; if (slot != UINT8_MAX) { @@ -685,7 +785,7 @@ static void collect_times_kvs(grpc_error* err, kv_pairs* kvs) { } } -static void add_errs(grpc_error* err, char** s, size_t* sz, size_t* cap) { +static void add_errs(grpc_error_handle err, char** s, size_t* sz, size_t* cap) { uint8_t slot = err->first_err; bool first = true; while (slot != UINT8_MAX) { @@ -701,7 +801,7 @@ static void add_errs(grpc_error* err, char** s, size_t* sz, size_t* cap) { } } -static char* errs_string(grpc_error* err) { +static char* errs_string(grpc_error_handle err) { char* s = nullptr; size_t sz = 0; size_t cap = 0; @@ -740,7 +840,7 @@ static char* finish_kvs(kv_pairs* kvs) { return s; } -const char* grpc_error_string(grpc_error* err) { +const char* grpc_error_string(grpc_error_handle err) { GPR_TIMER_SCOPE("grpc_error_string", 0); if (err == GRPC_ERROR_NONE) return no_error_string; if (err == GRPC_ERROR_OOM) return oom_error_string; @@ -775,8 +875,12 @@ const char* grpc_error_string(grpc_error* err) { return out; } -grpc_error* grpc_os_error(const char* file, int line, int err, - const char* call_name) { +std::string grpc_error_std_string(grpc_error_handle error) { + return std::string(grpc_error_string(error)); +} + +grpc_error_handle grpc_os_error(const char* file, int line, int err, + const char* call_name) { return grpc_error_set_str( grpc_error_set_str( grpc_error_set_int( @@ -790,10 +894,10 @@ grpc_error* grpc_os_error(const char* file, int line, int err, } #ifdef GPR_WINDOWS -grpc_error* grpc_wsa_error(const char* file, int line, int err, - const char* call_name) { +grpc_error_handle grpc_wsa_error(const char* file, int line, int err, + const char* call_name) { char* utf8_message = gpr_format_message(err); - grpc_error* error = grpc_error_set_str( + grpc_error_handle error = grpc_error_set_str( grpc_error_set_str( grpc_error_set_int( grpc_error_create(file, line, @@ -807,7 +911,7 @@ grpc_error* grpc_wsa_error(const char* file, int line, int err, } #endif -bool grpc_log_error(const char* what, grpc_error* error, const char* file, +bool grpc_log_error(const char* what, grpc_error_handle error, const char* file, int line) { GPR_DEBUG_ASSERT(error != GRPC_ERROR_NONE); const char* msg = grpc_error_string(error); @@ -815,3 +919,5 @@ bool grpc_log_error(const char* what, grpc_error* error, const char* file, GRPC_ERROR_UNREF(error); return false; } + +#endif // GRPC_ERROR_IS_ABSEIL_STATUS diff --git a/src/core/lib/iomgr/error.h b/src/core/lib/iomgr/error.h index ca520fa5678..aecd1e907cc 100644 --- a/src/core/lib/iomgr/error.h +++ b/src/core/lib/iomgr/error.h @@ -30,50 +30,70 @@ #include #include "src/core/lib/debug/trace.h" +#include "src/core/lib/gprpp/status_helper.h" + +#include "absl/status/status.h" /// Opaque representation of an error. /// See https://github.com/grpc/grpc/blob/master/doc/core/grpc-error.md for a /// full write up of this object. +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + +typedef absl::Status grpc_error_handle; + +#else // GRPC_ERROR_IS_ABSEIL_STATUS + typedef struct grpc_error grpc_error; +typedef grpc_error* grpc_error_handle; -extern grpc_core::DebugOnlyTraceFlag grpc_trace_error_refcount; +#endif // GRPC_ERROR_IS_ABSEIL_STATUS typedef enum { /// 'errno' from the operating system - GRPC_ERROR_INT_ERRNO, + GRPC_ERROR_INT_ERRNO = + static_cast(grpc_core::StatusIntProperty::kErrorNo), /// __LINE__ from the call site creating the error - GRPC_ERROR_INT_FILE_LINE, + GRPC_ERROR_INT_FILE_LINE = + static_cast(grpc_core::StatusIntProperty::kFileLine), /// stream identifier: for errors that are associated with an individual /// wire stream - GRPC_ERROR_INT_STREAM_ID, + GRPC_ERROR_INT_STREAM_ID = + static_cast(grpc_core::StatusIntProperty::kStreamId), /// grpc status code representing this error - GRPC_ERROR_INT_GRPC_STATUS, + GRPC_ERROR_INT_GRPC_STATUS = + static_cast(grpc_core::StatusIntProperty::kRpcStatus), /// offset into some binary blob (usually represented by /// GRPC_ERROR_STR_RAW_BYTES) where the error occurred - GRPC_ERROR_INT_OFFSET, + GRPC_ERROR_INT_OFFSET = + static_cast(grpc_core::StatusIntProperty::kOffset), /// context sensitive index associated with the error - GRPC_ERROR_INT_INDEX, + GRPC_ERROR_INT_INDEX = static_cast(grpc_core::StatusIntProperty::kIndex), /// context sensitive size associated with the error - GRPC_ERROR_INT_SIZE, + GRPC_ERROR_INT_SIZE = static_cast(grpc_core::StatusIntProperty::kSize), /// http2 error code associated with the error (see the HTTP2 RFC) - GRPC_ERROR_INT_HTTP2_ERROR, + GRPC_ERROR_INT_HTTP2_ERROR = + static_cast(grpc_core::StatusIntProperty::kHttp2Error), /// TSI status code associated with the error - GRPC_ERROR_INT_TSI_CODE, - /// grpc_security_status associated with the error - GRPC_ERROR_INT_SECURITY_STATUS, + GRPC_ERROR_INT_TSI_CODE = + static_cast(grpc_core::StatusIntProperty::kTsiCode), /// WSAGetLastError() reported when this error occurred - GRPC_ERROR_INT_WSA_ERROR, + GRPC_ERROR_INT_WSA_ERROR = + static_cast(grpc_core::StatusIntProperty::kWsaError), /// File descriptor associated with this error - GRPC_ERROR_INT_FD, + GRPC_ERROR_INT_FD = static_cast(grpc_core::StatusIntProperty::kFd), /// HTTP status (i.e. 404) - GRPC_ERROR_INT_HTTP_STATUS, - /// context sensitive limit associated with the error - GRPC_ERROR_INT_LIMIT, + GRPC_ERROR_INT_HTTP_STATUS = + static_cast(grpc_core::StatusIntProperty::kHttpStatus), /// chttp2: did the error occur while a write was in progress - GRPC_ERROR_INT_OCCURRED_DURING_WRITE, + GRPC_ERROR_INT_OCCURRED_DURING_WRITE = + static_cast(grpc_core::StatusIntProperty::kOccurredDuringWrite), /// channel connectivity state associated with the error - GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE, + GRPC_ERROR_INT_CHANNEL_CONNECTIVITY_STATE = + static_cast(grpc_core::StatusIntProperty::ChannelConnectivityState), + /// LB policy drop + GRPC_ERROR_INT_LB_POLICY_DROP = + static_cast(grpc_core::StatusIntProperty::kLbPolicyDrop), /// Must always be last GRPC_ERROR_INT_MAX, @@ -81,29 +101,35 @@ typedef enum { typedef enum { /// top-level textual description of this error - GRPC_ERROR_STR_DESCRIPTION, + GRPC_ERROR_STR_DESCRIPTION = + static_cast(grpc_core::StatusStrProperty::kDescription), /// source file in which this error occurred - GRPC_ERROR_STR_FILE, + GRPC_ERROR_STR_FILE = static_cast(grpc_core::StatusStrProperty::kFile), /// operating system description of this error - GRPC_ERROR_STR_OS_ERROR, + GRPC_ERROR_STR_OS_ERROR = + static_cast(grpc_core::StatusStrProperty::kOsError), /// syscall that generated this error - GRPC_ERROR_STR_SYSCALL, + GRPC_ERROR_STR_SYSCALL = + static_cast(grpc_core::StatusStrProperty::kSyscall), /// peer that we were trying to communicate when this error occurred - GRPC_ERROR_STR_TARGET_ADDRESS, + GRPC_ERROR_STR_TARGET_ADDRESS = + static_cast(grpc_core::StatusStrProperty::kTargetAddress), /// grpc status message associated with this error - GRPC_ERROR_STR_GRPC_MESSAGE, + GRPC_ERROR_STR_GRPC_MESSAGE = + static_cast(grpc_core::StatusStrProperty::kGrpcMessage), /// hex dump (or similar) with the data that generated this error - GRPC_ERROR_STR_RAW_BYTES, + GRPC_ERROR_STR_RAW_BYTES = + static_cast(grpc_core::StatusStrProperty::kRawBytes), /// tsi error string associated with this error - GRPC_ERROR_STR_TSI_ERROR, + GRPC_ERROR_STR_TSI_ERROR = + static_cast(grpc_core::StatusStrProperty::kTsiError), /// filename that we were trying to read/write when this error occurred - GRPC_ERROR_STR_FILENAME, - /// which data was queued for writing when the error occurred - GRPC_ERROR_STR_QUEUED_BUFFERS, + GRPC_ERROR_STR_FILENAME = + static_cast(grpc_core::StatusStrProperty::kFilename), /// key associated with the error - GRPC_ERROR_STR_KEY, + GRPC_ERROR_STR_KEY = static_cast(grpc_core::StatusStrProperty::kKey), /// value associated with the error - GRPC_ERROR_STR_VALUE, + GRPC_ERROR_STR_VALUE = static_cast(grpc_core::StatusStrProperty::kValue), /// Must always be last GRPC_ERROR_STR_MAX, @@ -117,32 +143,135 @@ typedef enum { GRPC_ERROR_TIME_MAX, } grpc_error_times; +// DEPRECATED: Use grpc_error_std_string instead +const char* grpc_error_string(grpc_error_handle error); +std::string grpc_error_std_string(grpc_error_handle error); + +// debug only toggles that allow for a sanity to check that ensures we will +// never create any errors in the per-RPC hotpath. +void grpc_disable_error_creation(); +void grpc_enable_error_creation(); + +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + +#define GRPC_ERROR_NONE absl::OkStatus() +#define GRPC_ERROR_OOM absl::Status(absl::ResourceExhaustedError) +#define GRPC_ERROR_CANCELLED absl::CancelledError() + +#define GRPC_ERROR_REF(err) (err) +#define GRPC_ERROR_UNREF(err) + +#define GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc) \ + StatusCreate(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {}) +#define GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc) \ + StatusCreate(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {}) +#define GRPC_ERROR_CREATE_FROM_STRING_VIEW(desc) \ + StatusCreate(ababsl::StatusCode::kUnknown, desc, DEBUG_LOCATION, {}) + +absl::Status grpc_status_create(absl::StatusCode code, absl::string_view msg, + const grpc_core::DebugLocation& location, + size_t children_count, + absl::Status* children) GRPC_MUST_USE_RESULT; + +// Create an error that references some other errors. This function adds a +// reference to each error in errs - it does not consume an existing reference +#define GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(desc, errs, count) \ + grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, count, \ + errs) +#define GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(desc, errs, count) \ + grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, count, \ + errs) + +// Consumes all the errors in the vector and forms a referencing error from +// them. If the vector is empty, return GRPC_ERROR_NONE. +template +static absl::Status grpc_status_create_from_vector( + const grpc_core::DebugLocation& location, const char* desc, + VectorType* error_list) { + absl::Status error = GRPC_ERROR_NONE; + if (error_list->size() != 0) { + error = grpc_status_create(absl::StatusCode::kUnknown, desc, DEBUG_LOCATION, + error_list->size(), error_list->data()); + error_list->clear(); + } + return error; +} + +#define GRPC_ERROR_CREATE_FROM_VECTOR(desc, error_list) \ + grpc_status_create_from_vector(DEBUG_LOCATION, desc, error_list) + +absl::Status grpc_os_error(const grpc_core::DebugLocation& location, int err, + const char* call_name) GRPC_MUST_USE_RESULT; + +inline absl::Status grpc_assert_never_ok(absl::Status error) { + GPR_ASSERT(error != GRPC_ERROR_NONE); + return error; +} + +/// create an error associated with errno!=0 (an 'operating system' error) +#define GRPC_OS_ERROR(err, call_name) \ + grpc_assert_never_ok(grpc_os_error(DEBUG_LOCATION, err, call_name)) + +absl::Status grpc_wsa_error(const grpc_core::DebugLocation& location, int err, + const char* call_name) GRPC_MUST_USE_RESULT; + +/// windows only: create an error associated with WSAGetLastError()!=0 +#define GRPC_WSA_ERROR(err, call_name) \ + grpc_wsa_error(DEBUG_LOCATION, err, call_name) + +#else // GRPC_ERROR_IS_ABSEIL_STATUS + /// The following "special" errors can be propagated without allocating memory. /// They are always even so that other code (particularly combiner locks, /// polling engines) can safely use the lower bit for themselves. -#define GRPC_ERROR_NONE ((grpc_error*)NULL) -#define GRPC_ERROR_RESERVED_1 ((grpc_error*)1) -#define GRPC_ERROR_OOM ((grpc_error*)2) -#define GRPC_ERROR_RESERVED_2 ((grpc_error*)3) -#define GRPC_ERROR_CANCELLED ((grpc_error*)4) +#define GRPC_ERROR_NONE ((grpc_error_handle)NULL) +#define GRPC_ERROR_RESERVED_1 ((grpc_error_handle)1) +#define GRPC_ERROR_OOM ((grpc_error_handle)2) +#define GRPC_ERROR_RESERVED_2 ((grpc_error_handle)3) +#define GRPC_ERROR_CANCELLED ((grpc_error_handle)4) #define GRPC_ERROR_SPECIAL_MAX GRPC_ERROR_CANCELLED -inline bool grpc_error_is_special(struct grpc_error* err) { +inline bool grpc_error_is_special(grpc_error_handle err) { return err <= GRPC_ERROR_SPECIAL_MAX; } -// debug only toggles that allow for a sanity to check that ensures we will -// never create any errors in the per-RPC hotpath. -void grpc_disable_error_creation(); -void grpc_enable_error_creation(); - -const char* grpc_error_string(grpc_error* error); +#ifndef NDEBUG +grpc_error_handle grpc_error_do_ref(grpc_error_handle err, const char* file, + int line); +void grpc_error_do_unref(grpc_error_handle err, const char* file, int line); +inline grpc_error_handle grpc_error_ref(grpc_error_handle err, const char* file, + int line) { + if (grpc_error_is_special(err)) return err; + return grpc_error_do_ref(err, file, line); +} +inline void grpc_error_unref(grpc_error_handle err, const char* file, + int line) { + if (grpc_error_is_special(err)) return; + grpc_error_do_unref(err, file, line); +} +#define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__) +#define GRPC_ERROR_UNREF(err) grpc_error_unref(err, __FILE__, __LINE__) +#else +grpc_error_handle grpc_error_do_ref(grpc_error_handle err); +void grpc_error_do_unref(grpc_error_handle err); +inline grpc_error_handle grpc_error_ref(grpc_error_handle err) { + if (grpc_error_is_special(err)) return err; + return grpc_error_do_ref(err); +} +inline void grpc_error_unref(grpc_error_handle err) { + if (grpc_error_is_special(err)) return; + grpc_error_do_unref(err); +} +#define GRPC_ERROR_REF(err) grpc_error_ref(err) +#define GRPC_ERROR_UNREF(err) grpc_error_unref(err) +#endif /// Create an error - but use GRPC_ERROR_CREATE instead -grpc_error* grpc_error_create(const char* file, int line, - const grpc_slice& desc, grpc_error** referencing, - size_t num_referencing); +grpc_error_handle grpc_error_create(const char* file, int line, + const grpc_slice& desc, + grpc_error_handle* referencing, + size_t num_referencing); /// Create an error (this is the preferred way of generating an error that is /// not due to a system call - for system calls, use GRPC_OS_ERROR or /// GRPC_WSA_ERROR as appropriate) @@ -157,6 +286,10 @@ grpc_error* grpc_error_create(const char* file, int line, #define GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc) \ grpc_error_create(__FILE__, __LINE__, grpc_slice_from_copied_string(desc), \ NULL, 0) +#define GRPC_ERROR_CREATE_FROM_STRING_VIEW(desc) \ + grpc_error_create( \ + __FILE__, __LINE__, \ + grpc_slice_from_copied_buffer((desc).data(), (desc).size()), NULL, 0) // Create an error that references some other errors. This function adds a // reference to each error in errs - it does not consume an existing reference @@ -170,41 +303,14 @@ grpc_error* grpc_error_create(const char* file, int line, #define GRPC_ERROR_CREATE_FROM_VECTOR(desc, error_list) \ grpc_error_create_from_vector(__FILE__, __LINE__, desc, error_list) -#ifndef NDEBUG -grpc_error* grpc_error_do_ref(grpc_error* err, const char* file, int line); -void grpc_error_do_unref(grpc_error* err, const char* file, int line); -inline grpc_error* grpc_error_ref(grpc_error* err, const char* file, int line) { - if (grpc_error_is_special(err)) return err; - return grpc_error_do_ref(err, file, line); -} -inline void grpc_error_unref(grpc_error* err, const char* file, int line) { - if (grpc_error_is_special(err)) return; - grpc_error_do_unref(err, file, line); -} -#define GRPC_ERROR_REF(err) grpc_error_ref(err, __FILE__, __LINE__) -#define GRPC_ERROR_UNREF(err) grpc_error_unref(err, __FILE__, __LINE__) -#else -grpc_error* grpc_error_do_ref(grpc_error* err); -void grpc_error_do_unref(grpc_error* err); -inline grpc_error* grpc_error_ref(grpc_error* err) { - if (grpc_error_is_special(err)) return err; - return grpc_error_do_ref(err); -} -inline void grpc_error_unref(grpc_error* err) { - if (grpc_error_is_special(err)) return; - grpc_error_do_unref(err); -} -#define GRPC_ERROR_REF(err) grpc_error_ref(err) -#define GRPC_ERROR_UNREF(err) grpc_error_unref(err) -#endif - // Consumes all the errors in the vector and forms a referencing error from // them. If the vector is empty, return GRPC_ERROR_NONE. template -static grpc_error* grpc_error_create_from_vector(const char* file, int line, - const char* desc, - VectorType* error_list) { - grpc_error* error = GRPC_ERROR_NONE; +static grpc_error_handle grpc_error_create_from_vector(const char* file, + int line, + const char* desc, + VectorType* error_list) { + grpc_error_handle error = GRPC_ERROR_NONE; if (error_list->size() != 0) { error = grpc_error_create(file, line, grpc_slice_from_static_string(desc), error_list->data(), error_list->size()); @@ -217,18 +323,40 @@ static grpc_error* grpc_error_create_from_vector(const char* file, int line, return error; } -grpc_error* grpc_error_set_int(grpc_error* src, grpc_error_ints which, - intptr_t value) GRPC_MUST_USE_RESULT; +grpc_error_handle grpc_os_error(const char* file, int line, int err, + const char* call_name) GRPC_MUST_USE_RESULT; + +inline grpc_error_handle grpc_assert_never_ok(grpc_error_handle error) { + GPR_ASSERT(error != GRPC_ERROR_NONE); + return error; +} + +/// create an error associated with errno!=0 (an 'operating system' error) +#define GRPC_OS_ERROR(err, call_name) \ + grpc_assert_never_ok(grpc_os_error(__FILE__, __LINE__, err, call_name)) +grpc_error_handle grpc_wsa_error(const char* file, int line, int err, + const char* call_name) GRPC_MUST_USE_RESULT; +/// windows only: create an error associated with WSAGetLastError()!=0 +#define GRPC_WSA_ERROR(err, call_name) \ + grpc_wsa_error(__FILE__, __LINE__, err, call_name) + +#endif // GRPC_ERROR_IS_ABSEIL_STATUS + +grpc_error_handle grpc_error_set_int(grpc_error_handle src, + grpc_error_ints which, + intptr_t value) GRPC_MUST_USE_RESULT; /// It is an error to pass nullptr as `p`. Caller should allocate a phony /// intptr_t for `p`, even if the value of `p` is not used. -bool grpc_error_get_int(grpc_error* error, grpc_error_ints which, intptr_t* p); +bool grpc_error_get_int(grpc_error_handle error, grpc_error_ints which, + intptr_t* p); /// This call takes ownership of the slice; the error is responsible for /// eventually unref-ing it. -grpc_error* grpc_error_set_str(grpc_error* src, grpc_error_strs which, - const grpc_slice& str) GRPC_MUST_USE_RESULT; +grpc_error_handle grpc_error_set_str( + grpc_error_handle src, grpc_error_strs which, + const grpc_slice& str) GRPC_MUST_USE_RESULT; /// Returns false if the specified string is not set. /// Caller does NOT own the slice. -bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, +bool grpc_error_get_str(grpc_error_handle error, grpc_error_strs which, grpc_slice* s); /// Add a child error: an error that is believed to have contributed to this @@ -242,29 +370,12 @@ bool grpc_error_get_str(grpc_error* error, grpc_error_strs which, /// returns GRPC_ERROR_NONE. 3) If \a src and \a child point to the same error, /// returns a single reference. (Note that, 2 references should have been /// received to the error in this case.) -grpc_error* grpc_error_add_child(grpc_error* src, - grpc_error* child) GRPC_MUST_USE_RESULT; - -grpc_error* grpc_os_error(const char* file, int line, int err, - const char* call_name) GRPC_MUST_USE_RESULT; - -inline grpc_error* grpc_assert_never_ok(grpc_error* error) { - GPR_ASSERT(error != GRPC_ERROR_NONE); - return error; -} - -/// create an error associated with errno!=0 (an 'operating system' error) -#define GRPC_OS_ERROR(err, call_name) \ - grpc_assert_never_ok(grpc_os_error(__FILE__, __LINE__, err, call_name)) -grpc_error* grpc_wsa_error(const char* file, int line, int err, - const char* call_name) GRPC_MUST_USE_RESULT; -/// windows only: create an error associated with WSAGetLastError()!=0 -#define GRPC_WSA_ERROR(err, call_name) \ - grpc_wsa_error(__FILE__, __LINE__, err, call_name) +grpc_error_handle grpc_error_add_child( + grpc_error_handle src, grpc_error_handle child) GRPC_MUST_USE_RESULT; -bool grpc_log_error(const char* what, grpc_error* error, const char* file, +bool grpc_log_error(const char* what, grpc_error_handle error, const char* file, int line); -inline bool grpc_log_if_error(const char* what, grpc_error* error, +inline bool grpc_log_if_error(const char* what, grpc_error_handle error, const char* file, int line) { return error == GRPC_ERROR_NONE ? true : grpc_log_error(what, error, file, line); diff --git a/src/core/lib/iomgr/error_cfstream.cc b/src/core/lib/iomgr/error_cfstream.cc index 7bf286585ac..114b3f2e4eb 100644 --- a/src/core/lib/iomgr/error_cfstream.cc +++ b/src/core/lib/iomgr/error_cfstream.cc @@ -31,8 +31,9 @@ #define MAX_ERROR_DESCRIPTION 256 -grpc_error* grpc_error_create_from_cferror(const char* file, int line, - void* arg, const char* custom_desc) { +grpc_error_handle grpc_error_create_from_cferror(const char* file, int line, + void* arg, + const char* custom_desc) { CFErrorRef error = static_cast(arg); char buf_domain[MAX_ERROR_DESCRIPTION]; char buf_desc[MAX_ERROR_DESCRIPTION]; diff --git a/src/core/lib/iomgr/error_cfstream.h b/src/core/lib/iomgr/error_cfstream.h index 06ab7513296..2d5b744c74e 100644 --- a/src/core/lib/iomgr/error_cfstream.h +++ b/src/core/lib/iomgr/error_cfstream.h @@ -24,8 +24,8 @@ #define GRPC_ERROR_CREATE_FROM_CFERROR(error, desc) \ grpc_error_create_from_cferror(__FILE__, __LINE__, \ static_cast((error)), (desc)) -grpc_error* grpc_error_create_from_cferror(const char* file, int line, - void* arg, const char* desc); +grpc_error_handle grpc_error_create_from_cferror(const char* file, int line, + void* arg, const char* desc); #endif /* GRPC_CFSTREAM */ #endif /* GRPC_CORE_LIB_IOMGR_ERROR_CFSTREAM_H */ diff --git a/src/core/lib/iomgr/error_internal.h b/src/core/lib/iomgr/error_internal.h index 33c233b9b67..50c1ddeb2dc 100644 --- a/src/core/lib/iomgr/error_internal.h +++ b/src/core/lib/iomgr/error_internal.h @@ -27,10 +27,12 @@ #include #include "src/core/lib/iomgr/error.h" +#ifndef GRPC_ERROR_IS_ABSEIL_STATUS + typedef struct grpc_linked_error grpc_linked_error; struct grpc_linked_error { - grpc_error* err; + grpc_error_handle err; uint8_t next; }; @@ -58,4 +60,6 @@ struct grpc_error { intptr_t arena[0]; }; +#endif // GRPC_ERROR_IS_ABSEIL_STATUS + #endif /* GRPC_CORE_LIB_IOMGR_ERROR_INTERNAL_H */ diff --git a/src/core/lib/iomgr/ev_apple.cc b/src/core/lib/iomgr/ev_apple.cc index 1264866bd38..25805826294 100644 --- a/src/core/lib/iomgr/ev_apple.cc +++ b/src/core/lib/iomgr/ev_apple.cc @@ -219,9 +219,9 @@ static void pollset_global_shutdown(void) { /// The Apple pollset simply waits on a condition variable until it is kicked. /// The network events are handled in the global run loop thread. Processing of /// these events will eventually trigger the kick. -static grpc_error* pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** worker, + grpc_millis deadline) { GRPC_POLLING_TRACE("pollset work: %p, worker: %p, deadline: %" PRIu64, pollset, worker, deadline); GrpcApplePollset* apple_pollset = @@ -272,8 +272,8 @@ static void kick_worker(GrpcAppleWorker* worker) { /// The caller must acquire the lock GrpcApplePollset.mu before calling this /// function. The kick action simply signals the condition variable of the /// worker. -static grpc_error* pollset_kick(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker) { +static grpc_error_handle pollset_kick(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker) { GrpcApplePollset* apple_pollset = reinterpret_cast(pollset); diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc index a8508701294..f09cd78b8fb 100644 --- a/src/core/lib/iomgr/ev_epoll1_linux.cc +++ b/src/core/lib/iomgr/ev_epoll1_linux.cc @@ -241,7 +241,7 @@ struct grpc_pollset_set { * Common helpers */ -static bool append_error(grpc_error** composite, grpc_error* error, +static bool append_error(grpc_error_handle* composite, grpc_error_handle error, const char* desc) { if (error == GRPC_ERROR_NONE) return true; if (*composite == GRPC_ERROR_NONE) { @@ -382,7 +382,7 @@ static int fd_wrapped_fd(grpc_fd* fd) { return fd->fd; } /* if 'releasing_fd' is true, it means that we are going to detach the internal * fd from grpc_fd structure (i.e which means we should not be calling * shutdown() syscall on that fd) */ -static void fd_shutdown_internal(grpc_fd* fd, grpc_error* why, +static void fd_shutdown_internal(grpc_fd* fd, grpc_error_handle why, bool releasing_fd) { if (fd->read_closure->SetShutdown(GRPC_ERROR_REF(why))) { if (!releasing_fd) { @@ -402,13 +402,13 @@ static void fd_shutdown_internal(grpc_fd* fd, grpc_error* why, } /* Might be called multiple times */ -static void fd_shutdown(grpc_fd* fd, grpc_error* why) { +static void fd_shutdown(grpc_fd* fd, grpc_error_handle why) { fd_shutdown_internal(fd, why, false); } static void fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, const char* reason) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; bool is_release_fd = (release_fd != nullptr); if (!fd->read_closure->IsShutdown()) { @@ -514,12 +514,12 @@ static size_t choose_neighborhood(void) { return static_cast(gpr_cpu_current_cpu()) % g_num_neighborhoods; } -static grpc_error* pollset_global_init(void) { +static grpc_error_handle pollset_global_init(void) { gpr_tls_init(&g_current_thread_pollset); gpr_tls_init(&g_current_thread_worker); gpr_atm_no_barrier_store(&g_active_poller, 0); global_wakeup_fd.read_fd = -1; - grpc_error* err = grpc_wakeup_fd_init(&global_wakeup_fd); + grpc_error_handle err = grpc_wakeup_fd_init(&global_wakeup_fd); if (err != GRPC_ERROR_NONE) return err; struct epoll_event ev; ev.events = static_cast(EPOLLIN | EPOLLET); @@ -589,9 +589,9 @@ static void pollset_destroy(grpc_pollset* pollset) { gpr_mu_destroy(&pollset->mu); } -static grpc_error* pollset_kick_all(grpc_pollset* pollset) { +static grpc_error_handle pollset_kick_all(grpc_pollset* pollset) { GPR_TIMER_SCOPE("pollset_kick_all", 0); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (pollset->root_worker != nullptr) { grpc_pollset_worker* worker = pollset->root_worker; do { @@ -663,11 +663,11 @@ static int poll_deadline_to_millis_timeout(grpc_millis millis) { NOTE ON SYNCRHONIZATION: Similar to do_epoll_wait(), this function is only called by g_active_poller thread. So there is no need for synchronization when accessing fields in g_epoll_set */ -static grpc_error* process_epoll_events(grpc_pollset* /*pollset*/) { +static grpc_error_handle process_epoll_events(grpc_pollset* /*pollset*/) { GPR_TIMER_SCOPE("process_epoll_events", 0); static const char* err_desc = "process_events"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; long num_events = gpr_atm_acq_load(&g_epoll_set.num_events); long cursor = gpr_atm_acq_load(&g_epoll_set.cursor); for (int idx = 0; @@ -715,7 +715,7 @@ static grpc_error* process_epoll_events(grpc_pollset* /*pollset*/) { NOTE ON SYNCHRONIZATION: At any point of time, only the g_active_poller (i.e the designated poller thread) will be calling this function. So there is no need for any synchronization when accesing fields in g_epoll_set */ -static grpc_error* do_epoll_wait(grpc_pollset* ps, grpc_millis deadline) { +static grpc_error_handle do_epoll_wait(grpc_pollset* ps, grpc_millis deadline) { GPR_TIMER_SCOPE("do_epoll_wait", 0); int r; @@ -1014,12 +1014,12 @@ static void end_worker(grpc_pollset* pollset, grpc_pollset_worker* worker, The function pollset_work() may temporarily release the lock (pollset->po.mu) during the course of its execution but it will always re-acquire the lock and ensure that it is held by the time the function returns */ -static grpc_error* pollset_work(grpc_pollset* ps, - grpc_pollset_worker** worker_hdl, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* ps, + grpc_pollset_worker** worker_hdl, + grpc_millis deadline) { GPR_TIMER_SCOPE("pollset_work", 0); grpc_pollset_worker worker; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; static const char* err_desc = "pollset_work"; if (ps->kicked_without_poller) { ps->kicked_without_poller = false; @@ -1065,11 +1065,11 @@ static grpc_error* pollset_work(grpc_pollset* ps, return error; } -static grpc_error* pollset_kick(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker) { +static grpc_error_handle pollset_kick(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker) { GPR_TIMER_SCOPE("pollset_kick", 0); GRPC_STATS_INC_POLLSET_KICK(); - grpc_error* ret_err = GRPC_ERROR_NONE; + grpc_error_handle ret_err = GRPC_ERROR_NONE; if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { std::vector log; log.push_back(absl::StrFormat( @@ -1260,7 +1260,7 @@ static bool is_any_background_poller_thread(void) { return false; } static void shutdown_background_closure(void) {} static bool add_closure_to_background_poller(grpc_closure* /*closure*/, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { return false; } diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc index f26a99293af..72d7da76ba5 100644 --- a/src/core/lib/iomgr/ev_epollex_linux.cc +++ b/src/core/lib/iomgr/ev_epollex_linux.cc @@ -134,7 +134,7 @@ static std::string pollable_desc(pollable* p) { /// added static pollable* g_empty_pollable; -static grpc_error* pollable_create(pollable_type type, pollable** p); +static grpc_error_handle pollable_create(pollable_type type, pollable** p); static pollable* pollable_ref(pollable* p, const grpc_core::DebugLocation& dbg_loc, const char* reason) { @@ -314,7 +314,7 @@ struct grpc_pollset_set { * Common helpers */ -static bool append_error(grpc_error** composite, grpc_error* error, +static bool append_error(grpc_error_handle* composite, grpc_error_handle error, const char* desc) { if (error == GRPC_ERROR_NONE) return true; if (*composite == GRPC_ERROR_NONE) { @@ -372,7 +372,7 @@ static void ref_by(grpc_fd* fd, int n) { } /* Uninitialize and add to the freelist */ -static void fd_destroy(void* arg, grpc_error* /*error*/) { +static void fd_destroy(void* arg, grpc_error_handle /*error*/) { grpc_fd* fd = static_cast(arg); fd->destroy(); @@ -509,7 +509,7 @@ static bool fd_is_shutdown(grpc_fd* fd) { } /* Might be called multiple times */ -static void fd_shutdown(grpc_fd* fd, grpc_error* why) { +static void fd_shutdown(grpc_fd* fd, grpc_error_handle why) { if (fd->read_closure.SetShutdown(GRPC_ERROR_REF(why))) { if (shutdown(fd->fd, SHUT_RDWR)) { if (errno != ENOTCONN) { @@ -556,7 +556,7 @@ static void fd_add_pollset(grpc_fd* fd, grpc_pollset* pollset) { * Pollable Definitions */ -static grpc_error* pollable_create(pollable_type type, pollable** p) { +static grpc_error_handle pollable_create(pollable_type type, pollable** p) { *p = nullptr; int epfd = epoll_create1(EPOLL_CLOEXEC); @@ -565,7 +565,7 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { } GRPC_FD_TRACE("Pollable_create: created epfd: %d (type: %d)", epfd, type); *p = static_cast(gpr_malloc(sizeof(**p))); - grpc_error* err = grpc_wakeup_fd_init(&(*p)->wakeup); + grpc_error_handle err = grpc_wakeup_fd_init(&(*p)->wakeup); if (err != GRPC_ERROR_NONE) { GRPC_FD_TRACE( "Pollable_create: closed epfd: %d (type: %d). wakeupfd_init error", @@ -609,8 +609,8 @@ static grpc_error* pollable_create(pollable_type type, pollable** p) { return GRPC_ERROR_NONE; } -static grpc_error* pollable_add_fd(pollable* p, grpc_fd* fd) { - grpc_error* error = GRPC_ERROR_NONE; +static grpc_error_handle pollable_add_fd(pollable* p, grpc_fd* fd) { + grpc_error_handle error = GRPC_ERROR_NONE; static const char* err_desc = "pollable_add_fd"; const int epfd = p->epfd; if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { @@ -647,7 +647,7 @@ GPR_TLS_DECL(g_current_thread_pollset); GPR_TLS_DECL(g_current_thread_worker); /* Global state management */ -static grpc_error* pollset_global_init(void) { +static grpc_error_handle pollset_global_init(void) { gpr_tls_init(&g_current_thread_pollset); gpr_tls_init(&g_current_thread_worker); return pollable_create(PO_EMPTY, &g_empty_pollable); @@ -681,7 +681,7 @@ static void pollset_maybe_finish_shutdown(grpc_pollset* pollset) { /* pollset->mu must be held before calling this function, * pollset->active_pollable->mu & specific_worker->pollable_obj->mu must not be * held */ -static grpc_error* kick_one_worker(grpc_pollset_worker* specific_worker) { +static grpc_error_handle kick_one_worker(grpc_pollset_worker* specific_worker) { GPR_TIMER_SCOPE("kick_one_worker", 0); pollable* p = specific_worker->pollable_obj; grpc_core::MutexLockForGprMu lock(&p->mu); @@ -708,7 +708,7 @@ static grpc_error* kick_one_worker(grpc_pollset_worker* specific_worker) { gpr_log(GPR_INFO, "PS:%p kicked_specific_via_wakeup_fd", p); } specific_worker->kicked = true; - grpc_error* error = grpc_wakeup_fd_wakeup(&p->wakeup); + grpc_error_handle error = grpc_wakeup_fd_wakeup(&p->wakeup); return error; } if (specific_worker->initialized_cv) { @@ -725,8 +725,8 @@ static grpc_error* kick_one_worker(grpc_pollset_worker* specific_worker) { return GRPC_ERROR_NONE; } -static grpc_error* pollset_kick(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker) { +static grpc_error_handle pollset_kick(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker) { GPR_TIMER_SCOPE("pollset_kick", 0); GRPC_STATS_INC_POLLSET_KICK(); if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { @@ -777,9 +777,9 @@ static grpc_error* pollset_kick(grpc_pollset* pollset, } } -static grpc_error* pollset_kick_all(grpc_pollset* pollset) { +static grpc_error_handle pollset_kick_all(grpc_pollset* pollset) { GPR_TIMER_SCOPE("pollset_kick_all", 0); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; const char* err_desc = "pollset_kick_all"; grpc_pollset_worker* w = pollset->root_worker; if (w != nullptr) { @@ -828,9 +828,9 @@ static void fd_has_errors(grpc_fd* fd) { fd->error_closure.SetReady(); } * * Note that if a pollable object is already attached to the fd, it may be of * either PO_FD or PO_MULTI type */ -static grpc_error* get_fd_pollable(grpc_fd* fd, pollable** p) { +static grpc_error_handle get_fd_pollable(grpc_fd* fd, pollable** p) { gpr_mu_lock(&fd->pollable_mu); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; static const char* err_desc = "get_fd_pollable"; if (fd->pollable_obj == nullptr) { if (append_error(&error, pollable_create(PO_FD, &fd->pollable_obj), @@ -863,8 +863,9 @@ static void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) { pollset_maybe_finish_shutdown(pollset); } -static grpc_error* pollable_process_events(grpc_pollset* pollset, - pollable* pollable_obj, bool drain) { +static grpc_error_handle pollable_process_events(grpc_pollset* pollset, + pollable* pollable_obj, + bool drain) { GPR_TIMER_SCOPE("pollable_process_events", 0); static const char* err_desc = "pollset_process_events"; // Use a simple heuristic to determine how many fd events to process @@ -877,7 +878,7 @@ static grpc_error* pollable_process_events(grpc_pollset* pollset, if (handle_count == 0) { handle_count = 1; } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; for (int i = 0; (drain || i < handle_count) && pollable_obj->event_cursor != pollable_obj->event_count; i++) { @@ -932,7 +933,7 @@ static void pollset_destroy(grpc_pollset* pollset) { gpr_mu_destroy(&pollset->mu); } -static grpc_error* pollable_epoll(pollable* p, grpc_millis deadline) { +static grpc_error_handle pollable_epoll(pollable* p, grpc_millis deadline) { GPR_TIMER_SCOPE("pollable_epoll", 0); int timeout = poll_deadline_to_millis_timeout(deadline); @@ -1103,9 +1104,9 @@ static long sys_gettid(void) { return syscall(__NR_gettid); } The function pollset_work() may temporarily release the lock (pollset->po.mu) during the course of its execution but it will always re-acquire the lock and ensure that it is held by the time the function returns */ -static grpc_error* pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker_hdl, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** worker_hdl, + grpc_millis deadline) { GPR_TIMER_SCOPE("pollset_work", 0); #ifdef GRPC_EPOLLEX_CREATE_WORKERS_ON_HEAP grpc_pollset_worker* worker = @@ -1126,7 +1127,7 @@ static grpc_error* pollset_work(grpc_pollset* pollset, deadline, pollset->kicked_without_poller, pollset->active_pollable); } static const char* err_desc = "pollset_work"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (pollset->kicked_without_poller) { pollset->kicked_without_poller = false; } else { @@ -1155,10 +1156,10 @@ static grpc_error* pollset_work(grpc_pollset* pollset, return error; } -static grpc_error* pollset_transition_pollable_from_empty_to_fd_locked( +static grpc_error_handle pollset_transition_pollable_from_empty_to_fd_locked( grpc_pollset* pollset, grpc_fd* fd) { static const char* err_desc = "pollset_transition_pollable_from_empty_to_fd"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, "PS:%p add fd %p (%d); transition pollable from empty to fd", @@ -1171,10 +1172,10 @@ static grpc_error* pollset_transition_pollable_from_empty_to_fd_locked( return error; } -static grpc_error* pollset_transition_pollable_from_fd_to_multi_locked( +static grpc_error_handle pollset_transition_pollable_from_fd_to_multi_locked( grpc_pollset* pollset, grpc_fd* and_add_fd) { static const char* err_desc = "pollset_transition_pollable_from_fd_to_multi"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log( GPR_INFO, @@ -1200,8 +1201,9 @@ static grpc_error* pollset_transition_pollable_from_fd_to_multi_locked( } /* expects pollsets locked, flag whether fd is locked or not */ -static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { - grpc_error* error = GRPC_ERROR_NONE; +static grpc_error_handle pollset_add_fd_locked(grpc_pollset* pollset, + grpc_fd* fd) { + grpc_error_handle error = GRPC_ERROR_NONE; pollable* po_at_start = POLLABLE_REF(pollset->active_pollable, "pollset_add_fd"); switch (pollset->active_pollable->type) { @@ -1236,9 +1238,9 @@ static grpc_error* pollset_add_fd_locked(grpc_pollset* pollset, grpc_fd* fd) { return error; } -static grpc_error* pollset_as_multipollable_locked(grpc_pollset* pollset, - pollable** pollable_obj) { - grpc_error* error = GRPC_ERROR_NONE; +static grpc_error_handle pollset_as_multipollable_locked( + grpc_pollset* pollset, pollable** pollable_obj) { + grpc_error_handle error = GRPC_ERROR_NONE; pollable* po_at_start = POLLABLE_REF(pollset->active_pollable, "pollset_as_multipollable"); switch (pollset->active_pollable->type) { @@ -1297,7 +1299,7 @@ static void pollset_add_fd(grpc_pollset* pollset, grpc_fd* fd) { } grpc_core::MutexLockForGprMu lock(&pollset->mu); - grpc_error* error = pollset_add_fd_locked(pollset, fd); + grpc_error_handle error = pollset_add_fd_locked(pollset, fd); // If we are in PO_MULTI mode, we should update the pollsets of the FD. if (gpr_atm_no_barrier_load(&pollset->active_pollable_type) == PO_MULTI) { @@ -1354,7 +1356,7 @@ static void pollset_set_add_fd(grpc_pollset_set* pss, grpc_fd* fd) { if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, "PSS:%p: add fd %p (%d)", pss, fd, fd->fd); } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; static const char* err_desc = "pollset_set_add_fd"; pss = pss_lock_adam(pss); for (size_t i = 0; i < pss->pollset_count; i++) { @@ -1421,13 +1423,14 @@ static void pollset_set_del_pollset(grpc_pollset_set* pss, grpc_pollset* ps) { // add all fds to pollables, and output a new array of unorphaned out_fds // assumes pollsets are multipollable -static grpc_error* add_fds_to_pollsets(grpc_fd** fds, size_t fd_count, - grpc_pollset** pollsets, - size_t pollset_count, - const char* err_desc, grpc_fd** out_fds, - size_t* out_fd_count) { +static grpc_error_handle add_fds_to_pollsets(grpc_fd** fds, size_t fd_count, + grpc_pollset** pollsets, + size_t pollset_count, + const char* err_desc, + grpc_fd** out_fds, + size_t* out_fd_count) { GPR_TIMER_SCOPE("add_fds_to_pollsets", 0); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; for (size_t i = 0; i < fd_count; i++) { gpr_mu_lock(&fds[i]->orphan_mu); if ((gpr_atm_no_barrier_load(&fds[i]->refst) & 1) == 0) { @@ -1451,7 +1454,7 @@ static void pollset_set_add_pollset(grpc_pollset_set* pss, grpc_pollset* ps) { if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, "PSS:%p: add pollset %p", pss, ps); } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; static const char* err_desc = "pollset_set_add_pollset"; pollable* pollable_obj = nullptr; gpr_mu_lock(&ps->mu); @@ -1488,7 +1491,7 @@ static void pollset_set_add_pollset_set(grpc_pollset_set* a, if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_INFO, "PSS: merge (%p, %p)", a, b); } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; static const char* err_desc = "pollset_set_add_fd"; for (;;) { if (a == b) { @@ -1573,7 +1576,7 @@ static bool is_any_background_poller_thread(void) { return false; } static void shutdown_background_closure(void) {} static bool add_closure_to_background_poller(grpc_closure* /*closure*/, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { return false; } diff --git a/src/core/lib/iomgr/ev_poll_posix.cc b/src/core/lib/iomgr/ev_poll_posix.cc index e58d1d39c48..fa4242f3275 100644 --- a/src/core/lib/iomgr/ev_poll_posix.cc +++ b/src/core/lib/iomgr/ev_poll_posix.cc @@ -89,7 +89,7 @@ struct grpc_fd { int closed; int released; gpr_atm pollhup; - grpc_error* shutdown_error; + grpc_error_handle shutdown_error; /* The watcher list. @@ -230,9 +230,9 @@ static int poll_deadline_to_millis_timeout(grpc_millis deadline); #define GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP 2 /* As per pollset_kick, with an extended set of flags (defined above) -- mostly for fd_posix's use. */ -static grpc_error* pollset_kick_ext(grpc_pollset* p, - grpc_pollset_worker* specific_worker, - uint32_t flags) GRPC_MUST_USE_RESULT; +static grpc_error_handle pollset_kick_ext(grpc_pollset* p, + grpc_pollset_worker* specific_worker, + uint32_t flags) GRPC_MUST_USE_RESULT; /* Return 1 if the pollset has active threads in pollset_work (pollset must * be locked) */ @@ -394,11 +394,12 @@ static bool fd_is_orphaned(grpc_fd* fd) { return (gpr_atm_acq_load(&fd->refst) & 1) == 0; } -static grpc_error* pollset_kick_locked(grpc_fd_watcher* watcher) { +static grpc_error_handle pollset_kick_locked(grpc_fd_watcher* watcher) { gpr_mu_lock(&watcher->pollset->mu); GPR_ASSERT(watcher->worker); - grpc_error* err = pollset_kick_ext(watcher->pollset, watcher->worker, - GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP); + grpc_error_handle err = + pollset_kick_ext(watcher->pollset, watcher->worker, + GRPC_POLLSET_REEVALUATE_POLLING_ON_WAKEUP); gpr_mu_unlock(&watcher->pollset->mu); return err; } @@ -484,7 +485,7 @@ static void fd_ref(grpc_fd* fd) { ref_by(fd, 2); } static void fd_unref(grpc_fd* fd) { unref_by(fd, 2); } #endif -static grpc_error* fd_shutdown_error(grpc_fd* fd) { +static grpc_error_handle fd_shutdown_error(grpc_fd* fd) { if (!fd->shutdown) { return GRPC_ERROR_NONE; } else { @@ -537,7 +538,7 @@ static int set_ready_locked(grpc_fd* fd, grpc_closure** st) { } } -static void fd_shutdown(grpc_fd* fd, grpc_error* why) { +static void fd_shutdown(grpc_fd* fd, grpc_error_handle why) { gpr_mu_lock(&fd->mu); /* only shutdown once */ if (!fd->shutdown) { @@ -747,7 +748,8 @@ static void push_front_worker(grpc_pollset* p, grpc_pollset_worker* worker) { worker->prev->next = worker->next->prev = worker; } -static void kick_append_error(grpc_error** composite, grpc_error* error) { +static void kick_append_error(grpc_error_handle* composite, + grpc_error_handle error) { if (error == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Kick Failure"); @@ -755,11 +757,11 @@ static void kick_append_error(grpc_error** composite, grpc_error* error) { *composite = grpc_error_add_child(*composite, error); } -static grpc_error* pollset_kick_ext(grpc_pollset* p, - grpc_pollset_worker* specific_worker, - uint32_t flags) { +static grpc_error_handle pollset_kick_ext(grpc_pollset* p, + grpc_pollset_worker* specific_worker, + uint32_t flags) { GPR_TIMER_SCOPE("pollset_kick_ext", 0); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; GRPC_STATS_INC_POLLSET_KICK(); /* pollset->mu already held */ @@ -826,14 +828,14 @@ static grpc_error* pollset_kick_ext(grpc_pollset* p, return error; } -static grpc_error* pollset_kick(grpc_pollset* p, - grpc_pollset_worker* specific_worker) { +static grpc_error_handle pollset_kick(grpc_pollset* p, + grpc_pollset_worker* specific_worker) { return pollset_kick_ext(p, specific_worker, 0); } /* global state management */ -static grpc_error* pollset_global_init(void) { +static grpc_error_handle pollset_global_init(void) { gpr_tls_init(&g_current_thread_poller); gpr_tls_init(&g_current_thread_worker); return GRPC_ERROR_NONE; @@ -904,7 +906,8 @@ static void finish_shutdown(grpc_pollset* pollset) { GRPC_ERROR_NONE); } -static void work_combine_error(grpc_error** composite, grpc_error* error) { +static void work_combine_error(grpc_error_handle* composite, + grpc_error_handle error) { if (error == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("pollset_work"); @@ -912,13 +915,13 @@ static void work_combine_error(grpc_error** composite, grpc_error* error) { *composite = grpc_error_add_child(*composite, error); } -static grpc_error* pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker_hdl, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** worker_hdl, + grpc_millis deadline) { GPR_TIMER_SCOPE("pollset_work", 0); grpc_pollset_worker worker; if (worker_hdl) *worker_hdl = &worker; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; /* Avoid malloc for small number of elements. */ enum { inline_elements = 96 }; @@ -1336,7 +1339,7 @@ static bool is_any_background_poller_thread(void) { return false; } static void shutdown_background_closure(void) {} static bool add_closure_to_background_poller(grpc_closure* /*closure*/, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { return false; } diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc index 07aeb7f2478..dfb250f4a6c 100644 --- a/src/core/lib/iomgr/ev_posix.cc +++ b/src/core/lib/iomgr/ev_posix.cc @@ -270,7 +270,7 @@ void grpc_fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, g_event_engine->fd_orphan(fd, on_done, release_fd, reason); } -void grpc_fd_shutdown(grpc_fd* fd, grpc_error* why) { +void grpc_fd_shutdown(grpc_fd* fd, grpc_error_handle why) { GRPC_POLLING_API_TRACE("fd_shutdown(%d)", grpc_fd_wrapped_fd(fd)); GRPC_FD_TRACE("fd_shutdown(%d)", grpc_fd_wrapped_fd(fd)); g_event_engine->fd_shutdown(fd, why); @@ -315,19 +315,20 @@ static void pollset_destroy(grpc_pollset* pollset) { g_event_engine->pollset_destroy(pollset); } -static grpc_error* pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** worker, + grpc_millis deadline) { GRPC_POLLING_API_TRACE("pollset_work(%p, %" PRId64 ") begin", pollset, deadline); - grpc_error* err = g_event_engine->pollset_work(pollset, worker, deadline); + grpc_error_handle err = + g_event_engine->pollset_work(pollset, worker, deadline); GRPC_POLLING_API_TRACE("pollset_work(%p, %" PRId64 ") end", pollset, deadline); return err; } -static grpc_error* pollset_kick(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker) { +static grpc_error_handle pollset_kick(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker) { GRPC_POLLING_API_TRACE("pollset_kick(%p, %p)", pollset, specific_worker); return g_event_engine->pollset_kick(pollset, specific_worker); } @@ -406,7 +407,7 @@ bool grpc_is_any_background_poller_thread(void) { } bool grpc_add_closure_to_background_poller(grpc_closure* closure, - grpc_error* error) { + grpc_error_handle error) { return g_event_engine->add_closure_to_background_poller(closure, error); } diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index 84edabce71e..479921ae169 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -52,7 +52,7 @@ typedef struct grpc_event_engine_vtable { int (*fd_wrapped_fd)(grpc_fd* fd); void (*fd_orphan)(grpc_fd* fd, grpc_closure* on_done, int* release_fd, const char* reason); - void (*fd_shutdown)(grpc_fd* fd, grpc_error* why); + void (*fd_shutdown)(grpc_fd* fd, grpc_error_handle why); void (*fd_notify_on_read)(grpc_fd* fd, grpc_closure* closure); void (*fd_notify_on_write)(grpc_fd* fd, grpc_closure* closure); void (*fd_notify_on_error)(grpc_fd* fd, grpc_closure* closure); @@ -64,11 +64,11 @@ typedef struct grpc_event_engine_vtable { void (*pollset_init)(grpc_pollset* pollset, gpr_mu** mu); void (*pollset_shutdown)(grpc_pollset* pollset, grpc_closure* closure); void (*pollset_destroy)(grpc_pollset* pollset); - grpc_error* (*pollset_work)(grpc_pollset* pollset, - grpc_pollset_worker** worker, - grpc_millis deadline); - grpc_error* (*pollset_kick)(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker); + grpc_error_handle (*pollset_work)(grpc_pollset* pollset, + grpc_pollset_worker** worker, + grpc_millis deadline); + grpc_error_handle (*pollset_kick)(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker); void (*pollset_add_fd)(grpc_pollset* pollset, struct grpc_fd* fd); grpc_pollset_set* (*pollset_set_create)(void); @@ -88,7 +88,7 @@ typedef struct grpc_event_engine_vtable { void (*shutdown_background_closure)(void); void (*shutdown_engine)(void); bool (*add_closure_to_background_poller)(grpc_closure* closure, - grpc_error* error); + grpc_error_handle error); } grpc_event_engine_vtable; /* register a new event engine factory */ @@ -139,7 +139,7 @@ void grpc_fd_orphan(grpc_fd* fd, grpc_closure* on_done, int* release_fd, bool grpc_fd_is_shutdown(grpc_fd* fd); /* Cause any current and future callbacks to fail. */ -void grpc_fd_shutdown(grpc_fd* fd, grpc_error* why); +void grpc_fd_shutdown(grpc_fd* fd, grpc_error_handle why); /* Register read interest, causing read_cb to be called once when fd becomes readable, on deadline specified by deadline, or on shutdown triggered by @@ -195,7 +195,7 @@ bool grpc_is_any_background_poller_thread(); * that the closure may or may not run yet when this function returns, and the * closure should not be blocking or long-running. */ bool grpc_add_closure_to_background_poller(grpc_closure* closure, - grpc_error* error); + grpc_error_handle error); /* Shut down all the closures registered in the background poller. */ void grpc_shutdown_background_closure(); diff --git a/src/core/lib/iomgr/exec_ctx.cc b/src/core/lib/iomgr/exec_ctx.cc index a2b6e7b38f2..54ab9fdad59 100644 --- a/src/core/lib/iomgr/exec_ctx.cc +++ b/src/core/lib/iomgr/exec_ctx.cc @@ -27,7 +27,7 @@ #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/profiling/timers.h" -static void exec_ctx_run(grpc_closure* closure, grpc_error* error) { +static void exec_ctx_run(grpc_closure* closure, grpc_error_handle error) { #ifndef NDEBUG closure->scheduled = false; if (grpc_trace_closure.enabled()) { @@ -46,7 +46,7 @@ static void exec_ctx_run(grpc_closure* closure, grpc_error* error) { GRPC_ERROR_UNREF(error); } -static void exec_ctx_sched(grpc_closure* closure, grpc_error* error) { +static void exec_ctx_sched(grpc_closure* closure, grpc_error_handle error) { grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(), closure, error); } @@ -152,7 +152,7 @@ bool ExecCtx::Flush() { closure_list_.head = closure_list_.tail = nullptr; while (c != nullptr) { grpc_closure* next = c->next_data.next; - grpc_error* error = c->error_data.error; + grpc_error_handle error = c->error_data.error; did_something = true; exec_ctx_run(c, error); c = next; @@ -174,7 +174,7 @@ grpc_millis ExecCtx::Now() { } void ExecCtx::Run(const DebugLocation& location, grpc_closure* closure, - grpc_error* error) { + grpc_error_handle error) { (void)location; if (closure == nullptr) { GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/iomgr/exec_ctx.h b/src/core/lib/iomgr/exec_ctx.h index c993133ef1c..9cb525759e3 100644 --- a/src/core/lib/iomgr/exec_ctx.h +++ b/src/core/lib/iomgr/exec_ctx.h @@ -228,7 +228,7 @@ class ExecCtx { } static void Run(const DebugLocation& location, grpc_closure* closure, - grpc_error* error); + grpc_error_handle error); static void RunList(const DebugLocation& location, grpc_closure_list* list); diff --git a/src/core/lib/iomgr/executor.cc b/src/core/lib/iomgr/executor.cc index b1d21bc91e6..3d8d757beb2 100644 --- a/src/core/lib/iomgr/executor.cc +++ b/src/core/lib/iomgr/executor.cc @@ -57,27 +57,27 @@ GPR_TLS_DECL(g_this_thread_state); Executor* executors[static_cast(ExecutorType::NUM_EXECUTORS)]; -void default_enqueue_short(grpc_closure* closure, grpc_error* error) { +void default_enqueue_short(grpc_closure* closure, grpc_error_handle error) { executors[static_cast(ExecutorType::DEFAULT)]->Enqueue( closure, error, true /* is_short */); } -void default_enqueue_long(grpc_closure* closure, grpc_error* error) { +void default_enqueue_long(grpc_closure* closure, grpc_error_handle error) { executors[static_cast(ExecutorType::DEFAULT)]->Enqueue( closure, error, false /* is_short */); } -void resolver_enqueue_short(grpc_closure* closure, grpc_error* error) { +void resolver_enqueue_short(grpc_closure* closure, grpc_error_handle error) { executors[static_cast(ExecutorType::RESOLVER)]->Enqueue( closure, error, true /* is_short */); } -void resolver_enqueue_long(grpc_closure* closure, grpc_error* error) { +void resolver_enqueue_long(grpc_closure* closure, grpc_error_handle error) { executors[static_cast(ExecutorType::RESOLVER)]->Enqueue( closure, error, false /* is_short */); } -using EnqueueFunc = void (*)(grpc_closure* closure, grpc_error* error); +using EnqueueFunc = void (*)(grpc_closure* closure, grpc_error_handle error); const EnqueueFunc executor_enqueue_fns_[static_cast(ExecutorType::NUM_EXECUTORS)] @@ -115,7 +115,7 @@ size_t Executor::RunClosures(const char* executor_name, grpc_closure* c = list.head; while (c != nullptr) { grpc_closure* next = c->next_data.next; - grpc_error* error = c->error_data.error; + grpc_error_handle error = c->error_data.error; #ifndef NDEBUG EXECUTOR_TRACE("(%s) run %p [created by %s:%d]", executor_name, c, c->file_created, c->line_created); @@ -251,7 +251,7 @@ void Executor::ThreadMain(void* arg) { gpr_tls_set(&g_this_thread_state, reinterpret_cast(nullptr)); } -void Executor::Enqueue(grpc_closure* closure, grpc_error* error, +void Executor::Enqueue(grpc_closure* closure, grpc_error_handle error, bool is_short) { bool retry_push; if (is_short) { @@ -404,7 +404,7 @@ void Executor::InitAll() { EXECUTOR_TRACE0("Executor::InitAll() done"); } -void Executor::Run(grpc_closure* closure, grpc_error* error, +void Executor::Run(grpc_closure* closure, grpc_error_handle error, ExecutorType executor_type, ExecutorJobType job_type) { executor_enqueue_fns_[static_cast(executor_type)] [static_cast(job_type)](closure, error); diff --git a/src/core/lib/iomgr/executor.h b/src/core/lib/iomgr/executor.h index 7a5d16b9fc5..37e5c1e57e1 100644 --- a/src/core/lib/iomgr/executor.h +++ b/src/core/lib/iomgr/executor.h @@ -70,7 +70,7 @@ class Executor { /** Enqueue the closure onto the executor. is_short is true if the closure is * a short job (i.e expected to not block and complete quickly) */ - void Enqueue(grpc_closure* closure, grpc_error* error, bool is_short); + void Enqueue(grpc_closure* closure, grpc_error_handle error, bool is_short); // TODO(sreek): Currently we have two executors (available globally): The // default executor and the resolver executor. @@ -83,7 +83,7 @@ class Executor { // Initialize ALL the executors static void InitAll(); - static void Run(grpc_closure* closure, grpc_error* error, + static void Run(grpc_closure* closure, grpc_error_handle error, ExecutorType executor_type = ExecutorType::DEFAULT, ExecutorJobType job_type = ExecutorJobType::SHORT); diff --git a/src/core/lib/iomgr/iomgr.cc b/src/core/lib/iomgr/iomgr.cc index 02646db428d..1210bd70ff2 100644 --- a/src/core/lib/iomgr/iomgr.cc +++ b/src/core/lib/iomgr/iomgr.cc @@ -169,7 +169,7 @@ bool grpc_iomgr_is_any_background_poller_thread() { } bool grpc_iomgr_add_closure_to_background_poller(grpc_closure* closure, - grpc_error* error) { + grpc_error_handle error) { return grpc_iomgr_platform_add_closure_to_background_poller(closure, error); } diff --git a/src/core/lib/iomgr/iomgr.h b/src/core/lib/iomgr/iomgr.h index e02f15e551c..9af0557e8a9 100644 --- a/src/core/lib/iomgr/iomgr.h +++ b/src/core/lib/iomgr/iomgr.h @@ -52,7 +52,7 @@ bool grpc_iomgr_is_any_background_poller_thread(); * that the closure may or may not run yet when this function returns, and the * closure should not be blocking or long-running. */ bool grpc_iomgr_add_closure_to_background_poller(grpc_closure* closure, - grpc_error* error); + grpc_error_handle error); /* Exposed only for testing */ size_t grpc_iomgr_count_objects_for_testing(); diff --git a/src/core/lib/iomgr/iomgr_custom.cc b/src/core/lib/iomgr/iomgr_custom.cc index 684044a5bbf..9a9f06a5aa2 100644 --- a/src/core/lib/iomgr/iomgr_custom.cc +++ b/src/core/lib/iomgr/iomgr_custom.cc @@ -45,7 +45,7 @@ static bool iomgr_platform_is_any_background_poller_thread(void) { return false; } static bool iomgr_platform_add_closure_to_background_poller( - grpc_closure* /*closure*/, grpc_error* /*error*/) { + grpc_closure* /*closure*/, grpc_error_handle /*error*/) { return false; } diff --git a/src/core/lib/iomgr/iomgr_internal.cc b/src/core/lib/iomgr/iomgr_internal.cc index 896d9fce67c..e5ce8ab3f89 100644 --- a/src/core/lib/iomgr/iomgr_internal.cc +++ b/src/core/lib/iomgr/iomgr_internal.cc @@ -50,8 +50,8 @@ bool grpc_iomgr_platform_is_any_background_poller_thread() { return iomgr_platform_vtable->is_any_background_poller_thread(); } -bool grpc_iomgr_platform_add_closure_to_background_poller(grpc_closure* closure, - grpc_error* error) { +bool grpc_iomgr_platform_add_closure_to_background_poller( + grpc_closure* closure, grpc_error_handle error) { return iomgr_platform_vtable->add_closure_to_background_poller(closure, error); } diff --git a/src/core/lib/iomgr/iomgr_internal.h b/src/core/lib/iomgr/iomgr_internal.h index 17607f98f11..01cd2483ea2 100644 --- a/src/core/lib/iomgr/iomgr_internal.h +++ b/src/core/lib/iomgr/iomgr_internal.h @@ -38,7 +38,7 @@ typedef struct grpc_iomgr_platform_vtable { void (*shutdown_background_closure)(void); bool (*is_any_background_poller_thread)(void); bool (*add_closure_to_background_poller)(grpc_closure* closure, - grpc_error* error); + grpc_error_handle error); } grpc_iomgr_platform_vtable; void grpc_iomgr_register_object(grpc_iomgr_object* obj, const char* name); @@ -65,8 +65,8 @@ bool grpc_iomgr_platform_is_any_background_poller_thread(void); /** Return true if the closure is registered into the background poller. Note * that the closure may or may not run yet when this function returns, and the * closure should not be blocking or long-running. */ -bool grpc_iomgr_platform_add_closure_to_background_poller(grpc_closure* closure, - grpc_error* error); +bool grpc_iomgr_platform_add_closure_to_background_poller( + grpc_closure* closure, grpc_error_handle error); bool grpc_iomgr_abort_on_leaks(void); diff --git a/src/core/lib/iomgr/iomgr_posix.cc b/src/core/lib/iomgr/iomgr_posix.cc index 5e778814905..0407e305cd8 100644 --- a/src/core/lib/iomgr/iomgr_posix.cc +++ b/src/core/lib/iomgr/iomgr_posix.cc @@ -59,7 +59,7 @@ static bool iomgr_platform_is_any_background_poller_thread(void) { } static bool iomgr_platform_add_closure_to_background_poller( - grpc_closure* closure, grpc_error* error) { + grpc_closure* closure, grpc_error_handle error) { return grpc_add_closure_to_background_poller(closure, error); } diff --git a/src/core/lib/iomgr/iomgr_posix_cfstream.cc b/src/core/lib/iomgr/iomgr_posix_cfstream.cc index 9db5e2235f6..78b2985142a 100644 --- a/src/core/lib/iomgr/iomgr_posix_cfstream.cc +++ b/src/core/lib/iomgr/iomgr_posix_cfstream.cc @@ -72,7 +72,7 @@ static bool apple_iomgr_platform_is_any_background_poller_thread(void) { } static bool apple_iomgr_platform_add_closure_to_background_poller( - grpc_closure* closure, grpc_error* error) { + grpc_closure* closure, grpc_error_handle error) { return false; } @@ -105,7 +105,7 @@ static bool iomgr_platform_is_any_background_poller_thread(void) { } static bool iomgr_platform_add_closure_to_background_poller( - grpc_closure* closure, grpc_error* error) { + grpc_closure* closure, grpc_error_handle error) { return grpc_add_closure_to_background_poller(closure, error); } diff --git a/src/core/lib/iomgr/iomgr_windows.cc b/src/core/lib/iomgr/iomgr_windows.cc index 728d4040818..df1207ae7d5 100644 --- a/src/core/lib/iomgr/iomgr_windows.cc +++ b/src/core/lib/iomgr/iomgr_windows.cc @@ -79,7 +79,7 @@ static bool iomgr_platform_is_any_background_poller_thread(void) { } static bool iomgr_platform_add_closure_to_background_poller( - grpc_closure* closure, grpc_error* error) { + grpc_closure* closure, grpc_error_handle error) { return false; } diff --git a/src/core/lib/iomgr/load_file.cc b/src/core/lib/iomgr/load_file.cc index 4bed6275dca..a1878229e82 100644 --- a/src/core/lib/iomgr/load_file.cc +++ b/src/core/lib/iomgr/load_file.cc @@ -30,14 +30,14 @@ #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/block_annotate.h" -grpc_error* grpc_load_file(const char* filename, int add_null_terminator, - grpc_slice* output) { +grpc_error_handle grpc_load_file(const char* filename, int add_null_terminator, + grpc_slice* output) { unsigned char* contents = nullptr; size_t contents_size = 0; grpc_slice result = grpc_empty_slice(); FILE* file; size_t bytes_read = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; GRPC_SCHEDULING_START_BLOCKING_REGION; file = fopen(filename, "rb"); @@ -67,7 +67,7 @@ end: *output = result; if (file != nullptr) fclose(file); if (error != GRPC_ERROR_NONE) { - grpc_error* error_out = + grpc_error_handle error_out = grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to load file", &error, 1), GRPC_ERROR_STR_FILENAME, diff --git a/src/core/lib/iomgr/load_file.h b/src/core/lib/iomgr/load_file.h index d7f8175aaea..a0206e21a35 100644 --- a/src/core/lib/iomgr/load_file.h +++ b/src/core/lib/iomgr/load_file.h @@ -29,7 +29,7 @@ /* Loads the content of a file into a slice. add_null_terminator will add a NULL terminator if non-zero. */ -grpc_error* grpc_load_file(const char* filename, int add_null_terminator, - grpc_slice* output); +grpc_error_handle grpc_load_file(const char* filename, int add_null_terminator, + grpc_slice* output); #endif /* GRPC_CORE_LIB_IOMGR_LOAD_FILE_H */ diff --git a/src/core/lib/iomgr/lockfree_event.cc b/src/core/lib/iomgr/lockfree_event.cc index b3fd8e0b63f..fa21406c5bf 100644 --- a/src/core/lib/iomgr/lockfree_event.cc +++ b/src/core/lib/iomgr/lockfree_event.cc @@ -77,7 +77,7 @@ void LockfreeEvent::DestroyEvent() { do { curr = gpr_atm_no_barrier_load(&state_); if (curr & kShutdownBit) { - GRPC_ERROR_UNREF((grpc_error*)(curr & ~kShutdownBit)); + GRPC_ERROR_UNREF((grpc_error_handle)(curr & ~kShutdownBit)); } else { GPR_ASSERT(curr == kClosureNotReady || curr == kClosureReady); } @@ -139,8 +139,8 @@ void LockfreeEvent::NotifyOn(grpc_closure* closure) { contains a pointer to the shutdown-error). If the fd is shutdown, schedule the closure with the shutdown error */ if ((curr & kShutdownBit) > 0) { - grpc_error* shutdown_err = - reinterpret_cast(curr & ~kShutdownBit); + grpc_error_handle shutdown_err = + reinterpret_cast(curr & ~kShutdownBit); ExecCtx::Run(DEBUG_LOCATION, closure, GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "FD Shutdown", &shutdown_err, 1)); @@ -159,7 +159,7 @@ void LockfreeEvent::NotifyOn(grpc_closure* closure) { GPR_UNREACHABLE_CODE(return ); } -bool LockfreeEvent::SetShutdown(grpc_error* shutdown_error) { +bool LockfreeEvent::SetShutdown(grpc_error_handle shutdown_error) { gpr_atm new_state = reinterpret_cast(shutdown_error) | kShutdownBit; while (true) { @@ -167,7 +167,7 @@ bool LockfreeEvent::SetShutdown(grpc_error* shutdown_error) { if (GRPC_TRACE_FLAG_ENABLED(grpc_polling_trace)) { gpr_log(GPR_DEBUG, "LockfreeEvent::SetShutdown: %p curr=%" PRIxPTR " err=%s", - &state_, curr, grpc_error_string(shutdown_error)); + &state_, curr, grpc_error_std_string(shutdown_error).c_str()); } switch (curr) { case kClosureReady: diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h index f7e855409f6..944f364b422 100644 --- a/src/core/lib/iomgr/lockfree_event.h +++ b/src/core/lib/iomgr/lockfree_event.h @@ -56,7 +56,7 @@ class LockfreeEvent { // Sets the shutdown state. If a closure had been provided by NotifyOn and has // not yet been scheduled, it will be scheduled with \a shutdown_error. - bool SetShutdown(grpc_error* shutdown_error); + bool SetShutdown(grpc_error_handle shutdown_error); // Signals that the event has been received. void SetReady(); diff --git a/src/core/lib/iomgr/poller/eventmanager_libuv.cc b/src/core/lib/iomgr/poller/eventmanager_libuv.cc deleted file mode 100644 index c34430aebdb..00000000000 --- a/src/core/lib/iomgr/poller/eventmanager_libuv.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include - -#include "src/core/lib/iomgr/poller/eventmanager_libuv.h" - -#include - -grpc::experimental::LibuvEventManager::Options::Options() : num_workers_(-1) {} -grpc::experimental::LibuvEventManager::Options::Options(int num_workers) - : num_workers_(num_workers) {} - -grpc::experimental::LibuvEventManager::LibuvEventManager(const Options& options) - : options_(options) { - int num_workers = options_.num_workers(); - // Number of workers can't be 0 if we do not accept thread donation. - // TODO(guantaol): replaces the hard-coded number with a flag. - if (num_workers <= 0) num_workers = 32; - - for (int i = 0; i < num_workers; i++) { - workers_.emplace_back( - options_.thread_name_prefix().c_str(), - [](void* em) { static_cast(em)->RunWorkerLoop(); }, - this); - workers_.back().Start(); - } -} - -grpc::experimental::LibuvEventManager::~LibuvEventManager() { - Shutdown(); - for (auto& th : workers_) { - th.Join(); - } -} - -void grpc::experimental::LibuvEventManager::RunWorkerLoop() { - while (true) { - // TODO(guantaol): extend the worker loop with real work. - if (ShouldStop()) return; - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), - gpr_time_from_micros(10, GPR_TIMESPAN))); - } -} - -bool grpc::experimental::LibuvEventManager::ShouldStop() { - return should_stop_.Load(grpc_core::MemoryOrder::ACQUIRE) != 0; -} - -void grpc::experimental::LibuvEventManager::Shutdown() { - if (should_stop_.Load(grpc_core::MemoryOrder::ACQUIRE)) { - return; // Already shut down. - } - - { - grpc_core::MutexLock lock(&shutdown_mu_); - while (shutdown_refcount_.Load(grpc_core::MemoryOrder::ACQUIRE) > 0) { - shutdown_cv_.Wait(&shutdown_mu_); - } - } - should_stop_.Store(true, grpc_core::MemoryOrder::RELEASE); -} - -void grpc::experimental::LibuvEventManager::ShutdownRef() { - shutdown_refcount_.FetchAdd(1, grpc_core::MemoryOrder::RELAXED); -} - -void grpc::experimental::LibuvEventManager::ShutdownUnref() { - if (shutdown_refcount_.FetchSub(1, grpc_core::MemoryOrder::ACQ_REL) == 1) { - grpc_core::MutexLock lock(&shutdown_mu_); - shutdown_cv_.Signal(); - } -} diff --git a/src/core/lib/iomgr/poller/eventmanager_libuv.h b/src/core/lib/iomgr/poller/eventmanager_libuv.h deleted file mode 100644 index 0bd0ecc4161..00000000000 --- a/src/core/lib/iomgr/poller/eventmanager_libuv.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#ifndef GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_LIBUV_H -#define GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_LIBUV_H - -#include - -#include -#include - -#include "src/core/lib/gprpp/atomic.h" -#include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/gprpp/thd.h" - -namespace grpc { -namespace experimental { - -class LibuvEventManager { - public: - class Options { - public: - Options(); - explicit Options(int num_workers); - - int num_workers() const { return num_workers_; } - void set_num_workers(int num) { num_workers_ = num; } - - const std::string& thread_name_prefix() const { - return thread_name_prefix_; - } - void set_thread_name_prefix(const std::string& name) { - thread_name_prefix_ = name; - } - - private: - // Number of worker threads to create at startup. If less than 0, uses the - // default value of 32. - int num_workers_; - // Name prefix used for worker. - std::string thread_name_prefix_; - }; - - explicit LibuvEventManager(const Options& options); - virtual ~LibuvEventManager(); - - void Shutdown(); - void ShutdownRef(); - void ShutdownUnref(); - - private: - // Function run by the worker threads. - void RunWorkerLoop(); - - // Whether the EventManager has been shut down. - bool ShouldStop(); - - const Options options_; - // Whether the EventManager workers should be stopped. - grpc_core::Atomic should_stop_{false}; - // A refcount preventing the EventManager from shutdown. - grpc_core::Atomic shutdown_refcount_{0}; - // Worker threads of the EventManager. - std::vector workers_; - // Mutex and condition variable used for shutdown. - grpc_core::Mutex shutdown_mu_; - grpc_core::CondVar shutdown_cv_; -}; - -} // namespace experimental -} // namespace grpc - -#endif /* GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_LIBUV_H */ diff --git a/src/core/lib/iomgr/pollset.cc b/src/core/lib/iomgr/pollset.cc index ebfef1dbc76..ba2a58d85ae 100644 --- a/src/core/lib/iomgr/pollset.cc +++ b/src/core/lib/iomgr/pollset.cc @@ -42,14 +42,14 @@ void grpc_pollset_destroy(grpc_pollset* pollset) { grpc_pollset_impl->destroy(pollset); } -grpc_error* grpc_pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker, - grpc_millis deadline) { +grpc_error_handle grpc_pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** worker, + grpc_millis deadline) { return grpc_pollset_impl->work(pollset, worker, deadline); } -grpc_error* grpc_pollset_kick(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker) { +grpc_error_handle grpc_pollset_kick(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker) { return grpc_pollset_impl->kick(pollset, specific_worker); } diff --git a/src/core/lib/iomgr/pollset.h b/src/core/lib/iomgr/pollset.h index 28472b360d6..7c87a827cdf 100644 --- a/src/core/lib/iomgr/pollset.h +++ b/src/core/lib/iomgr/pollset.h @@ -44,10 +44,10 @@ typedef struct grpc_pollset_vtable { void (*init)(grpc_pollset* pollset, gpr_mu** mu); void (*shutdown)(grpc_pollset* pollset, grpc_closure* closure); void (*destroy)(grpc_pollset* pollset); - grpc_error* (*work)(grpc_pollset* pollset, grpc_pollset_worker** worker, - grpc_millis deadline); - grpc_error* (*kick)(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker); + grpc_error_handle (*work)(grpc_pollset* pollset, grpc_pollset_worker** worker, + grpc_millis deadline); + grpc_error_handle (*kick)(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker); size_t (*pollset_size)(void); } grpc_pollset_vtable; @@ -86,14 +86,14 @@ void grpc_pollset_destroy(grpc_pollset* pollset); May call grpc_closure_list_run on grpc_closure_list, without holding the pollset lock */ -grpc_error* grpc_pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker, - grpc_millis deadline) GRPC_MUST_USE_RESULT; +grpc_error_handle grpc_pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** worker, + grpc_millis deadline) GRPC_MUST_USE_RESULT; /* Break one polling thread out of polling work for this pollset. If specific_worker is non-NULL, then kick that worker. */ -grpc_error* grpc_pollset_kick(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker) +grpc_error_handle grpc_pollset_kick(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker) GRPC_MUST_USE_RESULT; #endif /* GRPC_CORE_LIB_IOMGR_POLLSET_H */ diff --git a/src/core/lib/iomgr/pollset_custom.cc b/src/core/lib/iomgr/pollset_custom.cc index 98c8e64e2f0..62c4b397dd0 100644 --- a/src/core/lib/iomgr/pollset_custom.cc +++ b/src/core/lib/iomgr/pollset_custom.cc @@ -63,9 +63,9 @@ static void pollset_destroy(grpc_pollset* pollset) { gpr_mu_destroy(&pollset->mu); } -static grpc_error* pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** /*worker_hdl*/, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** /*worker_hdl*/, + grpc_millis deadline) { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); gpr_mu_unlock(&pollset->mu); grpc_millis now = grpc_core::ExecCtx::Get()->Now(); @@ -87,8 +87,8 @@ static grpc_error* pollset_work(grpc_pollset* pollset, return GRPC_ERROR_NONE; } -static grpc_error* pollset_kick(grpc_pollset* /*pollset*/, - grpc_pollset_worker* /*specific_worker*/) { +static grpc_error_handle pollset_kick( + grpc_pollset* /*pollset*/, grpc_pollset_worker* /*specific_worker*/) { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); poller_vtable->kick(); return GRPC_ERROR_NONE; diff --git a/src/core/lib/iomgr/pollset_windows.cc b/src/core/lib/iomgr/pollset_windows.cc index 184c330cf7c..f8758a3f73e 100644 --- a/src/core/lib/iomgr/pollset_windows.cc +++ b/src/core/lib/iomgr/pollset_windows.cc @@ -106,9 +106,9 @@ static void pollset_shutdown(grpc_pollset* pollset, grpc_closure* closure) { static void pollset_destroy(grpc_pollset* pollset) {} -static grpc_error* pollset_work(grpc_pollset* pollset, - grpc_pollset_worker** worker_hdl, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* pollset, + grpc_pollset_worker** worker_hdl, + grpc_millis deadline) { grpc_pollset_worker worker; if (worker_hdl) *worker_hdl = &worker; @@ -183,8 +183,8 @@ done: return GRPC_ERROR_NONE; } -static grpc_error* pollset_kick(grpc_pollset* p, - grpc_pollset_worker* specific_worker) { +static grpc_error_handle pollset_kick(grpc_pollset* p, + grpc_pollset_worker* specific_worker) { bool should_kick_global = false; if (specific_worker != NULL) { if (specific_worker == GRPC_POLLSET_KICK_BROADCAST) { diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h index 2a8d67b261c..8d3cd98b046 100644 --- a/src/core/lib/iomgr/port.h +++ b/src/core/lib/iomgr/port.h @@ -192,7 +192,7 @@ defined(GRPC_CUSTOM_SOCKET) + defined(GRPC_CFSTREAM) != \ 1 #error \ - "Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GRPC_CUSTOM_SOCKET" + "Must define exactly one of GRPC_POSIX_SOCKET, GRPC_WINSOCK_SOCKET, GRPC_CUSTOM_SOCKET, GRPC_CFSTREAM" #endif #ifdef GRPC_POSIX_SOCKET diff --git a/src/core/lib/iomgr/python_util.h b/src/core/lib/iomgr/python_util.h index 05d72a58ad0..10c335b1741 100644 --- a/src/core/lib/iomgr/python_util.h +++ b/src/core/lib/iomgr/python_util.h @@ -29,7 +29,7 @@ // They are easier to define here (rather than in Cython) // because Cython doesn't handle #defines well. -inline grpc_error* grpc_socket_error(char* error) { +inline grpc_error_handle grpc_socket_error(char* error) { return grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); diff --git a/src/core/lib/iomgr/resolve_address.cc b/src/core/lib/iomgr/resolve_address.cc index 7479836df74..83c6aacff7f 100644 --- a/src/core/lib/iomgr/resolve_address.cc +++ b/src/core/lib/iomgr/resolve_address.cc @@ -42,9 +42,9 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses* addresses) { gpr_free(addresses); } -grpc_error* grpc_blocking_resolve_address(const char* name, - const char* default_port, - grpc_resolved_addresses** addresses) { +grpc_error_handle grpc_blocking_resolve_address( + const char* name, const char* default_port, + grpc_resolved_addresses** addresses) { return grpc_resolve_address_impl->blocking_resolve_address(name, default_port, addresses); } diff --git a/src/core/lib/iomgr/resolve_address.h b/src/core/lib/iomgr/resolve_address.h index 025a141b4a7..112d0ac5e27 100644 --- a/src/core/lib/iomgr/resolve_address.h +++ b/src/core/lib/iomgr/resolve_address.h @@ -54,9 +54,9 @@ typedef struct grpc_address_resolver_vtable { grpc_pollset_set* interested_parties, grpc_closure* on_done, grpc_resolved_addresses** addresses); - grpc_error* (*blocking_resolve_address)(const char* name, - const char* default_port, - grpc_resolved_addresses** addresses); + grpc_error_handle (*blocking_resolve_address)( + const char* name, const char* default_port, + grpc_resolved_addresses** addresses); } grpc_address_resolver_vtable; void grpc_set_resolver_impl(grpc_address_resolver_vtable* vtable); @@ -74,8 +74,8 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses* addresses); /* Resolve addr in a blocking fashion. On success, result must be freed with grpc_resolved_addresses_destroy. */ -grpc_error* grpc_blocking_resolve_address(const char* name, - const char* default_port, - grpc_resolved_addresses** addresses); +grpc_error_handle grpc_blocking_resolve_address( + const char* name, const char* default_port, + grpc_resolved_addresses** addresses); #endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */ diff --git a/src/core/lib/iomgr/resolve_address_custom.cc b/src/core/lib/iomgr/resolve_address_custom.cc index 5ddd4523ce7..f89eab0591c 100644 --- a/src/core/lib/iomgr/resolve_address_custom.cc +++ b/src/core/lib/iomgr/resolve_address_custom.cc @@ -29,12 +29,12 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/iomgr/iomgr_custom.h" #include "src/core/lib/iomgr/port.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" struct grpc_custom_resolver { grpc_closure* on_done = nullptr; @@ -53,7 +53,7 @@ static int retry_named_port_failure(grpc_custom_resolver* r, if (r->port == svc[i][0]) { r->port = svc[i][1]; if (res) { - grpc_error* error = resolve_address_vtable->resolve( + grpc_error_handle error = resolve_address_vtable->resolve( r->host.c_str(), r->port.c_str(), res); if (error != GRPC_ERROR_NONE) { GRPC_ERROR_UNREF(error); @@ -71,7 +71,7 @@ static int retry_named_port_failure(grpc_custom_resolver* r, void grpc_custom_resolve_callback(grpc_custom_resolver* r, grpc_resolved_addresses* result, - grpc_error* error) { + grpc_error_handle error) { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; @@ -86,9 +86,10 @@ void grpc_custom_resolve_callback(grpc_custom_resolver* r, delete r; } -static grpc_error* try_split_host_port(const char* name, - const char* default_port, - std::string* host, std::string* port) { +static grpc_error_handle try_split_host_port(const char* name, + const char* default_port, + std::string* host, + std::string* port) { /* parse name, splitting it into host and port parts */ grpc_core::SplitHostPort(name, host, port); if (host->empty()) { @@ -106,13 +107,13 @@ static grpc_error* try_split_host_port(const char* name, return GRPC_ERROR_NONE; } -static grpc_error* blocking_resolve_address_impl( +static grpc_error_handle blocking_resolve_address_impl( const char* name, const char* default_port, grpc_resolved_addresses** addresses) { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); grpc_custom_resolver resolver; - grpc_error* err = + grpc_error_handle err = try_split_host_port(name, default_port, &resolver.host, &resolver.port); if (err != GRPC_ERROR_NONE) { return err; @@ -144,7 +145,7 @@ static void resolve_address_impl(const char* name, const char* default_port, GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); std::string host; std::string port; - grpc_error* err = try_split_host_port(name, default_port, &host, &port); + grpc_error_handle err = try_split_host_port(name, default_port, &host, &port); if (err != GRPC_ERROR_NONE) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, err); return; diff --git a/src/core/lib/iomgr/resolve_address_custom.h b/src/core/lib/iomgr/resolve_address_custom.h index f5f68ca32dd..5f674dd038e 100644 --- a/src/core/lib/iomgr/resolve_address_custom.h +++ b/src/core/lib/iomgr/resolve_address_custom.h @@ -29,15 +29,15 @@ typedef struct grpc_custom_resolver grpc_custom_resolver; typedef struct grpc_custom_resolver_vtable { - grpc_error* (*resolve)(const char* host, const char* port, - grpc_resolved_addresses** res); + grpc_error_handle (*resolve)(const char* host, const char* port, + grpc_resolved_addresses** res); void (*resolve_async)(grpc_custom_resolver* resolver, const char* host, const char* port); } grpc_custom_resolver_vtable; void grpc_custom_resolve_callback(grpc_custom_resolver* resolver, grpc_resolved_addresses* result, - grpc_error* error); + grpc_error_handle error); /* Internal APIs */ void grpc_custom_resolver_init(grpc_custom_resolver_vtable* impl); diff --git a/src/core/lib/iomgr/resolve_address_posix.cc b/src/core/lib/iomgr/resolve_address_posix.cc index 122dbe600f2..d0d1e0cd05d 100644 --- a/src/core/lib/iomgr/resolve_address_posix.cc +++ b/src/core/lib/iomgr/resolve_address_posix.cc @@ -42,7 +42,7 @@ #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" -static grpc_error* posix_blocking_resolve_address( +static grpc_error_handle posix_blocking_resolve_address( const char* name, const char* default_port, grpc_resolved_addresses** addresses) { grpc_core::ExecCtx exec_ctx; @@ -50,7 +50,7 @@ static grpc_error* posix_blocking_resolve_address( struct addrinfo *result = nullptr, *resp; int s; size_t i; - grpc_error* err; + grpc_error_handle err; std::string host; std::string port; @@ -145,7 +145,7 @@ struct request { }; /* Callback to be passed to grpc Executor to asynch-ify * grpc_blocking_resolve_address */ -static void do_request_thread(void* rp, grpc_error* /*error*/) { +static void do_request_thread(void* rp, grpc_error_handle /*error*/) { request* r = static_cast(rp); grpc_core::ExecCtx::Run( DEBUG_LOCATION, r->on_done, diff --git a/src/core/lib/iomgr/resolve_address_windows.cc b/src/core/lib/iomgr/resolve_address_windows.cc index 5d2d365d73a..926237bccf7 100644 --- a/src/core/lib/iomgr/resolve_address_windows.cc +++ b/src/core/lib/iomgr/resolve_address_windows.cc @@ -39,13 +39,13 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/block_annotate.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" struct request { char* name; @@ -54,7 +54,7 @@ struct request { grpc_closure* on_done; grpc_resolved_addresses** addresses; }; -static grpc_error* windows_blocking_resolve_address( +static grpc_error_handle windows_blocking_resolve_address( const char* name, const char* default_port, grpc_resolved_addresses** addresses) { grpc_core::ExecCtx exec_ctx; @@ -62,7 +62,7 @@ static grpc_error* windows_blocking_resolve_address( struct addrinfo *result = NULL, *resp; int s; size_t i; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; /* parse name, splitting it into host and port parts */ std::string host; @@ -121,7 +121,7 @@ done: /* Callback to be passed to grpc_executor to asynch-ify * grpc_blocking_resolve_address */ -static void do_request_thread(void* rp, grpc_error* error) { +static void do_request_thread(void* rp, grpc_error_handle error) { request* r = (request*)rp; if (error == GRPC_ERROR_NONE) { error = diff --git a/src/core/lib/iomgr/resource_quota.cc b/src/core/lib/iomgr/resource_quota.cc index dcbd5089bac..a4f4107d42f 100644 --- a/src/core/lib/iomgr/resource_quota.cc +++ b/src/core/lib/iomgr/resource_quota.cc @@ -276,7 +276,7 @@ static bool rq_reclaim_from_per_user_free_pool( grpc_resource_quota* resource_quota); static bool rq_reclaim(grpc_resource_quota* resource_quota, bool destructive); -static void rq_step(void* rq, grpc_error* /*error*/) { +static void rq_step(void* rq, grpc_error_handle /*error*/) { grpc_resource_quota* resource_quota = static_cast(rq); resource_quota->step_scheduled = false; do { @@ -484,7 +484,7 @@ static grpc_slice ru_slice_create(grpc_resource_user* resource_user, * the combiner */ -static void ru_allocate(void* ru, grpc_error* /*error*/) { +static void ru_allocate(void* ru, grpc_error_handle /*error*/) { grpc_resource_user* resource_user = static_cast(ru); if (rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION)) { @@ -493,7 +493,7 @@ static void ru_allocate(void* ru, grpc_error* /*error*/) { rulist_add_tail(resource_user, GRPC_RULIST_AWAITING_ALLOCATION); } -static void ru_add_to_free_pool(void* ru, grpc_error* /*error*/) { +static void ru_add_to_free_pool(void* ru, grpc_error_handle /*error*/) { grpc_resource_user* resource_user = static_cast(ru); if (!rulist_empty(resource_user->resource_quota, GRPC_RULIST_AWAITING_ALLOCATION) && @@ -518,7 +518,7 @@ static bool ru_post_reclaimer(grpc_resource_user* resource_user, return true; } -static void ru_post_benign_reclaimer(void* ru, grpc_error* /*error*/) { +static void ru_post_benign_reclaimer(void* ru, grpc_error_handle /*error*/) { grpc_resource_user* resource_user = static_cast(ru); if (!ru_post_reclaimer(resource_user, false)) return; if (!rulist_empty(resource_user->resource_quota, @@ -532,7 +532,8 @@ static void ru_post_benign_reclaimer(void* ru, grpc_error* /*error*/) { rulist_add_tail(resource_user, GRPC_RULIST_RECLAIMER_BENIGN); } -static void ru_post_destructive_reclaimer(void* ru, grpc_error* /*error*/) { +static void ru_post_destructive_reclaimer(void* ru, + grpc_error_handle /*error*/) { grpc_resource_user* resource_user = static_cast(ru); if (!ru_post_reclaimer(resource_user, true)) return; if (!rulist_empty(resource_user->resource_quota, @@ -548,7 +549,7 @@ static void ru_post_destructive_reclaimer(void* ru, grpc_error* /*error*/) { rulist_add_tail(resource_user, GRPC_RULIST_RECLAIMER_DESTRUCTIVE); } -static void ru_shutdown(void* ru, grpc_error* /*error*/) { +static void ru_shutdown(void* ru, grpc_error_handle /*error*/) { if (GRPC_TRACE_FLAG_ENABLED(grpc_resource_quota_trace)) { gpr_log(GPR_INFO, "RU shutdown %p", ru); } @@ -568,7 +569,7 @@ static void ru_shutdown(void* ru, grpc_error* /*error*/) { gpr_mu_unlock(&resource_user->mu); } -static void ru_destroy(void* ru, grpc_error* /*error*/) { +static void ru_destroy(void* ru, grpc_error_handle /*error*/) { grpc_resource_user* resource_user = static_cast(ru); GPR_ASSERT(gpr_atm_no_barrier_load(&resource_user->refs) == 0); // Free all the remaining thread quota @@ -601,7 +602,7 @@ static void ru_alloc_slices( } } -static void ru_allocated_slices(void* arg, grpc_error* error) { +static void ru_allocated_slices(void* arg, grpc_error_handle error) { grpc_resource_user_slice_allocator* slice_allocator = static_cast(arg); if (error == GRPC_ERROR_NONE) ru_alloc_slices(slice_allocator); @@ -619,7 +620,7 @@ struct rq_resize_args { grpc_resource_quota* resource_quota; grpc_closure closure; }; -static void rq_resize(void* args, grpc_error* /*error*/) { +static void rq_resize(void* args, grpc_error_handle /*error*/) { rq_resize_args* a = static_cast(args); int64_t delta = a->size - a->resource_quota->size; a->resource_quota->size += delta; @@ -630,7 +631,7 @@ static void rq_resize(void* args, grpc_error* /*error*/) { gpr_free(a); } -static void rq_reclamation_done(void* rq, grpc_error* /*error*/) { +static void rq_reclamation_done(void* rq, grpc_error_handle /*error*/) { grpc_resource_quota* resource_quota = static_cast(rq); resource_quota->reclaiming = false; rq_step_sched(resource_quota); diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc index 45233bc3268..e8c9ee19df7 100644 --- a/src/core/lib/iomgr/socket_utils_common_posix.cc +++ b/src/core/lib/iomgr/socket_utils_common_posix.cc @@ -47,13 +47,13 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" /* set a socket to use zerocopy */ -grpc_error* grpc_set_socket_zerocopy(int fd) { +grpc_error_handle grpc_set_socket_zerocopy(int fd) { #ifdef GRPC_LINUX_ERRQUEUE const int enable = 1; auto err = setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &enable, sizeof(enable)); @@ -68,7 +68,7 @@ grpc_error* grpc_set_socket_zerocopy(int fd) { } /* set a socket to non blocking mode */ -grpc_error* grpc_set_socket_nonblocking(int fd, int non_blocking) { +grpc_error_handle grpc_set_socket_nonblocking(int fd, int non_blocking) { int oldflags = fcntl(fd, F_GETFL, 0); if (oldflags < 0) { return GRPC_OS_ERROR(errno, "fcntl"); @@ -87,7 +87,7 @@ grpc_error* grpc_set_socket_nonblocking(int fd, int non_blocking) { return GRPC_ERROR_NONE; } -grpc_error* grpc_set_socket_no_sigpipe_if_possible(int fd) { +grpc_error_handle grpc_set_socket_no_sigpipe_if_possible(int fd) { #ifdef GRPC_HAVE_SO_NOSIGPIPE int val = 1; int newval; @@ -108,7 +108,7 @@ grpc_error* grpc_set_socket_no_sigpipe_if_possible(int fd) { return GRPC_ERROR_NONE; } -grpc_error* grpc_set_socket_ip_pktinfo_if_possible(int fd) { +grpc_error_handle grpc_set_socket_ip_pktinfo_if_possible(int fd) { // Use conditionally-important parameter to avoid warning (void)fd; #ifdef GRPC_HAVE_IP_PKTINFO @@ -121,7 +121,7 @@ grpc_error* grpc_set_socket_ip_pktinfo_if_possible(int fd) { return GRPC_ERROR_NONE; } -grpc_error* grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) { +grpc_error_handle grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) { // Use conditionally-important parameter to avoid warning (void)fd; #ifdef GRPC_HAVE_IPV6_RECVPKTINFO @@ -134,14 +134,14 @@ grpc_error* grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd) { return GRPC_ERROR_NONE; } -grpc_error* grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) { +grpc_error_handle grpc_set_socket_sndbuf(int fd, int buffer_size_bytes) { return 0 == setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buffer_size_bytes, sizeof(buffer_size_bytes)) ? GRPC_ERROR_NONE : GRPC_OS_ERROR(errno, "setsockopt(SO_SNDBUF)"); } -grpc_error* grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) { +grpc_error_handle grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) { return 0 == setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buffer_size_bytes, sizeof(buffer_size_bytes)) ? GRPC_ERROR_NONE @@ -149,7 +149,7 @@ grpc_error* grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes) { } /* set a socket to close on exec */ -grpc_error* grpc_set_socket_cloexec(int fd, int close_on_exec) { +grpc_error_handle grpc_set_socket_cloexec(int fd, int close_on_exec) { int oldflags = fcntl(fd, F_GETFD, 0); if (oldflags < 0) { return GRPC_OS_ERROR(errno, "fcntl"); @@ -169,7 +169,7 @@ grpc_error* grpc_set_socket_cloexec(int fd, int close_on_exec) { } /* set a socket to reuse old addresses */ -grpc_error* grpc_set_socket_reuse_addr(int fd, int reuse) { +grpc_error_handle grpc_set_socket_reuse_addr(int fd, int reuse) { int val = (reuse != 0); int newval; socklen_t intlen = sizeof(newval); @@ -187,7 +187,7 @@ grpc_error* grpc_set_socket_reuse_addr(int fd, int reuse) { } /* set a socket to reuse old addresses */ -grpc_error* grpc_set_socket_reuse_port(int fd, int reuse) { +grpc_error_handle grpc_set_socket_reuse_port(int fd, int reuse) { #ifndef SO_REUSEPORT return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "SO_REUSEPORT unavailable on compiling system"); @@ -232,7 +232,7 @@ bool grpc_is_socket_reuse_port_supported() { } /* disable nagle */ -grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) { +grpc_error_handle grpc_set_socket_low_latency(int fd, int low_latency) { int val = (low_latency != 0); int newval; socklen_t intlen = sizeof(newval); @@ -297,7 +297,7 @@ void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client) { } /* Set TCP_USER_TIMEOUT */ -grpc_error* grpc_set_socket_tcp_user_timeout( +grpc_error_handle grpc_set_socket_tcp_user_timeout( int fd, const grpc_channel_args* channel_args, bool is_client) { // Use conditionally-important parameter to avoid warning (void)fd; @@ -388,7 +388,8 @@ grpc_error* grpc_set_socket_tcp_user_timeout( } /* set a socket using a grpc_socket_mutator */ -grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) { +grpc_error_handle grpc_set_socket_with_mutator(int fd, + grpc_socket_mutator* mutator) { GPR_ASSERT(mutator); if (!grpc_socket_mutator_mutate_fd(mutator, fd)) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("grpc_socket_mutator failed."); @@ -396,8 +397,8 @@ grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator) { return GRPC_ERROR_NONE; } -grpc_error* grpc_apply_socket_mutator_in_args(int fd, - const grpc_channel_args* args) { +grpc_error_handle grpc_apply_socket_mutator_in_args( + int fd, const grpc_channel_args* args) { const grpc_arg* socket_mutator_arg = grpc_channel_args_find(args, GRPC_ARG_SOCKET_MUTATOR); if (socket_mutator_arg == nullptr) { @@ -437,16 +438,17 @@ int grpc_ipv6_loopback_available(void) { return g_ipv6_loopback_available; } -static grpc_error* error_for_fd(int fd, const grpc_resolved_address* addr) { +static grpc_error_handle error_for_fd(int fd, + const grpc_resolved_address* addr) { if (fd >= 0) return GRPC_ERROR_NONE; std::string addr_str = grpc_sockaddr_to_string(addr, false); - grpc_error* err = grpc_error_set_str( + grpc_error_handle err = grpc_error_set_str( GRPC_OS_ERROR(errno, "socket"), GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(addr_str.c_str())); return err; } -grpc_error* grpc_create_dualstack_socket( +grpc_error_handle grpc_create_dualstack_socket( const grpc_resolved_address* resolved_addr, int type, int protocol, grpc_dualstack_mode* dsmode, int* newfd) { return grpc_create_dualstack_socket_using_factory( @@ -460,7 +462,7 @@ static int create_socket(grpc_socket_factory* factory, int domain, int type, : socket(domain, type, protocol); } -grpc_error* grpc_create_dualstack_socket_using_factory( +grpc_error_handle grpc_create_dualstack_socket_using_factory( grpc_socket_factory* factory, const grpc_resolved_address* resolved_addr, int type, int protocol, grpc_dualstack_mode* dsmode, int* newfd) { const grpc_sockaddr* addr = diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h index b4dc909d1e0..13c22bc0834 100644 --- a/src/core/lib/iomgr/socket_utils_posix.h +++ b/src/core/lib/iomgr/socket_utils_posix.h @@ -45,31 +45,31 @@ int grpc_accept4(int sockfd, grpc_resolved_address* resolved_addr, int nonblock, int cloexec); /* set a socket to use zerocopy */ -grpc_error* grpc_set_socket_zerocopy(int fd); +grpc_error_handle grpc_set_socket_zerocopy(int fd); /* set a socket to non blocking mode */ -grpc_error* grpc_set_socket_nonblocking(int fd, int non_blocking); +grpc_error_handle grpc_set_socket_nonblocking(int fd, int non_blocking); /* set a socket to close on exec */ -grpc_error* grpc_set_socket_cloexec(int fd, int close_on_exec); +grpc_error_handle grpc_set_socket_cloexec(int fd, int close_on_exec); /* set a socket to reuse old addresses */ -grpc_error* grpc_set_socket_reuse_addr(int fd, int reuse); +grpc_error_handle grpc_set_socket_reuse_addr(int fd, int reuse); /* return true if SO_REUSEPORT is supported */ bool grpc_is_socket_reuse_port_supported(); /* disable nagle */ -grpc_error* grpc_set_socket_low_latency(int fd, int low_latency); +grpc_error_handle grpc_set_socket_low_latency(int fd, int low_latency); /* set SO_REUSEPORT */ -grpc_error* grpc_set_socket_reuse_port(int fd, int reuse); +grpc_error_handle grpc_set_socket_reuse_port(int fd, int reuse); /* Configure the default values for TCP_USER_TIMEOUT */ void config_default_tcp_user_timeout(bool enable, int timeout, bool is_client); /* Set TCP_USER_TIMEOUT */ -grpc_error* grpc_set_socket_tcp_user_timeout( +grpc_error_handle grpc_set_socket_tcp_user_timeout( int fd, const grpc_channel_args* channel_args, bool is_client); /* Returns true if this system can create AF_INET6 sockets bound to ::1. @@ -84,28 +84,29 @@ int grpc_ipv6_loopback_available(void); /* Tries to set SO_NOSIGPIPE if available on this platform. If SO_NO_SIGPIPE is not available, returns 1. */ -grpc_error* grpc_set_socket_no_sigpipe_if_possible(int fd); +grpc_error_handle grpc_set_socket_no_sigpipe_if_possible(int fd); /* Tries to set IP_PKTINFO if available on this platform. If IP_PKTINFO is not available, returns 1. */ -grpc_error* grpc_set_socket_ip_pktinfo_if_possible(int fd); +grpc_error_handle grpc_set_socket_ip_pktinfo_if_possible(int fd); /* Tries to set IPV6_RECVPKTINFO if available on this platform. If IPV6_RECVPKTINFO is not available, returns 1. */ -grpc_error* grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd); +grpc_error_handle grpc_set_socket_ipv6_recvpktinfo_if_possible(int fd); /* Tries to set the socket's send buffer to given size. */ -grpc_error* grpc_set_socket_sndbuf(int fd, int buffer_size_bytes); +grpc_error_handle grpc_set_socket_sndbuf(int fd, int buffer_size_bytes); /* Tries to set the socket's receive buffer to given size. */ -grpc_error* grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes); +grpc_error_handle grpc_set_socket_rcvbuf(int fd, int buffer_size_bytes); /* Tries to set the socket using a grpc_socket_mutator */ -grpc_error* grpc_set_socket_with_mutator(int fd, grpc_socket_mutator* mutator); +grpc_error_handle grpc_set_socket_with_mutator(int fd, + grpc_socket_mutator* mutator); /* Extracts the first socket mutator from args if any and applies on the fd. */ -grpc_error* grpc_apply_socket_mutator_in_args(int fd, - const grpc_channel_args* args); +grpc_error_handle grpc_apply_socket_mutator_in_args( + int fd, const grpc_channel_args* args); /* An enum to keep track of IPv4/IPv6 socket modes. @@ -149,14 +150,13 @@ int grpc_set_socket_dualstack(int fd); IPv4, so that bind() or connect() see the correct family. Also, it's important to distinguish between DUALSTACK and IPV6 when listening on the [::] wildcard address. */ -grpc_error* grpc_create_dualstack_socket(const grpc_resolved_address* addr, - int type, int protocol, - grpc_dualstack_mode* dsmode, - int* newfd); +grpc_error_handle grpc_create_dualstack_socket( + const grpc_resolved_address* addr, int type, int protocol, + grpc_dualstack_mode* dsmode, int* newfd); /* Same as grpc_create_dualstack_socket(), but use the given socket factory (if non-null) to create the socket, rather than calling socket() directly. */ -grpc_error* grpc_create_dualstack_socket_using_factory( +grpc_error_handle grpc_create_dualstack_socket_using_factory( grpc_socket_factory* factory, const grpc_resolved_address* addr, int type, int protocol, grpc_dualstack_mode* dsmode, int* newfd); diff --git a/src/core/lib/iomgr/tcp_client_cfstream.cc b/src/core/lib/iomgr/tcp_client_cfstream.cc index d0be97ae1fb..5c0a95e515b 100644 --- a/src/core/lib/iomgr/tcp_client_cfstream.cc +++ b/src/core/lib/iomgr/tcp_client_cfstream.cc @@ -33,6 +33,7 @@ #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/iomgr/cfstream_handle.h" @@ -40,7 +41,6 @@ #include "src/core/lib/iomgr/endpoint_cfstream.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/error_cfstream.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/timer.h" @@ -78,7 +78,7 @@ static void CFStreamConnectCleanup(CFStreamConnect* connect) { delete connect; } -static void OnAlarm(void* arg, grpc_error* error) { +static void OnAlarm(void* arg, grpc_error_handle error) { CFStreamConnect* connect = static_cast(arg); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnAlarm, error:%p", connect, error); @@ -93,13 +93,13 @@ static void OnAlarm(void* arg, grpc_error* error) { if (done) { CFStreamConnectCleanup(connect); } else { - grpc_error* error = + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("connect() timed out"); grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, error); } } -static void OnOpen(void* arg, grpc_error* error) { +static void OnOpen(void* arg, grpc_error_handle error) { CFStreamConnect* connect = static_cast(arg); if (grpc_tcp_trace.enabled()) { gpr_log(GPR_DEBUG, "CLIENT_CONNECT :%p OnOpen, error:%p", connect, error); diff --git a/src/core/lib/iomgr/tcp_client_custom.cc b/src/core/lib/iomgr/tcp_client_custom.cc index 046380c3ab5..d54a5f03501 100644 --- a/src/core/lib/iomgr/tcp_client_custom.cc +++ b/src/core/lib/iomgr/tcp_client_custom.cc @@ -25,9 +25,9 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/iomgr_custom.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_custom.h" #include "src/core/lib/iomgr/timer.h" @@ -59,14 +59,13 @@ static void custom_tcp_connect_cleanup(grpc_custom_tcp_connect* connect) { static void custom_close_callback(grpc_custom_socket* /*socket*/) {} -static void on_alarm(void* acp, grpc_error* error) { +static void on_alarm(void* acp, grpc_error_handle error) { int done; grpc_custom_socket* socket = static_cast(acp); grpc_custom_tcp_connect* connect = socket->connector; if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(error); gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_alarm: error=%s", - connect->addr_name.c_str(), str); + connect->addr_name.c_str(), grpc_error_std_string(error).c_str()); } if (error == GRPC_ERROR_NONE) { /* error == NONE implies that the timer ran out, and wasn't cancelled. If @@ -81,7 +80,7 @@ static void on_alarm(void* acp, grpc_error* error) { } static void custom_connect_callback_internal(grpc_custom_socket* socket, - grpc_error* error) { + grpc_error_handle error) { grpc_custom_tcp_connect* connect = socket->connector; int done; grpc_closure* closure = connect->closure; @@ -99,7 +98,7 @@ static void custom_connect_callback_internal(grpc_custom_socket* socket, } static void custom_connect_callback(grpc_custom_socket* socket, - grpc_error* error) { + grpc_error_handle error) { grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; if (grpc_core::ExecCtx::Get() == nullptr) { /* If we are being run on a thread which does not have an exec_ctx created diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc index 49e8854819e..741cc6af87b 100644 --- a/src/core/lib/iomgr/tcp_client_posix.cc +++ b/src/core/lib/iomgr/tcp_client_posix.cc @@ -35,12 +35,12 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_mutator.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" @@ -64,9 +64,10 @@ struct async_connect { grpc_channel_args* channel_args; }; -static grpc_error* prepare_socket(const grpc_resolved_address* addr, int fd, - const grpc_channel_args* channel_args) { - grpc_error* err = GRPC_ERROR_NONE; +static grpc_error_handle prepare_socket(const grpc_resolved_address* addr, + int fd, + const grpc_channel_args* channel_args) { + grpc_error_handle err = GRPC_ERROR_NONE; GPR_ASSERT(fd >= 0); @@ -99,13 +100,12 @@ done: return err; } -static void tc_on_alarm(void* acp, grpc_error* error) { +static void tc_on_alarm(void* acp, grpc_error_handle error) { int done; async_connect* ac = static_cast(acp); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(error); gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_alarm: error=%s", - ac->addr_str.c_str(), str); + ac->addr_str.c_str(), grpc_error_std_string(error).c_str()); } gpr_mu_lock(&ac->mu); if (ac->fd != nullptr) { @@ -126,7 +126,7 @@ grpc_endpoint* grpc_tcp_client_create_from_fd( return grpc_tcp_create(fd, channel_args, addr_str); } -static void on_writable(void* acp, grpc_error* error) { +static void on_writable(void* acp, grpc_error_handle error) { async_connect* ac = static_cast(acp); int so_error = 0; socklen_t so_error_size; @@ -139,9 +139,8 @@ static void on_writable(void* acp, grpc_error* error) { GRPC_ERROR_REF(error); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(error); gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_writable: error=%s", - ac->addr_str.c_str(), str); + ac->addr_str.c_str(), grpc_error_std_string(error).c_str()); } gpr_mu_lock(&ac->mu); @@ -242,12 +241,11 @@ finish: grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, error); } -grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args, - const grpc_resolved_address* addr, - grpc_resolved_address* mapped_addr, - int* fd) { +grpc_error_handle grpc_tcp_client_prepare_fd( + const grpc_channel_args* channel_args, const grpc_resolved_address* addr, + grpc_resolved_address* mapped_addr, int* fd) { grpc_dualstack_mode dsmode; - grpc_error* error; + grpc_error_handle error; *fd = -1; /* Use dualstack sockets where available. Set mapped to v6 or v4 mapped to v6. */ @@ -293,7 +291,7 @@ void grpc_tcp_client_create_from_prepared_fd( return; } if (errno != EWOULDBLOCK && errno != EINPROGRESS) { - grpc_error* error = GRPC_OS_ERROR(errno, "connect"); + grpc_error_handle error = GRPC_OS_ERROR(errno, "connect"); error = grpc_error_set_str( error, GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_cpp_string(grpc_sockaddr_to_uri(addr))); @@ -335,7 +333,7 @@ static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep, grpc_millis deadline) { grpc_resolved_address mapped_addr; int fd = -1; - grpc_error* error; + grpc_error_handle error; *ep = nullptr; if ((error = grpc_tcp_client_prepare_fd(channel_args, addr, &mapped_addr, &fd)) != GRPC_ERROR_NONE) { diff --git a/src/core/lib/iomgr/tcp_client_posix.h b/src/core/lib/iomgr/tcp_client_posix.h index 6f61866fc4f..2467f3745c0 100644 --- a/src/core/lib/iomgr/tcp_client_posix.h +++ b/src/core/lib/iomgr/tcp_client_posix.h @@ -45,10 +45,9 @@ grpc_endpoint* grpc_tcp_client_create_from_fd( fd: out parameter. The new FD Returns: error, if any. Out parameters are not set on error */ -grpc_error* grpc_tcp_client_prepare_fd(const grpc_channel_args* channel_args, - const grpc_resolved_address* addr, - grpc_resolved_address* mapped_addr, - int* fd); +grpc_error_handle grpc_tcp_client_prepare_fd( + const grpc_channel_args* channel_args, const grpc_resolved_address* addr, + grpc_resolved_address* mapped_addr, int* fd); /* Connect a configured TCP client fd. diff --git a/src/core/lib/iomgr/tcp_client_windows.cc b/src/core/lib/iomgr/tcp_client_windows.cc index 061e70393d6..ef260cad752 100644 --- a/src/core/lib/iomgr/tcp_client_windows.cc +++ b/src/core/lib/iomgr/tcp_client_windows.cc @@ -31,10 +31,10 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_windows.h" @@ -66,7 +66,7 @@ static void async_connect_unlock_and_cleanup(async_connect* ac, if (socket != NULL) grpc_winsocket_destroy(socket); } -static void on_alarm(void* acp, grpc_error* error) { +static void on_alarm(void* acp, grpc_error_handle error) { async_connect* ac = (async_connect*)acp; gpr_mu_lock(&ac->mu); grpc_winsocket* socket = ac->socket; @@ -77,7 +77,7 @@ static void on_alarm(void* acp, grpc_error* error) { async_connect_unlock_and_cleanup(ac, socket); } -static void on_connect(void* acp, grpc_error* error) { +static void on_connect(void* acp, grpc_error_handle error) { async_connect* ac = (async_connect*)acp; grpc_endpoint** ep = ac->endpoint; GPR_ASSERT(*ep == NULL); @@ -137,7 +137,7 @@ static void tcp_connect(grpc_closure* on_done, grpc_endpoint** endpoint, GUID guid = WSAID_CONNECTEX; DWORD ioctl_num_bytes; grpc_winsocket_callback_info* info; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; async_connect* ac = NULL; *endpoint = NULL; @@ -213,7 +213,7 @@ static void tcp_connect(grpc_closure* on_done, grpc_endpoint** endpoint, failure: GPR_ASSERT(error != GRPC_ERROR_NONE); std::string target_uri = grpc_sockaddr_to_uri(addr); - grpc_error* final_error = + grpc_error_handle final_error = grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed to connect", &error, 1), GRPC_ERROR_STR_TARGET_ADDRESS, diff --git a/src/core/lib/iomgr/tcp_custom.cc b/src/core/lib/iomgr/tcp_custom.cc index 0f45c75c0d5..c526a9579c2 100644 --- a/src/core/lib/iomgr/tcp_custom.cc +++ b/src/core/lib/iomgr/tcp_custom.cc @@ -29,10 +29,10 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/iomgr_custom.h" #include "src/core/lib/iomgr/resource_quota.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_custom.h" #include "src/core/lib/iomgr/tcp_server.h" @@ -122,15 +122,13 @@ static void tcp_unref(custom_tcp_endpoint* tcp) { static void tcp_ref(custom_tcp_endpoint* tcp) { gpr_ref(&tcp->refcount); } #endif -static void call_read_cb(custom_tcp_endpoint* tcp, grpc_error* error) { +static void call_read_cb(custom_tcp_endpoint* tcp, grpc_error_handle error) { grpc_closure* cb = tcp->read_cb; if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp->socket, cb, cb->cb, cb->cb_arg); size_t i; - const char* str = grpc_error_string(error); - gpr_log(GPR_INFO, "read: error=%s", str); - + gpr_log(GPR_INFO, "read: error=%s", grpc_error_std_string(error).c_str()); for (i = 0; i < tcp->read_slices->count; i++) { char* dump = grpc_dump_slice(tcp->read_slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII); @@ -146,7 +144,7 @@ static void call_read_cb(custom_tcp_endpoint* tcp, grpc_error* error) { } static void custom_read_callback(grpc_custom_socket* socket, size_t nread, - grpc_error* error) { + grpc_error_handle error) { grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; grpc_slice_buffer garbage; @@ -171,11 +169,11 @@ static void custom_read_callback(grpc_custom_socket* socket, size_t nread, call_read_cb(tcp, error); } -static void tcp_read_allocation_done(void* tcpp, grpc_error* error) { +static void tcp_read_allocation_done(void* tcpp, grpc_error_handle error) { custom_tcp_endpoint* tcp = static_cast(tcpp); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { gpr_log(GPR_INFO, "TCP:%p read_allocation_done: %s", tcp->socket, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } if (error == GRPC_ERROR_NONE) { /* Before calling read, we allocate a buffer with exactly one slice @@ -191,8 +189,8 @@ static void tcp_read_allocation_done(void* tcpp, grpc_error* error) { call_read_cb(tcp, GRPC_ERROR_REF(error)); } if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(error); - gpr_log(GPR_INFO, "Initiating read on %p: error=%s", tcp->socket, str); + gpr_log(GPR_INFO, "Initiating read on %p: error=%s", tcp->socket, + grpc_error_std_string(error).c_str()); } } @@ -213,7 +211,7 @@ static void endpoint_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, } static void custom_write_callback(grpc_custom_socket* socket, - grpc_error* error) { + grpc_error_handle error) { grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; custom_tcp_endpoint* tcp = @@ -221,8 +219,8 @@ static void custom_write_callback(grpc_custom_socket* socket, grpc_closure* cb = tcp->write_cb; tcp->write_cb = nullptr; if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(error); - gpr_log(GPR_INFO, "write complete on %p: error=%s", tcp->socket, str); + gpr_log(GPR_INFO, "write complete on %p: error=%s", tcp->socket, + grpc_error_std_string(error).c_str()); } TCP_UNREF(tcp, "write"); grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, error); @@ -287,12 +285,12 @@ static void endpoint_delete_from_pollset_set(grpc_endpoint* ep, (void)pollset; } -static void endpoint_shutdown(grpc_endpoint* ep, grpc_error* why) { +static void endpoint_shutdown(grpc_endpoint* ep, grpc_error_handle why) { custom_tcp_endpoint* tcp = reinterpret_cast(ep); if (!tcp->shutting_down) { if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(why); - gpr_log(GPR_INFO, "TCP %p shutdown why=%s", tcp->socket, str); + gpr_log(GPR_INFO, "TCP %p shutdown why=%s", tcp->socket, + grpc_error_std_string(why).c_str()); } tcp->shutting_down = true; // grpc_core::ExecCtx::Run(DEBUG_LOCATION,tcp->read_cb, diff --git a/src/core/lib/iomgr/tcp_custom.h b/src/core/lib/iomgr/tcp_custom.h index d32ed2b4b61..b342efba85f 100644 --- a/src/core/lib/iomgr/tcp_custom.h +++ b/src/core/lib/iomgr/tcp_custom.h @@ -40,18 +40,19 @@ typedef struct grpc_custom_socket { } grpc_custom_socket; typedef void (*grpc_custom_connect_callback)(grpc_custom_socket* socket, - grpc_error* error); + grpc_error_handle error); typedef void (*grpc_custom_write_callback)(grpc_custom_socket* socket, - grpc_error* error); + grpc_error_handle error); typedef void (*grpc_custom_read_callback)(grpc_custom_socket* socket, - size_t nread, grpc_error* error); + size_t nread, + grpc_error_handle error); typedef void (*grpc_custom_accept_callback)(grpc_custom_socket* socket, grpc_custom_socket* client, - grpc_error* error); + grpc_error_handle error); typedef void (*grpc_custom_close_callback)(grpc_custom_socket* socket); typedef struct grpc_socket_vtable { - grpc_error* (*init)(grpc_custom_socket* socket, int domain); + grpc_error_handle (*init)(grpc_custom_socket* socket, int domain); void (*connect)(grpc_custom_socket* socket, const grpc_sockaddr* addr, size_t len, grpc_custom_connect_callback cb); void (*destroy)(grpc_custom_socket* socket); @@ -61,13 +62,13 @@ typedef struct grpc_socket_vtable { grpc_custom_write_callback cb); void (*read)(grpc_custom_socket* socket, char* buffer, size_t length, grpc_custom_read_callback cb); - grpc_error* (*getpeername)(grpc_custom_socket* socket, - const grpc_sockaddr* addr, int* len); - grpc_error* (*getsockname)(grpc_custom_socket* socket, - const grpc_sockaddr* addr, int* len); - grpc_error* (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr, - size_t len, int flags); - grpc_error* (*listen)(grpc_custom_socket* socket); + grpc_error_handle (*getpeername)(grpc_custom_socket* socket, + const grpc_sockaddr* addr, int* len); + grpc_error_handle (*getsockname)(grpc_custom_socket* socket, + const grpc_sockaddr* addr, int* len); + grpc_error_handle (*bind)(grpc_custom_socket* socket, + const grpc_sockaddr* addr, size_t len, int flags); + grpc_error_handle (*listen)(grpc_custom_socket* socket); void (*accept)(grpc_custom_socket* socket, grpc_custom_socket* client, grpc_custom_accept_callback cb); } grpc_socket_vtable; diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc index 6e1a29372cb..1f28b773da9 100644 --- a/src/core/lib/iomgr/tcp_posix.cc +++ b/src/core/lib/iomgr/tcp_posix.cc @@ -45,6 +45,7 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/debug/trace.h" @@ -54,7 +55,6 @@ #include "src/core/lib/iomgr/buffer_list.h" #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/executor.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -435,12 +435,12 @@ static void ZerocopyDisableAndWaitForRemaining(grpc_tcp* tcp); static gpr_atm g_uncovered_notifications_pending; static gpr_atm g_backup_poller; /* backup_poller* */ -static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error* error); -static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error); +static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error_handle error); +static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error_handle error); static void tcp_drop_uncovered_then_handle_write(void* arg /* grpc_tcp */, - grpc_error* error); + grpc_error_handle error); -static void done_poller(void* bp, grpc_error* /*error_ignored*/) { +static void done_poller(void* bp, grpc_error_handle /*error_ignored*/) { backup_poller* p = static_cast(bp); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { gpr_log(GPR_INFO, "BACKUP_POLLER:%p destroy", p); @@ -449,7 +449,7 @@ static void done_poller(void* bp, grpc_error* /*error_ignored*/) { gpr_free(p); } -static void run_poller(void* bp, grpc_error* /*error_ignored*/) { +static void run_poller(void* bp, grpc_error_handle /*error_ignored*/) { backup_poller* p = static_cast(bp); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { gpr_log(GPR_INFO, "BACKUP_POLLER:%p run", p); @@ -560,9 +560,11 @@ static void notify_on_write(grpc_tcp* tcp) { grpc_fd_notify_on_write(tcp->em_fd, &tcp->write_done_closure); } -static void tcp_drop_uncovered_then_handle_write(void* arg, grpc_error* error) { +static void tcp_drop_uncovered_then_handle_write(void* arg, + grpc_error_handle error) { if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - gpr_log(GPR_INFO, "TCP:%p got_write: %s", arg, grpc_error_string(error)); + gpr_log(GPR_INFO, "TCP:%p got_write: %s", arg, + grpc_error_std_string(error).c_str()); } drop_uncovered(static_cast(arg)); tcp_handle_write(arg, error); @@ -604,7 +606,8 @@ static size_t get_target_read_size(grpc_tcp* tcp) { return sz; } -static grpc_error* tcp_annotate_error(grpc_error* src_error, grpc_tcp* tcp) { +static grpc_error_handle tcp_annotate_error(grpc_error_handle src_error, + grpc_tcp* tcp) { return grpc_error_set_str( grpc_error_set_int( grpc_error_set_int(src_error, GRPC_ERROR_INT_FD, tcp->fd), @@ -615,10 +618,10 @@ static grpc_error* tcp_annotate_error(grpc_error* src_error, grpc_tcp* tcp) { grpc_slice_from_copied_string(tcp->peer_string.c_str())); } -static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error* error); -static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error); +static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error_handle error); +static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error_handle error); -static void tcp_shutdown(grpc_endpoint* ep, grpc_error* why) { +static void tcp_shutdown(grpc_endpoint* ep, grpc_error_handle why) { grpc_tcp* tcp = reinterpret_cast(ep); ZerocopyDisableAndWaitForRemaining(tcp); grpc_fd_shutdown(tcp->em_fd, why); @@ -678,16 +681,14 @@ static void tcp_destroy(grpc_endpoint* ep) { TCP_UNREF(tcp, "destroy"); } -static void call_read_cb(grpc_tcp* tcp, grpc_error* error) { +static void call_read_cb(grpc_tcp* tcp, grpc_error_handle error) { grpc_closure* cb = tcp->read_cb; if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp, cb, cb->cb, cb->cb_arg); size_t i; - const char* str = grpc_error_string(error); gpr_log(GPR_INFO, "READ %p (peer=%s) error=%s", tcp, - tcp->peer_string.c_str(), str); - + tcp->peer_string.c_str(), grpc_error_std_string(error).c_str()); if (gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { for (i = 0; i < tcp->incoming_buffer->count; i++) { char* dump = grpc_dump_slice(tcp->incoming_buffer->slices[i], @@ -850,11 +851,11 @@ static void tcp_do_read(grpc_tcp* tcp) { TCP_UNREF(tcp, "read"); } -static void tcp_read_allocation_done(void* tcpp, grpc_error* error) { +static void tcp_read_allocation_done(void* tcpp, grpc_error_handle error) { grpc_tcp* tcp = static_cast(tcpp); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { gpr_log(GPR_INFO, "TCP:%p read_allocation_done: %s", tcp, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { grpc_slice_buffer_reset_and_unref_internal(tcp->incoming_buffer); @@ -887,10 +888,11 @@ static void tcp_continue_read(grpc_tcp* tcp) { tcp_do_read(tcp); } -static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error* error) { +static void tcp_handle_read(void* arg /* grpc_tcp */, grpc_error_handle error) { grpc_tcp* tcp = static_cast(arg); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - gpr_log(GPR_INFO, "TCP:%p got_read: %s", tcp, grpc_error_string(error)); + gpr_log(GPR_INFO, "TCP:%p got_read: %s", tcp, + grpc_error_std_string(error).c_str()); } if (GPR_UNLIKELY(error != GRPC_ERROR_NONE)) { @@ -958,7 +960,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* tcp, struct msghdr* msg, int additional_flags = 0); /** The callback function to be invoked when we get an error on the socket. */ -static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error); +static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error_handle error); static TcpZerocopySendRecord* tcp_get_send_zerocopy_record( grpc_tcp* tcp, grpc_slice_buffer* buf); @@ -1213,10 +1215,12 @@ static bool process_errors(grpc_tcp* tcp) { } } -static void tcp_handle_error(void* arg /* grpc_tcp */, grpc_error* error) { +static void tcp_handle_error(void* arg /* grpc_tcp */, + grpc_error_handle error) { grpc_tcp* tcp = static_cast(arg); if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - gpr_log(GPR_INFO, "TCP:%p got_error: %s", tcp, grpc_error_string(error)); + gpr_log(GPR_INFO, "TCP:%p got_error: %s", tcp, + grpc_error_std_string(error).c_str()); } if (error != GRPC_ERROR_NONE || @@ -1257,7 +1261,7 @@ static bool tcp_write_with_timestamps(grpc_tcp* /*tcp*/, struct msghdr* /*msg*/, } static void tcp_handle_error(void* /*arg*/ /* grpc_tcp */, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { gpr_log(GPR_ERROR, "Error handling is not supported for this platform"); GPR_ASSERT(0); } @@ -1323,7 +1327,7 @@ void TcpZerocopySendRecord::UpdateOffsetForBytesSent(size_t sending_length, // returns true if done, false if pending; if returning true, *error is set static bool do_tcp_flush_zerocopy(grpc_tcp* tcp, TcpZerocopySendRecord* record, - grpc_error** error) { + grpc_error_handle* error) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; msg_iovlen_type iov_size; @@ -1399,7 +1403,7 @@ static void UnrefMaybePutZerocopySendRecord(grpc_tcp* tcp, } static bool tcp_flush_zerocopy(grpc_tcp* tcp, TcpZerocopySendRecord* record, - grpc_error** error) { + grpc_error_handle* error) { bool done = do_tcp_flush_zerocopy(tcp, record, error); if (done) { // Either we encountered an error, or we successfully sent all the bytes. @@ -1409,7 +1413,7 @@ static bool tcp_flush_zerocopy(grpc_tcp* tcp, TcpZerocopySendRecord* record, return done; } -static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { +static bool tcp_flush(grpc_tcp* tcp, grpc_error_handle* error) { struct msghdr msg; struct iovec iov[MAX_WRITE_IOVEC]; msg_iovlen_type iov_size; @@ -1516,7 +1520,8 @@ static bool tcp_flush(grpc_tcp* tcp, grpc_error** error) { } } -static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) { +static void tcp_handle_write(void* arg /* grpc_tcp */, + grpc_error_handle error) { grpc_tcp* tcp = static_cast(arg); grpc_closure* cb; @@ -1549,8 +1554,7 @@ static void tcp_handle_write(void* arg /* grpc_tcp */, grpc_error* error) { tcp->write_cb = nullptr; tcp->current_zerocopy_send = nullptr; if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(error); - gpr_log(GPR_INFO, "write: %s", str); + gpr_log(GPR_INFO, "write: %s", grpc_error_std_string(error).c_str()); } // No need to take a ref on error since tcp_flush provides a ref. grpc_core::Closure::Run(DEBUG_LOCATION, cb, error); @@ -1562,7 +1566,7 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, grpc_closure* cb, void* arg) { GPR_TIMER_SCOPE("tcp_write", 0); grpc_tcp* tcp = reinterpret_cast(ep); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; TcpZerocopySendRecord* zerocopy_send_record = nullptr; if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { @@ -1618,8 +1622,7 @@ static void tcp_write(grpc_endpoint* ep, grpc_slice_buffer* buf, notify_on_write(tcp); } else { if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { - const char* str = grpc_error_string(error); - gpr_log(GPR_INFO, "write: %s", str); + gpr_log(GPR_INFO, "write: %s", grpc_error_std_string(error).c_str()); } grpc_core::Closure::Run(DEBUG_LOCATION, cb, error); } @@ -1639,7 +1642,6 @@ static void tcp_add_to_pollset_set(grpc_endpoint* ep, static void tcp_delete_from_pollset_set(grpc_endpoint* ep, grpc_pollset_set* pollset_set) { grpc_tcp* tcp = reinterpret_cast(ep); - ZerocopyDisableAndWaitForRemaining(tcp); grpc_pollset_set_del_fd(pollset_set, tcp->em_fd); } @@ -1673,10 +1675,7 @@ static bool tcp_can_track_err(grpc_endpoint* ep) { if (getsockname(tcp->fd, &addr, &len) < 0) { return false; } - if (addr.sa_family == AF_INET || addr.sa_family == AF_INET6) { - return true; - } - return false; + return addr.sa_family == AF_INET || addr.sa_family == AF_INET6; } static const grpc_endpoint_vtable vtable = {tcp_read, diff --git a/src/core/lib/iomgr/tcp_server.cc b/src/core/lib/iomgr/tcp_server.cc index 046fd4979bd..8d6fefbbb20 100644 --- a/src/core/lib/iomgr/tcp_server.cc +++ b/src/core/lib/iomgr/tcp_server.cc @@ -22,9 +22,9 @@ grpc_tcp_server_vtable* grpc_tcp_server_impl; -grpc_error* grpc_tcp_server_create(grpc_closure* shutdown_complete, - const grpc_channel_args* args, - grpc_tcp_server** server) { +grpc_error_handle grpc_tcp_server_create(grpc_closure* shutdown_complete, + const grpc_channel_args* args, + grpc_tcp_server** server) { return grpc_tcp_server_impl->create(shutdown_complete, args, server); } @@ -34,9 +34,9 @@ void grpc_tcp_server_start(grpc_tcp_server* server, grpc_tcp_server_impl->start(server, pollsets, on_accept_cb, cb_arg); } -grpc_error* grpc_tcp_server_add_port(grpc_tcp_server* s, - const grpc_resolved_address* addr, - int* out_port) { +grpc_error_handle grpc_tcp_server_add_port(grpc_tcp_server* s, + const grpc_resolved_address* addr, + int* out_port) { return grpc_tcp_server_impl->add_port(s, addr, out_port); } diff --git a/src/core/lib/iomgr/tcp_server.h b/src/core/lib/iomgr/tcp_server.h index 6ba3513da5b..50ac4e74a96 100644 --- a/src/core/lib/iomgr/tcp_server.h +++ b/src/core/lib/iomgr/tcp_server.h @@ -63,14 +63,15 @@ class TcpServerFdHandler { } // namespace grpc_core typedef struct grpc_tcp_server_vtable { - grpc_error* (*create)(grpc_closure* shutdown_complete, - const grpc_channel_args* args, - grpc_tcp_server** server); + grpc_error_handle (*create)(grpc_closure* shutdown_complete, + const grpc_channel_args* args, + grpc_tcp_server** server); void (*start)(grpc_tcp_server* server, const std::vector* pollsets, grpc_tcp_server_cb on_accept_cb, void* cb_arg); - grpc_error* (*add_port)(grpc_tcp_server* s, const grpc_resolved_address* addr, - int* out_port); + grpc_error_handle (*add_port)(grpc_tcp_server* s, + const grpc_resolved_address* addr, + int* out_port); grpc_core::TcpServerFdHandler* (*create_fd_handler)(grpc_tcp_server* s); unsigned (*port_fd_count)(grpc_tcp_server* s, unsigned port_index); int (*port_fd)(grpc_tcp_server* s, unsigned port_index, unsigned fd_index); @@ -84,9 +85,9 @@ typedef struct grpc_tcp_server_vtable { /* Create a server, initially not bound to any ports. The caller owns one ref. If shutdown_complete is not NULL, it will be used by grpc_tcp_server_unref() when the ref count reaches zero. */ -grpc_error* grpc_tcp_server_create(grpc_closure* shutdown_complete, - const grpc_channel_args* args, - grpc_tcp_server** server); +grpc_error_handle grpc_tcp_server_create(grpc_closure* shutdown_complete, + const grpc_channel_args* args, + grpc_tcp_server** server); /* Start listening to bound ports */ void grpc_tcp_server_start(grpc_tcp_server* server, @@ -102,9 +103,9 @@ void grpc_tcp_server_start(grpc_tcp_server* server, but not dualstack sockets. */ /* TODO(ctiller): deprecate this, and make grpc_tcp_server_add_ports to handle all of the multiple socket port matching logic in one place */ -grpc_error* grpc_tcp_server_add_port(grpc_tcp_server* s, - const grpc_resolved_address* addr, - int* out_port); +grpc_error_handle grpc_tcp_server_add_port(grpc_tcp_server* s, + const grpc_resolved_address* addr, + int* out_port); /* Create and return a TcpServerFdHandler so that it can be used by upper layer to hand over an externally connected fd to the grpc server. */ diff --git a/src/core/lib/iomgr/tcp_server_custom.cc b/src/core/lib/iomgr/tcp_server_custom.cc index 18d74945be5..fff75453f02 100644 --- a/src/core/lib/iomgr/tcp_server_custom.cc +++ b/src/core/lib/iomgr/tcp_server_custom.cc @@ -28,12 +28,12 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr_custom.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_custom.h" #include "src/core/lib/iomgr/tcp_server.h" @@ -80,9 +80,9 @@ struct grpc_tcp_server { grpc_resource_quota* resource_quota; }; -static grpc_error* tcp_server_create(grpc_closure* shutdown_complete, - const grpc_channel_args* args, - grpc_tcp_server** server) { +static grpc_error_handle tcp_server_create(grpc_closure* shutdown_complete, + const grpc_channel_args* args, + grpc_tcp_server** server) { grpc_tcp_server* s = static_cast(gpr_malloc(sizeof(grpc_tcp_server))); // Let the implementation decide if so_reuseport can be enabled or not. @@ -218,7 +218,7 @@ static void finish_accept(grpc_tcp_listener* sp, grpc_custom_socket* socket) { grpc_endpoint* ep = nullptr; grpc_resolved_address peer_name; std::string peer_name_string; - grpc_error* err; + grpc_error_handle err; memset(&peer_name, 0, sizeof(grpc_resolved_address)); peer_name.len = GRPC_MAX_SOCKADDR_SIZE; @@ -246,17 +246,18 @@ static void finish_accept(grpc_tcp_listener* sp, grpc_custom_socket* socket) { static void custom_accept_callback(grpc_custom_socket* socket, grpc_custom_socket* client, - grpc_error* error); + grpc_error_handle error); static void custom_accept_callback(grpc_custom_socket* socket, grpc_custom_socket* client, - grpc_error* error) { + grpc_error_handle error) { grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; grpc_tcp_listener* sp = socket->listener; if (error != GRPC_ERROR_NONE) { if (!sp->closed) { - gpr_log(GPR_ERROR, "Accept failed: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "Accept failed: %s", + grpc_error_std_string(error).c_str()); } gpr_free(client); GRPC_ERROR_UNREF(error); @@ -275,14 +276,14 @@ static void custom_accept_callback(grpc_custom_socket* socket, } } -static grpc_error* add_socket_to_server(grpc_tcp_server* s, - grpc_custom_socket* socket, - const grpc_resolved_address* addr, - unsigned port_index, - grpc_tcp_listener** listener) { +static grpc_error_handle add_socket_to_server(grpc_tcp_server* s, + grpc_custom_socket* socket, + const grpc_resolved_address* addr, + unsigned port_index, + grpc_tcp_listener** listener) { grpc_tcp_listener* sp = nullptr; int port = -1; - grpc_error* error; + grpc_error_handle error; grpc_resolved_address sockname_temp; // NOTE(lidiz) The last argument is "flags" which is unused by other @@ -335,9 +336,9 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, return GRPC_ERROR_NONE; } -static grpc_error* tcp_server_add_port(grpc_tcp_server* s, - const grpc_resolved_address* addr, - int* port) { +static grpc_error_handle tcp_server_add_port(grpc_tcp_server* s, + const grpc_resolved_address* addr, + int* port) { // This function is mostly copied from tcp_server_windows.c grpc_tcp_listener* sp = nullptr; grpc_custom_socket* socket; @@ -346,7 +347,7 @@ static grpc_error* tcp_server_add_port(grpc_tcp_server* s, grpc_resolved_address* allocated_addr = nullptr; grpc_resolved_address sockname_temp; unsigned port_index = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; int family; GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); @@ -392,7 +393,7 @@ static grpc_error* tcp_server_add_port(grpc_tcp_server* s, if (GRPC_TRACE_FLAG_ENABLED(grpc_tcp_trace)) { gpr_log(GPR_INFO, "SERVER %p add_port %s error=%s", s, grpc_sockaddr_to_string(addr, false).c_str(), - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } family = grpc_sockaddr_get_family(addr); @@ -410,8 +411,9 @@ static grpc_error* tcp_server_add_port(grpc_tcp_server* s, gpr_free(allocated_addr); if (error != GRPC_ERROR_NONE) { - grpc_error* error_out = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Failed to add port to server", &error, 1); + grpc_error_handle error_out = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Failed to add port to server", &error, 1); GRPC_ERROR_UNREF(error); error = error_out; *port = -1; diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc index d6e13e81d15..5662aec7c97 100644 --- a/src/core/lib/iomgr/tcp_server_posix.cc +++ b/src/core/lib/iomgr/tcp_server_posix.cc @@ -47,22 +47,22 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/tcp_server_utils_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" -static grpc_error* tcp_server_create(grpc_closure* shutdown_complete, - const grpc_channel_args* args, - grpc_tcp_server** server) { +static grpc_error_handle tcp_server_create(grpc_closure* shutdown_complete, + const grpc_channel_args* args, + grpc_tcp_server** server) { grpc_tcp_server* s = static_cast(gpr_zalloc(sizeof(grpc_tcp_server))); s->so_reuseport = grpc_is_socket_reuse_port_supported(); @@ -129,7 +129,7 @@ static void finish_shutdown(grpc_tcp_server* s) { gpr_free(s); } -static void destroyed_port(void* server, grpc_error* /*error*/) { +static void destroyed_port(void* server, grpc_error_handle /*error*/) { grpc_tcp_server* s = static_cast(server); gpr_mu_lock(&s->mu); s->destroyed_ports++; @@ -188,7 +188,7 @@ static void tcp_server_destroy(grpc_tcp_server* s) { } /* event manager callback when reads are ready */ -static void on_read(void* arg, grpc_error* err) { +static void on_read(void* arg, grpc_error_handle err) { grpc_tcp_listener* sp = static_cast(arg); grpc_pollset* read_notifier_pollset; if (err != GRPC_ERROR_NONE) { @@ -281,18 +281,18 @@ error: } /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ -static grpc_error* add_wildcard_addrs_to_server(grpc_tcp_server* s, - unsigned port_index, - int requested_port, - int* out_port) { +static grpc_error_handle add_wildcard_addrs_to_server(grpc_tcp_server* s, + unsigned port_index, + int requested_port, + int* out_port) { grpc_resolved_address wild4; grpc_resolved_address wild6; unsigned fd_index = 0; grpc_dualstack_mode dsmode; grpc_tcp_listener* sp = nullptr; grpc_tcp_listener* sp2 = nullptr; - grpc_error* v6_err = GRPC_ERROR_NONE; - grpc_error* v4_err = GRPC_ERROR_NONE; + grpc_error_handle v6_err = GRPC_ERROR_NONE; + grpc_error_handle v4_err = GRPC_ERROR_NONE; *out_port = -1; if (grpc_tcp_server_have_ifaddrs() && s->expand_wildcard_addrs) { @@ -325,19 +325,19 @@ static grpc_error* add_wildcard_addrs_to_server(grpc_tcp_server* s, gpr_log(GPR_INFO, "Failed to add :: listener, " "the environment may not support IPv6: %s", - grpc_error_string(v6_err)); + grpc_error_std_string(v6_err).c_str()); GRPC_ERROR_UNREF(v6_err); } if (v4_err != GRPC_ERROR_NONE) { gpr_log(GPR_INFO, "Failed to add 0.0.0.0 listener, " "the environment may not support IPv4: %s", - grpc_error_string(v4_err)); + grpc_error_std_string(v4_err).c_str()); GRPC_ERROR_UNREF(v4_err); } return GRPC_ERROR_NONE; } else { - grpc_error* root_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + grpc_error_handle root_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Failed to add any wildcard listeners"); GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE); root_err = grpc_error_add_child(root_err, v6_err); @@ -346,10 +346,11 @@ static grpc_error* add_wildcard_addrs_to_server(grpc_tcp_server* s, } } -static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) { +static grpc_error_handle clone_port(grpc_tcp_listener* listener, + unsigned count) { grpc_tcp_listener* sp = nullptr; std::string addr_str; - grpc_error* err; + grpc_error_handle err; for (grpc_tcp_listener* l = listener->next; l && l->is_sibling; l = l->next) { l->fd_index += count; @@ -395,16 +396,16 @@ static grpc_error* clone_port(grpc_tcp_listener* listener, unsigned count) { return GRPC_ERROR_NONE; } -static grpc_error* tcp_server_add_port(grpc_tcp_server* s, - const grpc_resolved_address* addr, - int* out_port) { +static grpc_error_handle tcp_server_add_port(grpc_tcp_server* s, + const grpc_resolved_address* addr, + int* out_port) { grpc_tcp_listener* sp; grpc_resolved_address sockname_temp; grpc_resolved_address addr6_v4mapped; int requested_port = grpc_sockaddr_get_port(addr); unsigned port_index = 0; grpc_dualstack_mode dsmode; - grpc_error* err; + grpc_error_handle err; *out_port = -1; if (s->tail != nullptr) { port_index = s->tail->port_index + 1; diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h index 6b8a5f9f207..ed4587a34ce 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix.h +++ b/src/core/lib/iomgr/tcp_server_utils_posix.h @@ -98,26 +98,27 @@ struct grpc_tcp_server { /* If successful, add a listener to \a s for \a addr, set \a dsmode for the socket, and return the \a listener. */ -grpc_error* grpc_tcp_server_add_addr(grpc_tcp_server* s, - const grpc_resolved_address* addr, - unsigned port_index, unsigned fd_index, - grpc_dualstack_mode* dsmode, - grpc_tcp_listener** listener); +grpc_error_handle grpc_tcp_server_add_addr(grpc_tcp_server* s, + const grpc_resolved_address* addr, + unsigned port_index, + unsigned fd_index, + grpc_dualstack_mode* dsmode, + grpc_tcp_listener** listener); /* Get all addresses assigned to network interfaces on the machine and create a listener for each. requested_port is the port to use for every listener, or 0 to select one random port that will be used for every listener. Set *out_port to the port selected. Return GRPC_ERROR_NONE only if all listeners were added. */ -grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, - unsigned port_index, - int requested_port, - int* out_port); +grpc_error_handle grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, + unsigned port_index, + int requested_port, + int* out_port); /* Prepare a recently-created socket for listening. */ -grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server*, int fd, - const grpc_resolved_address* addr, - bool so_reuseport, int* port); +grpc_error_handle grpc_tcp_server_prepare_socket( + grpc_tcp_server*, int fd, const grpc_resolved_address* addr, + bool so_reuseport, int* port); /* Ruturn true if the platform supports ifaddrs */ bool grpc_tcp_server_have_ifaddrs(void); diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index bd7ff9b363e..6fdf0701a86 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -37,9 +37,9 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #define MIN_SAFE_ACCEPT_QUEUE_SIZE 100 @@ -80,14 +80,15 @@ static int get_max_accept_queue_size(void) { return s_max_accept_queue_size; } -static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd, - const grpc_resolved_address* addr, - unsigned port_index, unsigned fd_index, - grpc_tcp_listener** listener) { +static grpc_error_handle add_socket_to_server(grpc_tcp_server* s, int fd, + const grpc_resolved_address* addr, + unsigned port_index, + unsigned fd_index, + grpc_tcp_listener** listener) { grpc_tcp_listener* sp = nullptr; int port = -1; - grpc_error* err = + grpc_error_handle err = grpc_tcp_server_prepare_socket(s, fd, addr, s->so_reuseport, &port); if (err == GRPC_ERROR_NONE) { GPR_ASSERT(port > 0); @@ -123,14 +124,15 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, int fd, /* If successful, add a listener to s for addr, set *dsmode for the socket, and return the *listener. */ -grpc_error* grpc_tcp_server_add_addr(grpc_tcp_server* s, - const grpc_resolved_address* addr, - unsigned port_index, unsigned fd_index, - grpc_dualstack_mode* dsmode, - grpc_tcp_listener** listener) { +grpc_error_handle grpc_tcp_server_add_addr(grpc_tcp_server* s, + const grpc_resolved_address* addr, + unsigned port_index, + unsigned fd_index, + grpc_dualstack_mode* dsmode, + grpc_tcp_listener** listener) { grpc_resolved_address addr4_copy; int fd; - grpc_error* err = + grpc_error_handle err = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd); if (err != GRPC_ERROR_NONE) { return err; @@ -143,11 +145,11 @@ grpc_error* grpc_tcp_server_add_addr(grpc_tcp_server* s, } /* Prepare a recently-created socket for listening. */ -grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd, - const grpc_resolved_address* addr, - bool so_reuseport, int* port) { +grpc_error_handle grpc_tcp_server_prepare_socket( + grpc_tcp_server* s, int fd, const grpc_resolved_address* addr, + bool so_reuseport, int* port) { grpc_resolved_address sockname_temp; - grpc_error* err = GRPC_ERROR_NONE; + grpc_error_handle err = GRPC_ERROR_NONE; GPR_ASSERT(fd >= 0); @@ -210,7 +212,7 @@ error: if (fd >= 0) { close(fd); } - grpc_error* ret = + grpc_error_handle ret = grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Unable to configure socket", &err, 1), GRPC_ERROR_INT_FD, fd); diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc index d591f789691..a7e8f840db0 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc @@ -36,9 +36,9 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" /* Return the listener in s with address addr or NULL. */ static grpc_tcp_listener* find_listener_with_addr(grpc_tcp_server* s, @@ -58,12 +58,12 @@ static grpc_tcp_listener* find_listener_with_addr(grpc_tcp_server* s, } /* Bind to "::" to get a port number not used by any address. */ -static grpc_error* get_unused_port(int* port) { +static grpc_error_handle get_unused_port(int* port) { grpc_resolved_address wild; grpc_sockaddr_make_wildcard6(0, &wild); grpc_dualstack_mode dsmode; int fd; - grpc_error* err = + grpc_error_handle err = grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd); if (err != GRPC_ERROR_NONE) { return err; @@ -89,15 +89,15 @@ static grpc_error* get_unused_port(int* port) { : GRPC_ERROR_NONE; } -grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, - unsigned port_index, - int requested_port, - int* out_port) { +grpc_error_handle grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, + unsigned port_index, + int requested_port, + int* out_port) { struct ifaddrs* ifa = nullptr; struct ifaddrs* ifa_it; unsigned fd_index = 0; grpc_tcp_listener* sp = nullptr; - grpc_error* err = GRPC_ERROR_NONE; + grpc_error_handle err = GRPC_ERROR_NONE; if (requested_port == 0) { /* Note: There could be a race where some local addrs can listen on the selected port and some can't. The sane way to handle this would be to @@ -146,7 +146,7 @@ grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, } if ((err = grpc_tcp_server_add_addr(s, &addr, port_index, fd_index, &dsmode, &new_sp)) != GRPC_ERROR_NONE) { - grpc_error* root_err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle root_err = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("Failed to add listener: ", addr_str).c_str()); err = grpc_error_add_child(root_err, err); break; diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc index 86ee14f2856..a9354b00146 100644 --- a/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc +++ b/src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc @@ -24,10 +24,10 @@ #include "src/core/lib/iomgr/tcp_server_utils_posix.h" -grpc_error* grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, - unsigned port_index, - int requested_port, - int* out_port) { +grpc_error_handle grpc_tcp_server_add_all_local_addrs(grpc_tcp_server* s, + unsigned port_index, + int requested_port, + int* out_port) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("no ifaddrs available"); } diff --git a/src/core/lib/iomgr/tcp_server_windows.cc b/src/core/lib/iomgr/tcp_server_windows.cc index c44c3a5cd77..614ea35ef20 100644 --- a/src/core/lib/iomgr/tcp_server_windows.cc +++ b/src/core/lib/iomgr/tcp_server_windows.cc @@ -38,11 +38,11 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/pollset_windows.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/tcp_windows.h" @@ -101,9 +101,9 @@ struct grpc_tcp_server { /* Public function. Allocates the proper data structures to hold a grpc_tcp_server. */ -static grpc_error* tcp_server_create(grpc_closure* shutdown_complete, - const grpc_channel_args* args, - grpc_tcp_server** server) { +static grpc_error_handle tcp_server_create(grpc_closure* shutdown_complete, + const grpc_channel_args* args, + grpc_tcp_server** server) { grpc_tcp_server* s = (grpc_tcp_server*)gpr_malloc(sizeof(grpc_tcp_server)); s->channel_args = grpc_channel_args_copy(args); gpr_ref_init(&s->refs, 1); @@ -120,7 +120,7 @@ static grpc_error* tcp_server_create(grpc_closure* shutdown_complete, return GRPC_ERROR_NONE; } -static void destroy_server(void* arg, grpc_error* error) { +static void destroy_server(void* arg, grpc_error_handle error) { grpc_tcp_server* s = (grpc_tcp_server*)arg; /* Now that the accepts have been aborted, we can destroy the sockets. @@ -191,11 +191,11 @@ static void tcp_server_unref(grpc_tcp_server* s) { } /* Prepare (bind) a recently-created socket for listening. */ -static grpc_error* prepare_socket(SOCKET sock, - const grpc_resolved_address* addr, - int* port) { +static grpc_error_handle prepare_socket(SOCKET sock, + const grpc_resolved_address* addr, + int* port) { grpc_resolved_address sockname_temp; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; int sockname_temp_len; error = grpc_tcp_prepare_socket(sock); @@ -249,12 +249,12 @@ static void decrement_active_ports_and_notify_locked(grpc_tcp_listener* sp) { /* In order to do an async accept, we need to create a socket first which will be the one assigned to the new incoming connection. */ -static grpc_error* start_accept_locked(grpc_tcp_listener* port) { +static grpc_error_handle start_accept_locked(grpc_tcp_listener* port) { SOCKET sock = INVALID_SOCKET; BOOL success; DWORD addrlen = sizeof(grpc_sockaddr_in6) + 16; DWORD bytes_received = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (port->shutting_down) { return GRPC_ERROR_NONE; @@ -299,7 +299,7 @@ failure: } /* Event manager callback when reads are ready. */ -static void on_accept(void* arg, grpc_error* error) { +static void on_accept(void* arg, grpc_error_handle error) { grpc_tcp_listener* sp = (grpc_tcp_listener*)arg; SOCKET sock = sp->new_socket; grpc_winsocket_callback_info* info = &sp->socket->read_info; @@ -318,8 +318,8 @@ static void on_accept(void* arg, grpc_error* error) { this is necessary in the read/write case, it's useless for the accept case. We only need to adjust the pending callback count */ if (error != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(error); - gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg); + gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", + grpc_error_std_string(error).c_str()); gpr_mu_unlock(&sp->server->mu); return; @@ -388,17 +388,17 @@ static void on_accept(void* arg, grpc_error* error) { gpr_mu_unlock(&sp->server->mu); } -static grpc_error* add_socket_to_server(grpc_tcp_server* s, SOCKET sock, - const grpc_resolved_address* addr, - unsigned port_index, - grpc_tcp_listener** listener) { +static grpc_error_handle add_socket_to_server(grpc_tcp_server* s, SOCKET sock, + const grpc_resolved_address* addr, + unsigned port_index, + grpc_tcp_listener** listener) { grpc_tcp_listener* sp = NULL; int port = -1; int status; GUID guid = WSAID_ACCEPTEX; DWORD ioctl_num_bytes; LPFN_ACCEPTEX AcceptEx; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; /* We need to grab the AcceptEx pointer for that port, as it may be interface-dependent. We'll cache it to avoid doing that again. */ @@ -446,9 +446,9 @@ static grpc_error* add_socket_to_server(grpc_tcp_server* s, SOCKET sock, return GRPC_ERROR_NONE; } -static grpc_error* tcp_server_add_port(grpc_tcp_server* s, - const grpc_resolved_address* addr, - int* port) { +static grpc_error_handle tcp_server_add_port(grpc_tcp_server* s, + const grpc_resolved_address* addr, + int* port) { grpc_tcp_listener* sp = NULL; SOCKET sock; grpc_resolved_address addr6_v4mapped; @@ -456,7 +456,7 @@ static grpc_error* tcp_server_add_port(grpc_tcp_server* s, grpc_resolved_address* allocated_addr = NULL; grpc_resolved_address sockname_temp; unsigned port_index = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (s->tail != NULL) { port_index = s->tail->port_index + 1; @@ -508,8 +508,9 @@ done: gpr_free(allocated_addr); if (error != GRPC_ERROR_NONE) { - grpc_error* error_out = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Failed to add port to server", &error, 1); + grpc_error_handle error_out = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Failed to add port to server", &error, 1); GRPC_ERROR_UNREF(error); error = error_out; *port = -1; diff --git a/src/core/lib/iomgr/tcp_uv.cc b/src/core/lib/iomgr/tcp_uv.cc index e395b149265..8f64d22b1fe 100644 --- a/src/core/lib/iomgr/tcp_uv.cc +++ b/src/core/lib/iomgr/tcp_uv.cc @@ -55,7 +55,7 @@ typedef struct uv_socket_t { int pending_connections; grpc_custom_socket* accept_socket; - grpc_error* accept_error; + grpc_error_handle accept_error; grpc_custom_connect_callback connect_cb; grpc_custom_write_callback write_cb; @@ -65,11 +65,11 @@ typedef struct uv_socket_t { } uv_socket_t; -static grpc_error* tcp_error_create(const char* desc, int status) { +static grpc_error_handle tcp_error_create(const char* desc, int status) { if (status == 0) { return GRPC_ERROR_NONE; } - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(desc); /* All tcp errors are marked with UNAVAILABLE so that application may * choose to retry. */ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, @@ -95,7 +95,7 @@ static void alloc_uv_buf(uv_handle_t* handle, size_t suggested_size, static void uv_read_callback(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (nread == 0) { // Nothing happened. Wait for the next callback return; @@ -126,7 +126,7 @@ static void uv_socket_read(grpc_custom_socket* socket, char* buffer, size_t length, grpc_custom_read_callback read_cb) { uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; int status; - grpc_error* error; + grpc_error_handle error; uv_socket->read_cb = read_cb; uv_socket->read_buf = buffer; uv_socket->read_len = length; @@ -184,7 +184,8 @@ static void uv_socket_close(grpc_custom_socket* socket, uv_close((uv_handle_t*)uv_socket->handle, uv_close_callback); } -static grpc_error* uv_socket_init_helper(uv_socket_t* uv_socket, int domain) { +static grpc_error_handle uv_socket_init_helper(uv_socket_t* uv_socket, + int domain) { uv_tcp_t* tcp = (uv_tcp_t*)gpr_malloc(sizeof(uv_tcp_t)); uv_socket->handle = tcp; int status = uv_tcp_init_ex(uv_default_loop(), tcp, (unsigned int)domain); @@ -212,9 +213,10 @@ static grpc_error* uv_socket_init_helper(uv_socket_t* uv_socket, int domain) { return GRPC_ERROR_NONE; } -static grpc_error* uv_socket_init(grpc_custom_socket* socket, int domain) { +static grpc_error_handle uv_socket_init(grpc_custom_socket* socket, + int domain) { uv_socket_t* uv_socket = (uv_socket_t*)gpr_malloc(sizeof(uv_socket_t)); - grpc_error* error = uv_socket_init_helper(uv_socket, domain); + grpc_error_handle error = uv_socket_init_helper(uv_socket, domain); if (error != GRPC_ERROR_NONE) { return error; } @@ -223,18 +225,18 @@ static grpc_error* uv_socket_init(grpc_custom_socket* socket, int domain) { return GRPC_ERROR_NONE; } -static grpc_error* uv_socket_getpeername(grpc_custom_socket* socket, - const grpc_sockaddr* addr, - int* addr_len) { +static grpc_error_handle uv_socket_getpeername(grpc_custom_socket* socket, + const grpc_sockaddr* addr, + int* addr_len) { uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; int err = uv_tcp_getpeername(uv_socket->handle, (struct sockaddr*)IGNORE_CONST(addr), addr_len); return tcp_error_create("getpeername failed", err); } -static grpc_error* uv_socket_getsockname(grpc_custom_socket* socket, - const grpc_sockaddr* addr, - int* addr_len) { +static grpc_error_handle uv_socket_getsockname(grpc_custom_socket* socket, + const grpc_sockaddr* addr, + int* addr_len) { uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; int err = uv_tcp_getsockname(uv_socket->handle, (struct sockaddr*)IGNORE_CONST(addr), addr_len); @@ -247,7 +249,7 @@ static void accept_new_connection(grpc_custom_socket* socket) { return; } grpc_custom_socket* new_socket = uv_socket->accept_socket; - grpc_error* error = uv_socket->accept_error; + grpc_error_handle error = uv_socket->accept_error; uv_socket->accept_socket = nullptr; uv_socket->accept_error = GRPC_ERROR_NONE; uv_socket->pending_connections -= 1; @@ -293,16 +295,16 @@ void uv_socket_accept(grpc_custom_socket* socket, accept_new_connection(socket); } -static grpc_error* uv_socket_bind(grpc_custom_socket* socket, - const grpc_sockaddr* addr, size_t len, - int flags) { +static grpc_error_handle uv_socket_bind(grpc_custom_socket* socket, + const grpc_sockaddr* addr, size_t len, + int flags) { uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; int status = uv_tcp_bind((uv_tcp_t*)uv_socket->handle, (struct sockaddr*)addr, 0); return tcp_error_create("Failed to bind to port", status); } -static grpc_error* uv_socket_listen(grpc_custom_socket* socket) { +static grpc_error_handle uv_socket_listen(grpc_custom_socket* socket) { uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; int status = uv_listen((uv_stream_t*)uv_socket->handle, SOMAXCONN, uv_on_connect); @@ -312,7 +314,7 @@ static grpc_error* uv_socket_listen(grpc_custom_socket* socket) { static void uv_tc_on_connect(uv_connect_t* req, int status) { grpc_custom_socket* socket = (grpc_custom_socket*)req->data; uv_socket_t* uv_socket = (uv_socket_t*)socket->impl; - grpc_error* error; + grpc_error_handle error; if (status == UV_ECANCELED) { // This should only happen if the handle is already closed error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Timeout occurred"); @@ -370,8 +372,8 @@ static void uv_resolve_callback(uv_getaddrinfo_t* req, int status, tcp_error_create("getaddrinfo failed", status)); } -static grpc_error* uv_resolve(const char* host, const char* port, - grpc_resolved_addresses** result) { +static grpc_error_handle uv_resolve(const char* host, const char* port, + grpc_resolved_addresses** result) { int status; uv_getaddrinfo_t req; struct addrinfo hints; @@ -403,7 +405,7 @@ static void uv_resolve_async(grpc_custom_resolver* r, const char* host, port, &hints); if (status != 0) { gpr_free(req); - grpc_error* error = tcp_error_create("getaddrinfo failed", status); + grpc_error_handle error = tcp_error_create("getaddrinfo failed", status); grpc_custom_resolve_callback(r, NULL, error); } } diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc index d28a54ccf43..aa693cc1fbb 100644 --- a/src/core/lib/iomgr/tcp_windows.cc +++ b/src/core/lib/iomgr/tcp_windows.cc @@ -32,10 +32,10 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/iomgr/iocp_windows.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_windows.h" @@ -53,7 +53,7 @@ extern grpc_core::TraceFlag grpc_tcp_trace; -grpc_error* grpc_tcp_set_non_block(SOCKET sock) { +grpc_error_handle grpc_tcp_set_non_block(SOCKET sock) { int status; uint32_t param = 1; DWORD ret; @@ -64,7 +64,7 @@ grpc_error* grpc_tcp_set_non_block(SOCKET sock) { : GRPC_WSA_ERROR(WSAGetLastError(), "WSAIoctl(GRPC_FIONBIO)"); } -static grpc_error* set_dualstack(SOCKET sock) { +static grpc_error_handle set_dualstack(SOCKET sock) { int status; unsigned long param = 0; status = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)¶m, @@ -74,7 +74,7 @@ static grpc_error* set_dualstack(SOCKET sock) { : GRPC_WSA_ERROR(WSAGetLastError(), "setsockopt(IPV6_V6ONLY)"); } -static grpc_error* enable_socket_low_latency(SOCKET sock) { +static grpc_error_handle enable_socket_low_latency(SOCKET sock) { int status; BOOL param = TRUE; status = ::setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, @@ -86,8 +86,8 @@ static grpc_error* enable_socket_low_latency(SOCKET sock) { : GRPC_WSA_ERROR(status, "setsockopt(TCP_NODELAY)"); } -grpc_error* grpc_tcp_prepare_socket(SOCKET sock) { - grpc_error* err; +grpc_error_handle grpc_tcp_prepare_socket(SOCKET sock) { + grpc_error_handle err; err = grpc_tcp_set_non_block(sock); if (err != GRPC_ERROR_NONE) return err; err = set_dualstack(sock); @@ -123,7 +123,7 @@ typedef struct grpc_tcp { to protect ourselves when requesting a shutdown. */ gpr_mu mu; int shutting_down; - grpc_error* shutdown_error; + grpc_error_handle shutdown_error; std::string peer_string; std::string local_address; @@ -177,7 +177,7 @@ static void tcp_ref(grpc_tcp* tcp) { gpr_ref(&tcp->refcount); } #endif /* Asynchronous callback from the IOCP, or the background thread. */ -static void on_read(void* tcpp, grpc_error* error) { +static void on_read(void* tcpp, grpc_error_handle error) { grpc_tcp* tcp = (grpc_tcp*)tcpp; grpc_closure* cb = tcp->read_cb; grpc_winsocket* socket = tcp->socket; @@ -313,7 +313,7 @@ static void win_read(grpc_endpoint* ep, grpc_slice_buffer* read_slices, } /* Asynchronous callback from the IOCP, or the background thread. */ -static void on_write(void* tcpp, grpc_error* error) { +static void on_write(void* tcpp, grpc_error_handle error) { grpc_tcp* tcp = (grpc_tcp*)tcpp; grpc_winsocket* handle = tcp->socket; grpc_winsocket_callback_info* info = &handle->write_info; @@ -399,9 +399,9 @@ static void win_write(grpc_endpoint* ep, grpc_slice_buffer* slices, connection that has its send queue filled up. But if we don't, then we can avoid doing an async write operation at all. */ if (info->wsa_error != WSAEWOULDBLOCK) { - grpc_error* error = status == 0 - ? GRPC_ERROR_NONE - : GRPC_WSA_ERROR(info->wsa_error, "WSASend"); + grpc_error_handle error = status == 0 + ? GRPC_ERROR_NONE + : GRPC_WSA_ERROR(info->wsa_error, "WSASend"); grpc_core::ExecCtx::Run(DEBUG_LOCATION, cb, error); if (allocated) gpr_free(allocated); return; @@ -454,7 +454,7 @@ static void win_delete_from_pollset_set(grpc_endpoint* ep, we're not going to protect against these. However the IO Completion Port callback will happen from another thread, so we need to protect against concurrent access of the data structure in that regard. */ -static void win_shutdown(grpc_endpoint* ep, grpc_error* why) { +static void win_shutdown(grpc_endpoint* ep, grpc_error_handle why) { grpc_tcp* tcp = (grpc_tcp*)ep; gpr_mu_lock(&tcp->mu); /* At that point, what may happen is that we're already inside the IOCP diff --git a/src/core/lib/iomgr/tcp_windows.h b/src/core/lib/iomgr/tcp_windows.h index 04ef8102b65..de3dc550f4e 100644 --- a/src/core/lib/iomgr/tcp_windows.h +++ b/src/core/lib/iomgr/tcp_windows.h @@ -44,9 +44,9 @@ grpc_endpoint* grpc_tcp_create(grpc_winsocket* socket, grpc_channel_args* channel_args, const char* peer_string); -grpc_error* grpc_tcp_prepare_socket(SOCKET sock); +grpc_error_handle grpc_tcp_prepare_socket(SOCKET sock); -grpc_error* grpc_tcp_set_non_block(SOCKET sock); +grpc_error_handle grpc_tcp_set_non_block(SOCKET sock); #endif diff --git a/src/core/lib/iomgr/timer_custom.cc b/src/core/lib/iomgr/timer_custom.cc index 867359a28db..cb01b7ce799 100644 --- a/src/core/lib/iomgr/timer_custom.cc +++ b/src/core/lib/iomgr/timer_custom.cc @@ -30,7 +30,8 @@ static grpc_custom_timer_vtable* custom_timer_impl; -void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* /*error*/) { +void grpc_custom_timer_callback(grpc_custom_timer* t, + grpc_error_handle /*error*/) { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; diff --git a/src/core/lib/iomgr/timer_custom.h b/src/core/lib/iomgr/timer_custom.h index bfea8bafa69..83c3e8ddab9 100644 --- a/src/core/lib/iomgr/timer_custom.h +++ b/src/core/lib/iomgr/timer_custom.h @@ -38,6 +38,6 @@ typedef struct grpc_custom_timer_vtable { void grpc_custom_timer_init(grpc_custom_timer_vtable* impl); -void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error); +void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error_handle error); #endif /* GRPC_CORE_LIB_IOMGR_TIMER_CUSTOM_H */ diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc index c4e961af995..3d2fc0061e4 100644 --- a/src/core/lib/iomgr/timer_generic.cc +++ b/src/core/lib/iomgr/timer_generic.cc @@ -247,7 +247,7 @@ static grpc_millis saturating_add(grpc_millis a, grpc_millis b) { static grpc_timer_check_result run_some_expired_timers(grpc_millis now, grpc_millis* next, - grpc_error* error); + grpc_error_handle error); static grpc_millis compute_min_deadline(timer_shard* shard) { return grpc_timer_heap_is_empty(&shard->heap) @@ -561,7 +561,8 @@ static grpc_timer* pop_one(timer_shard* shard, grpc_millis now) { /* REQUIRES: shard->mu unlocked */ static size_t pop_timers(timer_shard* shard, grpc_millis now, - grpc_millis* new_min_deadline, grpc_error* error) { + grpc_millis* new_min_deadline, + grpc_error_handle error) { size_t n = 0; grpc_timer* timer; gpr_mu_lock(&shard->mu); @@ -580,9 +581,8 @@ static size_t pop_timers(timer_shard* shard, grpc_millis now, return n; } -static grpc_timer_check_result run_some_expired_timers(grpc_millis now, - grpc_millis* next, - grpc_error* error) { +static grpc_timer_check_result run_some_expired_timers( + grpc_millis now, grpc_millis* next, grpc_error_handle error) { grpc_timer_check_result result = GRPC_TIMERS_NOT_CHECKED; #if GPR_ARCH_64 @@ -702,7 +702,7 @@ static grpc_timer_check_result timer_check(grpc_millis* next) { return GRPC_TIMERS_CHECKED_AND_EMPTY; } - grpc_error* shutdown_error = + grpc_error_handle shutdown_error = now != GRPC_MILLIS_INF_FUTURE ? GRPC_ERROR_NONE : GRPC_ERROR_CREATE_FROM_STATIC_STRING("Shutting down timer system"); diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc index c2eacc5053d..4efaf23b4aa 100644 --- a/src/core/lib/iomgr/udp_server.cc +++ b/src/core/lib/iomgr/udp_server.cc @@ -56,6 +56,8 @@ #include #include #include + +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/memory.h" @@ -64,7 +66,6 @@ #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_factory_posix.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" @@ -83,11 +84,11 @@ class GrpcUdpListener { /* Called when data is available to read from the socket. * Return true if there is more data to read from fd. */ - void OnRead(grpc_error* error, void* do_read_arg); + void OnRead(grpc_error_handle error, void* do_read_arg); /* Called when the socket is writeable. The given closure should be scheduled * when the socket becomes blocked next time. */ - void OnCanWrite(grpc_error* error, void* do_write_arg); + void OnCanWrite(grpc_error_handle error, void* do_write_arg); /* Called when the grpc_fd is about to be orphaned (and the FD closed). */ void OnFdAboutToOrphan(); @@ -107,16 +108,16 @@ class GrpcUdpListener { private: /* event manager callback when reads are ready */ - static void on_read(void* arg, grpc_error* error); - static void on_write(void* arg, grpc_error* error); + static void on_read(void* arg, grpc_error_handle error); + static void on_write(void* arg, grpc_error_handle error); - static void do_read(void* arg, grpc_error* error); - static void do_write(void* arg, grpc_error* error); + static void do_read(void* arg, grpc_error_handle error); + static void do_write(void* arg, grpc_error_handle error); // Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback // interface. - static void fd_notify_on_write_wrapper(void* arg, grpc_error* error); + static void fd_notify_on_write_wrapper(void* arg, grpc_error_handle error); - static void shutdown_fd(void* args, grpc_error* error); + static void shutdown_fd(void* args, grpc_error_handle error); int fd_; grpc_fd* emfd_; @@ -222,7 +223,7 @@ grpc_udp_server* grpc_udp_server_create(const grpc_channel_args* args) { } // static -void GrpcUdpListener::shutdown_fd(void* args, grpc_error* error) { +void GrpcUdpListener::shutdown_fd(void* args, grpc_error_handle error) { if (args == nullptr) { // No-op if shutdown args are null. return; @@ -261,7 +262,7 @@ static void finish_shutdown(grpc_udp_server* s) { delete s; } -static void destroyed_port(void* server, grpc_error* /*error*/) { +static void destroyed_port(void* server, grpc_error_handle /*error*/) { grpc_udp_server* s = static_cast(server); gpr_mu_lock(&s->mu); s->destroyed_ports++; @@ -436,7 +437,7 @@ error: } // static -void GrpcUdpListener::do_read(void* arg, grpc_error* error) { +void GrpcUdpListener::do_read(void* arg, grpc_error_handle error) { GrpcUdpListener* sp = static_cast(arg); GPR_ASSERT(error == GRPC_ERROR_NONE); /* TODO: the reason we hold server->mu here is merely to prevent fd @@ -460,12 +461,12 @@ void GrpcUdpListener::do_read(void* arg, grpc_error* error) { } // static -void GrpcUdpListener::on_read(void* arg, grpc_error* error) { +void GrpcUdpListener::on_read(void* arg, grpc_error_handle error) { GrpcUdpListener* sp = static_cast(arg); sp->OnRead(error, arg); } -void GrpcUdpListener::OnRead(grpc_error* error, void* do_read_arg) { +void GrpcUdpListener::OnRead(grpc_error_handle error, void* do_read_arg) { if (error != GRPC_ERROR_NONE) { gpr_mu_lock(&server_->mu); if (0 == --server_->active_ports && server_->shutdown) { @@ -497,7 +498,7 @@ void GrpcUdpListener::OnRead(grpc_error* error, void* do_read_arg) { // static // Wrapper of grpc_fd_notify_on_write() with a grpc_closure callback interface. void GrpcUdpListener::fd_notify_on_write_wrapper(void* arg, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { GrpcUdpListener* sp = static_cast(arg); gpr_mu_lock(sp->mutex()); if (!sp->notify_on_write_armed_) { @@ -508,7 +509,7 @@ void GrpcUdpListener::fd_notify_on_write_wrapper(void* arg, } // static -void GrpcUdpListener::do_write(void* arg, grpc_error* error) { +void GrpcUdpListener::do_write(void* arg, grpc_error_handle error) { GrpcUdpListener* sp = static_cast(arg); gpr_mu_lock(sp->mutex()); if (sp->already_shutdown_) { @@ -527,12 +528,12 @@ void GrpcUdpListener::do_write(void* arg, grpc_error* error) { } // static -void GrpcUdpListener::on_write(void* arg, grpc_error* error) { +void GrpcUdpListener::on_write(void* arg, grpc_error_handle error) { GrpcUdpListener* sp = static_cast(arg); sp->OnCanWrite(error, arg); } -void GrpcUdpListener::OnCanWrite(grpc_error* error, void* do_write_arg) { +void GrpcUdpListener::OnCanWrite(grpc_error_handle error, void* do_write_arg) { if (error != GRPC_ERROR_NONE) { gpr_mu_lock(&server_->mu); if (0 == --server_->active_ports && server_->shutdown) { @@ -630,7 +631,7 @@ int grpc_udp_server_add_port(grpc_udp_server* s, grpc_resolved_address* addr, /* Try listening on IPv6 first. */ addr = &wild6; - // TODO(rjshade): Test and propagate the returned grpc_error*: + // TODO(rjshade): Test and propagate the returned grpc_error_handle: GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory( s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd)); allocated_port1 = @@ -666,7 +667,7 @@ int grpc_udp_server_add_port(grpc_udp_server* s, grpc_resolved_address* addr, addr = &wild4; } - // TODO(rjshade): Test and propagate the returned grpc_error*: + // TODO(rjshade): Test and propagate the returned grpc_error_handle: GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory( s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd)); if (fd < 0) { diff --git a/src/core/lib/iomgr/unix_sockets_posix.cc b/src/core/lib/iomgr/unix_sockets_posix.cc index 034aa91005e..2b077a38cf0 100644 --- a/src/core/lib/iomgr/unix_sockets_posix.cc +++ b/src/core/lib/iomgr/unix_sockets_posix.cc @@ -30,7 +30,7 @@ #include "absl/strings/str_cat.h" -#include "src/core/lib/iomgr/parse_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include @@ -42,7 +42,7 @@ void grpc_create_socketpair_if_unix(int sv[2]) { GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); } -grpc_error* grpc_resolve_unix_domain_address( +grpc_error_handle grpc_resolve_unix_domain_address( const char* name, grpc_resolved_addresses** addresses) { *addresses = static_cast( gpr_malloc(sizeof(grpc_resolved_addresses))); @@ -52,7 +52,7 @@ grpc_error* grpc_resolve_unix_domain_address( return grpc_core::UnixSockaddrPopulate(name, (*addresses)->addrs); } -grpc_error* grpc_resolve_unix_abstract_domain_address( +grpc_error_handle grpc_resolve_unix_abstract_domain_address( const absl::string_view name, grpc_resolved_addresses** addresses) { *addresses = static_cast( gpr_malloc(sizeof(grpc_resolved_addresses))); diff --git a/src/core/lib/iomgr/unix_sockets_posix.h b/src/core/lib/iomgr/unix_sockets_posix.h index 302ac176eb2..c35423bc040 100644 --- a/src/core/lib/iomgr/unix_sockets_posix.h +++ b/src/core/lib/iomgr/unix_sockets_posix.h @@ -33,10 +33,10 @@ void grpc_create_socketpair_if_unix(int sv[2]); -grpc_error* grpc_resolve_unix_domain_address( +grpc_error_handle grpc_resolve_unix_domain_address( const char* name, grpc_resolved_addresses** addresses); -grpc_error* grpc_resolve_unix_abstract_domain_address( +grpc_error_handle grpc_resolve_unix_abstract_domain_address( absl::string_view name, grpc_resolved_addresses** addresses); int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr); diff --git a/src/core/lib/iomgr/unix_sockets_posix_noop.cc b/src/core/lib/iomgr/unix_sockets_posix_noop.cc index 7205797c38c..c2659221f9d 100644 --- a/src/core/lib/iomgr/unix_sockets_posix_noop.cc +++ b/src/core/lib/iomgr/unix_sockets_posix_noop.cc @@ -26,33 +26,36 @@ #include -void grpc_create_socketpair_if_unix(int sv[2]) { +void grpc_create_socketpair_if_unix(int /* sv */[2]) { // TODO: Either implement this for the non-Unix socket case or make // sure that it is never called in any such case. Until then, leave an // assertion to notify if this gets called inadvertently GPR_ASSERT(0); } -grpc_error* grpc_resolve_unix_domain_address( - const char* name, grpc_resolved_addresses** addresses) { +grpc_error_handle grpc_resolve_unix_domain_address( + const char* /* name */, grpc_resolved_addresses** addresses) { *addresses = NULL; return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unix domain sockets are not supported on Windows"); } -grpc_error* grpc_resolve_unix_abstract_domain_address( +grpc_error_handle grpc_resolve_unix_abstract_domain_address( absl::string_view, grpc_resolved_addresses** addresses) { *addresses = NULL; return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unix domain sockets are not supported on Windows"); } -int grpc_is_unix_socket(const grpc_resolved_address* addr) { return false; } +int grpc_is_unix_socket(const grpc_resolved_address* /* addr */) { + return false; +} -void grpc_unlink_if_unix_domain_socket(const grpc_resolved_address* addr) {} +void grpc_unlink_if_unix_domain_socket( + const grpc_resolved_address* /* addr */) {} std::string grpc_sockaddr_to_uri_unix_if_possible( - const grpc_resolved_address* addr) { + const grpc_resolved_address* /* addr */) { return ""; } diff --git a/src/core/lib/iomgr/wakeup_fd_eventfd.cc b/src/core/lib/iomgr/wakeup_fd_eventfd.cc index d68c9ada1f2..3951fe6f570 100644 --- a/src/core/lib/iomgr/wakeup_fd_eventfd.cc +++ b/src/core/lib/iomgr/wakeup_fd_eventfd.cc @@ -31,7 +31,7 @@ #include "src/core/lib/iomgr/wakeup_fd_posix.h" #include "src/core/lib/profiling/timers.h" -static grpc_error* eventfd_create(grpc_wakeup_fd* fd_info) { +static grpc_error_handle eventfd_create(grpc_wakeup_fd* fd_info) { fd_info->read_fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); fd_info->write_fd = -1; if (fd_info->read_fd < 0) { @@ -40,7 +40,7 @@ static grpc_error* eventfd_create(grpc_wakeup_fd* fd_info) { return GRPC_ERROR_NONE; } -static grpc_error* eventfd_consume(grpc_wakeup_fd* fd_info) { +static grpc_error_handle eventfd_consume(grpc_wakeup_fd* fd_info) { eventfd_t value; int err; do { @@ -52,7 +52,7 @@ static grpc_error* eventfd_consume(grpc_wakeup_fd* fd_info) { return GRPC_ERROR_NONE; } -static grpc_error* eventfd_wakeup(grpc_wakeup_fd* fd_info) { +static grpc_error_handle eventfd_wakeup(grpc_wakeup_fd* fd_info) { GPR_TIMER_SCOPE("eventfd_wakeup", 0); int err; do { diff --git a/src/core/lib/iomgr/wakeup_fd_pipe.cc b/src/core/lib/iomgr/wakeup_fd_pipe.cc index 797cd44cd1a..943d9d54e77 100644 --- a/src/core/lib/iomgr/wakeup_fd_pipe.cc +++ b/src/core/lib/iomgr/wakeup_fd_pipe.cc @@ -33,14 +33,14 @@ #include "src/core/lib/iomgr/socket_utils_posix.h" -static grpc_error* pipe_init(grpc_wakeup_fd* fd_info) { +static grpc_error_handle pipe_init(grpc_wakeup_fd* fd_info) { int pipefd[2]; int r = pipe(pipefd); if (0 != r) { gpr_log(GPR_ERROR, "pipe creation failed (%d): %s", errno, strerror(errno)); return GRPC_OS_ERROR(errno, "pipe"); } - grpc_error* err; + grpc_error_handle err; err = grpc_set_socket_nonblocking(pipefd[0], 1); if (err != GRPC_ERROR_NONE) return err; err = grpc_set_socket_nonblocking(pipefd[1], 1); @@ -50,7 +50,7 @@ static grpc_error* pipe_init(grpc_wakeup_fd* fd_info) { return GRPC_ERROR_NONE; } -static grpc_error* pipe_consume(grpc_wakeup_fd* fd_info) { +static grpc_error_handle pipe_consume(grpc_wakeup_fd* fd_info) { char buf[128]; ssize_t r; @@ -69,7 +69,7 @@ static grpc_error* pipe_consume(grpc_wakeup_fd* fd_info) { } } -static grpc_error* pipe_wakeup(grpc_wakeup_fd* fd_info) { +static grpc_error_handle pipe_wakeup(grpc_wakeup_fd* fd_info) { char c = 0; while (write(fd_info->write_fd, &c, 1) != 1 && errno == EINTR) { } diff --git a/src/core/lib/iomgr/wakeup_fd_posix.cc b/src/core/lib/iomgr/wakeup_fd_posix.cc index 3b66d6f34de..36b497b8670 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.cc +++ b/src/core/lib/iomgr/wakeup_fd_posix.cc @@ -50,15 +50,15 @@ void grpc_wakeup_fd_global_destroy(void) { wakeup_fd_vtable = nullptr; } int grpc_has_wakeup_fd(void) { return has_real_wakeup_fd; } -grpc_error* grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info) { +grpc_error_handle grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info) { return wakeup_fd_vtable->init(fd_info); } -grpc_error* grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info) { +grpc_error_handle grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info) { return wakeup_fd_vtable->consume(fd_info); } -grpc_error* grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info) { +grpc_error_handle grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info) { return wakeup_fd_vtable->wakeup(fd_info); } diff --git a/src/core/lib/iomgr/wakeup_fd_posix.h b/src/core/lib/iomgr/wakeup_fd_posix.h index 670c319593b..1079ce6899e 100644 --- a/src/core/lib/iomgr/wakeup_fd_posix.h +++ b/src/core/lib/iomgr/wakeup_fd_posix.h @@ -65,9 +65,9 @@ void grpc_enable_cv_wakeup_fds(int enable); typedef struct grpc_wakeup_fd grpc_wakeup_fd; typedef struct grpc_wakeup_fd_vtable { - grpc_error* (*init)(grpc_wakeup_fd* fd_info); - grpc_error* (*consume)(grpc_wakeup_fd* fd_info); - grpc_error* (*wakeup)(grpc_wakeup_fd* fd_info); + grpc_error_handle (*init)(grpc_wakeup_fd* fd_info); + grpc_error_handle (*consume)(grpc_wakeup_fd* fd_info); + grpc_error_handle (*wakeup)(grpc_wakeup_fd* fd_info); void (*destroy)(grpc_wakeup_fd* fd_info); /* Must be called before calling any other functions */ int (*check_availability)(void); @@ -83,10 +83,12 @@ extern int grpc_allow_pipe_wakeup_fd; #define GRPC_WAKEUP_FD_GET_READ_FD(fd_info) ((fd_info)->read_fd) -grpc_error* grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT; -grpc_error* grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info) +grpc_error_handle grpc_wakeup_fd_init(grpc_wakeup_fd* fd_info) + GRPC_MUST_USE_RESULT; +grpc_error_handle grpc_wakeup_fd_consume_wakeup(grpc_wakeup_fd* fd_info) + GRPC_MUST_USE_RESULT; +grpc_error_handle grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT; -grpc_error* grpc_wakeup_fd_wakeup(grpc_wakeup_fd* fd_info) GRPC_MUST_USE_RESULT; void grpc_wakeup_fd_destroy(grpc_wakeup_fd* fd_info); /* Defined in some specialized implementation's .c file, or by diff --git a/src/core/lib/iomgr/work_serializer.h b/src/core/lib/iomgr/work_serializer.h index 169562da82d..547b80c71d7 100644 --- a/src/core/lib/iomgr/work_serializer.h +++ b/src/core/lib/iomgr/work_serializer.h @@ -20,6 +20,8 @@ #include +#include "absl/synchronization/mutex.h" + #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/atomic.h" #include "src/core/lib/gprpp/debug_location.h" @@ -43,12 +45,26 @@ namespace grpc_core { // other callbacks from other threads might also be executed before Run() // returns. Since an arbitrary set of callbacks might be executed when Run() is // called, generally no locks should be held while calling Run(). -class WorkSerializer { +class ABSL_LOCKABLE WorkSerializer { public: WorkSerializer(); ~WorkSerializer(); + // Runs a given callback. + // + // If you want to use clang thread annotation to make sure that callback is + // called by WorkSerializer only, you need to add the annotation to both the + // lambda function given to Run and the actual callback function like; + // + // void run_callback() { + // work_serializer.Run( + // []() ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer) { + // callback(); + // }, DEBUG_LOCATION); + // } + // void callback() ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer) { ... } + // // TODO(yashkt): Replace grpc_core::DebugLocation with absl::SourceLocation // once we can start using it directly. void Run(std::function callback, diff --git a/src/core/lib/json/json.h b/src/core/lib/json/json.h index 9b3e0be7bfd..fc09d3a7255 100644 --- a/src/core/lib/json/json.h +++ b/src/core/lib/json/json.h @@ -56,7 +56,7 @@ class Json { using Array = std::vector; // Parses JSON string from json_str. On error, sets *error. - static Json Parse(absl::string_view json_str, grpc_error** error); + static Json Parse(absl::string_view json_str, grpc_error_handle* error); Json() = default; diff --git a/src/core/lib/json/json_reader.cc b/src/core/lib/json/json_reader.cc index d23112e48c0..2daeadf4613 100644 --- a/src/core/lib/json/json_reader.cc +++ b/src/core/lib/json/json_reader.cc @@ -38,7 +38,7 @@ namespace { class JsonReader { public: - static grpc_error* Parse(absl::string_view input, Json* output); + static grpc_error_handle Parse(absl::string_view input, Json* output); private: enum class Status { @@ -117,7 +117,7 @@ class JsonReader { bool container_just_begun_ = false; uint16_t unicode_char_ = 0; uint16_t unicode_high_surrogate_ = 0; - std::vector errors_; + std::vector errors_; bool truncated_errors_ = false; Json root_value_; @@ -821,7 +821,7 @@ JsonReader::Status JsonReader::Run() { GPR_UNREACHABLE_CODE(return Status::GRPC_JSON_INTERNAL_ERROR); } -grpc_error* JsonReader::Parse(absl::string_view input, Json* output) { +grpc_error_handle JsonReader::Parse(absl::string_view input, Json* output) { JsonReader reader(input); Status status = reader.Run(); if (reader.truncated_errors_) { @@ -849,7 +849,7 @@ grpc_error* JsonReader::Parse(absl::string_view input, Json* output) { } // namespace -Json Json::Parse(absl::string_view json_str, grpc_error** error) { +Json Json::Parse(absl::string_view json_str, grpc_error_handle* error) { Json value; *error = JsonReader::Parse(json_str, &value); return value; diff --git a/src/core/lib/matchers/matchers.cc b/src/core/lib/matchers/matchers.cc new file mode 100644 index 00000000000..489a4808004 --- /dev/null +++ b/src/core/lib/matchers/matchers.cc @@ -0,0 +1,339 @@ +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "src/core/lib/matchers/matchers.h" + +#include "absl/memory/memory.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" +#include "absl/strings/str_split.h" + +namespace grpc_core { + +// +// StringMatcher +// + +absl::StatusOr StringMatcher::Create(Type type, + absl::string_view matcher, + bool case_sensitive) { + if (type == Type::kSafeRegex) { + RE2::Options options; + options.set_case_sensitive(case_sensitive); + auto regex_matcher = absl::make_unique(std::string(matcher), options); + if (!regex_matcher->ok()) { + return absl::InvalidArgumentError( + "Invalid regex string specified in matcher."); + } + return StringMatcher(std::move(regex_matcher), case_sensitive); + } else { + return StringMatcher(type, matcher, case_sensitive); + } +} + +StringMatcher::StringMatcher(Type type, absl::string_view matcher, + bool case_sensitive) + : type_(type), string_matcher_(matcher), case_sensitive_(case_sensitive) {} + +StringMatcher::StringMatcher(std::unique_ptr regex_matcher, + bool case_sensitive) + : type_(Type::kSafeRegex), + regex_matcher_(std::move(regex_matcher)), + case_sensitive_(case_sensitive) {} + +StringMatcher::StringMatcher(const StringMatcher& other) + : type_(other.type_), case_sensitive_(other.case_sensitive_) { + if (type_ == Type::kSafeRegex) { + RE2::Options options; + options.set_case_sensitive(other.case_sensitive_); + regex_matcher_ = + absl::make_unique(other.regex_matcher_->pattern(), options); + } else { + string_matcher_ = other.string_matcher_; + } +} + +StringMatcher& StringMatcher::operator=(const StringMatcher& other) { + type_ = other.type_; + if (type_ == Type::kSafeRegex) { + RE2::Options options; + options.set_case_sensitive(other.case_sensitive_); + regex_matcher_ = + absl::make_unique(other.regex_matcher_->pattern(), options); + } else { + string_matcher_ = other.string_matcher_; + } + case_sensitive_ = other.case_sensitive_; + return *this; +} + +StringMatcher::StringMatcher(StringMatcher&& other) noexcept + : type_(other.type_), case_sensitive_(other.case_sensitive_) { + if (type_ == Type::kSafeRegex) { + regex_matcher_ = std::move(other.regex_matcher_); + } else { + string_matcher_ = std::move(other.string_matcher_); + } +} + +StringMatcher& StringMatcher::operator=(StringMatcher&& other) noexcept { + type_ = other.type_; + if (type_ == Type::kSafeRegex) { + regex_matcher_ = std::move(other.regex_matcher_); + } else { + string_matcher_ = std::move(other.string_matcher_); + } + case_sensitive_ = other.case_sensitive_; + return *this; +} + +bool StringMatcher::operator==(const StringMatcher& other) const { + if (type_ != other.type_ || case_sensitive_ != other.case_sensitive_) { + return false; + } + if (type_ == Type::kSafeRegex) { + return regex_matcher_->pattern() == other.regex_matcher_->pattern(); + } else { + return string_matcher_ == other.string_matcher_; + } +} + +bool StringMatcher::Match(absl::string_view value) const { + switch (type_) { + case Type::kExact: + return case_sensitive_ ? value == string_matcher_ + : absl::EqualsIgnoreCase(value, string_matcher_); + case StringMatcher::Type::kPrefix: + return case_sensitive_ + ? absl::StartsWith(value, string_matcher_) + : absl::StartsWithIgnoreCase(value, string_matcher_); + case StringMatcher::Type::kSuffix: + return case_sensitive_ ? absl::EndsWith(value, string_matcher_) + : absl::EndsWithIgnoreCase(value, string_matcher_); + case StringMatcher::Type::kContains: + return case_sensitive_ + ? absl::StrContains(value, string_matcher_) + : absl::StrContains(absl::AsciiStrToLower(value), + absl::AsciiStrToLower(string_matcher_)); + case StringMatcher::Type::kSafeRegex: + return RE2::FullMatch(std::string(value), *regex_matcher_); + default: + return false; + } +} + +std::string StringMatcher::ToString() const { + switch (type_) { + case Type::kExact: + return absl::StrFormat("StringMatcher{exact=%s%s}", string_matcher_, + case_sensitive_ ? "" : ", case_sensitive=false"); + case Type::kPrefix: + return absl::StrFormat("StringMatcher{prefix=%s%s}", string_matcher_, + case_sensitive_ ? "" : ", case_sensitive=false"); + case Type::kSuffix: + return absl::StrFormat("StringMatcher{suffix=%s%s}", string_matcher_, + case_sensitive_ ? "" : ", case_sensitive=false"); + case Type::kContains: + return absl::StrFormat("StringMatcher{contains=%s%s}", string_matcher_, + case_sensitive_ ? "" : ", case_sensitive=false"); + case Type::kSafeRegex: + return absl::StrFormat("StringMatcher{safe_regex=%s%s}", + regex_matcher_->pattern(), + case_sensitive_ ? "" : ", case_sensitive=false"); + default: + return ""; + } +} + +// +// HeaderMatcher +// + +absl::StatusOr HeaderMatcher::Create( + absl::string_view name, Type type, absl::string_view matcher, + int64_t range_start, int64_t range_end, bool present_match, + bool invert_match) { + if (static_cast(type) < 5) { + // Only for EXACT, PREFIX, SUFFIX, SAFE_REGEX and CONTAINS. + absl::StatusOr string_matcher = + StringMatcher::Create(static_cast(type), matcher, + /*case_sensitive=*/true); + if (!string_matcher.ok()) { + return string_matcher.status(); + } + return HeaderMatcher(name, type, std::move(string_matcher.value()), + invert_match); + } else if (type == Type::kRange) { + if (range_start > range_end) { + return absl::InvalidArgumentError( + "Invalid range specifier specified: end cannot be smaller than " + "start."); + } + return HeaderMatcher(name, range_start, range_end, invert_match); + } else { + return HeaderMatcher(name, present_match, invert_match); + } +} + +HeaderMatcher::HeaderMatcher(absl::string_view name, Type type, + StringMatcher string_matcher, bool invert_match) + : name_(name), + type_(type), + matcher_(std::move(string_matcher)), + invert_match_(invert_match) {} + +HeaderMatcher::HeaderMatcher(absl::string_view name, int64_t range_start, + int64_t range_end, bool invert_match) + : name_(name), + type_(Type::kRange), + range_start_(range_start), + range_end_(range_end), + invert_match_(invert_match) {} + +HeaderMatcher::HeaderMatcher(absl::string_view name, bool present_match, + bool invert_match) + : name_(name), + type_(Type::kPresent), + present_match_(present_match), + invert_match_(invert_match) {} + +HeaderMatcher::HeaderMatcher(const HeaderMatcher& other) + : name_(other.name_), + type_(other.type_), + invert_match_(other.invert_match_) { + switch (type_) { + case Type::kRange: + range_start_ = other.range_start_; + range_end_ = other.range_end_; + break; + case Type::kPresent: + present_match_ = other.present_match_; + break; + default: + matcher_ = other.matcher_; + } +} + +HeaderMatcher& HeaderMatcher::operator=(const HeaderMatcher& other) { + name_ = other.name_; + type_ = other.type_; + invert_match_ = other.invert_match_; + switch (type_) { + case Type::kRange: + range_start_ = other.range_start_; + range_end_ = other.range_end_; + break; + case Type::kPresent: + present_match_ = other.present_match_; + break; + default: + matcher_ = other.matcher_; + } + return *this; +} + +HeaderMatcher::HeaderMatcher(HeaderMatcher&& other) noexcept + : name_(std::move(other.name_)), + type_(other.type_), + invert_match_(other.invert_match_) { + switch (type_) { + case Type::kRange: + range_start_ = other.range_start_; + range_end_ = other.range_end_; + break; + case Type::kPresent: + present_match_ = other.present_match_; + break; + default: + matcher_ = std::move(other.matcher_); + } +} + +HeaderMatcher& HeaderMatcher::operator=(HeaderMatcher&& other) noexcept { + name_ = std::move(other.name_); + type_ = other.type_; + invert_match_ = other.invert_match_; + switch (type_) { + case Type::kRange: + range_start_ = other.range_start_; + range_end_ = other.range_end_; + break; + case Type::kPresent: + present_match_ = other.present_match_; + break; + default: + matcher_ = std::move(other.matcher_); + } + return *this; +} + +bool HeaderMatcher::operator==(const HeaderMatcher& other) const { + if (name_ != other.name_) return false; + if (type_ != other.type_) return false; + if (invert_match_ != other.invert_match_) return false; + switch (type_) { + case Type::kRange: + return range_start_ == other.range_start_ && + range_end_ == other.range_end_; + case Type::kPresent: + return present_match_ == other.present_match_; + default: + return matcher_ == other.matcher_; + } +} + +bool HeaderMatcher::Match( + const absl::optional& value) const { + bool match; + if (type_ == Type::kPresent) { + match = value.has_value() == present_match_; + } else if (!value.has_value()) { + // All other types fail to match if field is not present. + match = false; + } else if (type_ == Type::kRange) { + int64_t int_value; + match = absl::SimpleAtoi(value.value(), &int_value) && + int_value >= range_start_ && int_value < range_end_; + } else { + match = matcher_.Match(value.value()); + } + return match != invert_match_; +} + +std::string HeaderMatcher::ToString() const { + switch (type_) { + case Type::kRange: + return absl::StrFormat("HeaderMatcher{%s %srange=[%d, %d]}", name_, + invert_match_ ? "not " : "", range_start_, + range_end_); + case Type::kPresent: + return absl::StrFormat("HeaderMatcher{%s %spresent=%s}", name_, + invert_match_ ? "not " : "", + present_match_ ? "true" : "false"); + case Type::kExact: + case Type::kPrefix: + case Type::kSuffix: + case Type::kSafeRegex: + case Type::kContains: + return absl::StrFormat("HeaderMatcher{%s %s%s}", name_, + invert_match_ ? "not " : "", matcher_.ToString()); + default: + return ""; + } +} + +} // namespace grpc_core diff --git a/src/core/lib/matchers/matchers.h b/src/core/lib/matchers/matchers.h new file mode 100644 index 00000000000..af2ce59bf18 --- /dev/null +++ b/src/core/lib/matchers/matchers.h @@ -0,0 +1,160 @@ +// Copyright 2021 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_MATCHERS_MATCHERS_H +#define GRPC_CORE_LIB_MATCHERS_MATCHERS_H + +#include + +#include +#include + +#include "absl/status/statusor.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" + +#include "re2/re2.h" + +namespace grpc_core { + +class StringMatcher { + public: + enum class Type { + kExact, // value stored in string_matcher_ field + kPrefix, // value stored in string_matcher_ field + kSuffix, // value stored in string_matcher_ field + kSafeRegex, // pattern stored in regex_matcher_ field + kContains, // value stored in string_matcher_ field + }; + + // Creates StringMatcher instance. Returns error status on failure. + static absl::StatusOr Create(Type type, + absl::string_view matcher, + bool case_sensitive = true); + + StringMatcher() = default; + StringMatcher(const StringMatcher& other); + StringMatcher& operator=(const StringMatcher& other); + StringMatcher(StringMatcher&& other) noexcept; + StringMatcher& operator=(StringMatcher&& other) noexcept; + bool operator==(const StringMatcher& other) const; + + bool Match(absl::string_view value) const; + + std::string ToString() const; + + Type type() const { return type_; } + + // Valid for kExact, kPrefix, kSuffix and kContains. + const std::string& string_matcher() const { return string_matcher_; } + + // Valid for kSafeRegex. + RE2* regex_matcher() const { return regex_matcher_.get(); } + + bool case_sensitive() const { return case_sensitive_; } + + private: + StringMatcher(Type type, absl::string_view matcher, bool case_sensitive); + StringMatcher(std::unique_ptr regex_matcher, bool case_sensitive); + + Type type_ = Type::kExact; + std::string string_matcher_; + std::unique_ptr regex_matcher_; + bool case_sensitive_ = true; +}; + +class HeaderMatcher { + public: + enum class Type { + kExact, // value stored in StringMatcher field + kPrefix, // value stored in StringMatcher field + kSuffix, // value stored in StringMatcher field + kSafeRegex, // value stored in StringMatcher field + kContains, // value stored in StringMatcher field + kRange, // uses range_start and range_end fields + kPresent, // uses present_match field + }; + + // Make sure that the first five HeaderMatcher::Type enum values match up to + // the corresponding StringMatcher::Type enum values, so that it's safe to + // convert by casting when delegating to StringMatcher. + static_assert(static_cast(Type::kExact) == + StringMatcher::Type::kExact, + ""); + static_assert(static_cast(Type::kPrefix) == + StringMatcher::Type::kPrefix, + ""); + static_assert(static_cast(Type::kSuffix) == + StringMatcher::Type::kSuffix, + ""); + static_assert(static_cast(Type::kSafeRegex) == + StringMatcher::Type::kSafeRegex, + ""); + static_assert(static_cast(Type::kContains) == + StringMatcher::Type::kContains, + ""); + + // Creates HeaderMatcher instance. Returns error status on failure. + static absl::StatusOr Create(absl::string_view name, Type type, + absl::string_view matcher, + int64_t range_start = 0, + int64_t range_end = 0, + bool present_match = false, + bool invert_match = false); + + HeaderMatcher() = default; + HeaderMatcher(const HeaderMatcher& other); + HeaderMatcher& operator=(const HeaderMatcher& other); + HeaderMatcher(HeaderMatcher&& other) noexcept; + HeaderMatcher& operator=(HeaderMatcher&& other) noexcept; + bool operator==(const HeaderMatcher& other) const; + + const std::string& name() const { return name_; } + + Type type() const { return type_; } + + // Valid for kExact, kPrefix, kSuffix and kContains. + const std::string& string_matcher() const { + return matcher_.string_matcher(); + } + + // Valid for kSafeRegex. + RE2* regex_matcher() const { return matcher_.regex_matcher(); } + + bool Match(const absl::optional& value) const; + + std::string ToString() const; + + private: + // For StringMatcher. + HeaderMatcher(absl::string_view name, Type type, StringMatcher matcher, + bool invert_match); + // For RangeMatcher. + HeaderMatcher(absl::string_view name, int64_t range_start, int64_t range_end, + bool invert_match); + // For PresentMatcher. + HeaderMatcher(absl::string_view name, bool present_match, bool invert_match); + + std::string name_; + Type type_ = Type::kExact; + StringMatcher matcher_; + int64_t range_start_; + int64_t range_end_; + bool present_match_; + bool invert_match_ = false; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_MATCHERS_MATCHERS_H */ diff --git a/src/core/lib/security/authorization/authorization_engine.h b/src/core/lib/security/authorization/authorization_engine.h index 809784c334e..7889e62dc6f 100644 --- a/src/core/lib/security/authorization/authorization_engine.h +++ b/src/core/lib/security/authorization/authorization_engine.h @@ -1,5 +1,4 @@ - -// Copyright 2020 gRPC authors. +// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,67 +17,28 @@ #include -#include -#include -#include #include -#include - -#include "absl/container/flat_hash_set.h" -#include "envoy/config/rbac/v3/rbac.upb.h" -#include "google/api/expr/v1alpha1/syntax.upb.h" -#include "upb/upb.hpp" #include "src/core/lib/security/authorization/evaluate_args.h" -#include "src/core/lib/security/authorization/mock_cel/activation.h" namespace grpc_core { -// AuthorizationEngine makes an AuthorizationDecision to ALLOW or DENY the -// current action based on the condition fields in provided RBAC policies. -// The engine may be constructed with one or two policies. If two polcies, -// the first policy is deny-if-matched and the second is allow-if-matched. -// The engine returns UNDECIDED decision if it fails to find a match in any -// policy. This engine ignores the principal and permission fields in RBAC -// policies. It is the caller's responsibility to provide RBAC policies that -// are compatible with this engine. -// -// Example: -// AuthorizationEngine* -// auth_engine = AuthorizationEngine::CreateAuthorizationEngine(rbac_policies); -// auth_engine->Evaluate(evaluate_args); // returns authorization decision. +// Interface for gRPC Authorization Engine. class AuthorizationEngine { public: - // rbac_policies must be a vector containing either a single policy of any - // kind, or one deny policy and one allow policy, in that order. - static std::unique_ptr CreateAuthorizationEngine( - const std::vector& rbac_policies); - - // Users should use the CreateAuthorizationEngine factory function - // instead of calling the AuthorizationEngine constructor directly. - explicit AuthorizationEngine( - const std::vector& rbac_policies); - // TODO(mywang@google.com): add an Evaluate member function. - - private: - enum Action { - kAllow, - kDeny, + struct Decision { + enum class Type { + kAllow, + kDeny, + }; + Type type; + std::string matching_policy_name; }; - std::unique_ptr CreateActivation( - const EvaluateArgs& args); - - std::map - deny_if_matched_; - std::map - allow_if_matched_; - upb::Arena arena_; - absl::flat_hash_set envoy_attributes_; - absl::flat_hash_set header_keys_; - std::unique_ptr headers_; + virtual ~AuthorizationEngine() = default; + virtual Decision Evaluate(const EvaluateArgs& args) const = 0; }; } // namespace grpc_core -#endif /* GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_ENGINE_H */ +#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_AUTHORIZATION_ENGINE_H diff --git a/src/core/lib/security/authorization/authorization_engine.cc b/src/core/lib/security/authorization/cel_authorization_engine.cc similarity index 94% rename from src/core/lib/security/authorization/authorization_engine.cc rename to src/core/lib/security/authorization/cel_authorization_engine.cc index 8e6a63dc21b..844d9fb512c 100644 --- a/src/core/lib/security/authorization/authorization_engine.cc +++ b/src/core/lib/security/authorization/cel_authorization_engine.cc @@ -16,7 +16,7 @@ #include "absl/memory/memory.h" -#include "src/core/lib/security/authorization/authorization_engine.h" +#include "src/core/lib/security/authorization/cel_authorization_engine.h" namespace grpc_core { @@ -36,8 +36,8 @@ constexpr char kCertServerName[] = "cert_server_name"; } // namespace -std::unique_ptr -AuthorizationEngine::CreateAuthorizationEngine( +std::unique_ptr +CelAuthorizationEngine::CreateCelAuthorizationEngine( const std::vector& rbac_policies) { if (rbac_policies.empty() || rbac_policies.size() > 2) { gpr_log(GPR_ERROR, @@ -52,11 +52,11 @@ AuthorizationEngine::CreateAuthorizationEngine( policy and one allow policy, in that order."); return nullptr; } else { - return absl::make_unique(rbac_policies); + return absl::make_unique(rbac_policies); } } -AuthorizationEngine::AuthorizationEngine( +CelAuthorizationEngine::CelAuthorizationEngine( const std::vector& rbac_policies) { for (const auto& rbac_policy : rbac_policies) { // Extract array of policies and store their condition fields in either @@ -90,7 +90,7 @@ AuthorizationEngine::AuthorizationEngine( } } -std::unique_ptr AuthorizationEngine::CreateActivation( +std::unique_ptr CelAuthorizationEngine::CreateActivation( const EvaluateArgs& args) { std::unique_ptr activation; for (const auto& elem : envoy_attributes_) { @@ -158,7 +158,7 @@ std::unique_ptr AuthorizationEngine::CreateActivation( kSpiffeId, mock_cel::CelValue::CreateStringView(spiffe_id)); } } else if (elem == kCertServerName) { - absl::string_view cert_server_name(args.GetCertServerName()); + absl::string_view cert_server_name(args.GetCommonName()); if (!cert_server_name.empty()) { activation->InsertValue( kCertServerName, diff --git a/src/core/lib/security/authorization/cel_authorization_engine.h b/src/core/lib/security/authorization/cel_authorization_engine.h new file mode 100644 index 00000000000..6f37bfbe8ff --- /dev/null +++ b/src/core/lib/security/authorization/cel_authorization_engine.h @@ -0,0 +1,84 @@ + +// 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_AUTHORIZATION_CEL_AUTHORIZATION_ENGINE_H +#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_CEL_AUTHORIZATION_ENGINE_H + +#include + +#include +#include +#include +#include +#include + +#include "absl/container/flat_hash_set.h" +#include "envoy/config/rbac/v3/rbac.upb.h" +#include "google/api/expr/v1alpha1/syntax.upb.h" +#include "upb/upb.hpp" + +#include "src/core/lib/security/authorization/evaluate_args.h" +#include "src/core/lib/security/authorization/mock_cel/activation.h" + +namespace grpc_core { + +// CelAuthorizationEngine makes an AuthorizationDecision to ALLOW or DENY the +// current action based on the condition fields in provided RBAC policies. +// The engine may be constructed with one or two policies. If two polcies, +// the first policy is deny-if-matched and the second is allow-if-matched. +// The engine returns UNDECIDED decision if it fails to find a match in any +// policy. This engine ignores the principal and permission fields in RBAC +// policies. It is the caller's responsibility to provide RBAC policies that +// are compatible with this engine. +// +// Example: +// CelAuthorizationEngine* engine = +// CelAuthorizationEngine::CreateCelAuthorizationEngine(rbac_policies); +// engine->Evaluate(evaluate_args); // returns authorization decision. +class CelAuthorizationEngine { + public: + // rbac_policies must be a vector containing either a single policy of any + // kind, or one deny policy and one allow policy, in that order. + static std::unique_ptr CreateCelAuthorizationEngine( + const std::vector& rbac_policies); + + // Users should use the CreateCelAuthorizationEngine factory function + // instead of calling the CelAuthorizationEngine constructor directly. + explicit CelAuthorizationEngine( + const std::vector& rbac_policies); + // TODO(mywang@google.com): add an Evaluate member function. + + private: + enum Action { + kAllow, + kDeny, + }; + + std::unique_ptr CreateActivation( + const EvaluateArgs& args); + + std::map + deny_if_matched_; + std::map + allow_if_matched_; + upb::Arena arena_; + absl::flat_hash_set envoy_attributes_; + absl::flat_hash_set header_keys_; + std::unique_ptr headers_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SECURITY_AUTHORIZATION_CEL_AUTHORIZATION_ENGINE_H */ diff --git a/src/core/lib/security/authorization/evaluate_args.cc b/src/core/lib/security/authorization/evaluate_args.cc index 4f92549a660..12144dfbde3 100644 --- a/src/core/lib/security/authorization/evaluate_args.cc +++ b/src/core/lib/security/authorization/evaluate_args.cc @@ -1,6 +1,4 @@ -// -// -// Copyright 2020 gRPC authors. +// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,22 +11,76 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// #include #include "src/core/lib/security/authorization/evaluate_args.h" -#include "absl/strings/str_join.h" - -#include "src/core/lib/iomgr/parse_address.h" -#include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/slice/slice_utils.h" namespace grpc_core { +namespace { + +absl::string_view GetAuthPropertyValue(grpc_auth_context* context, + const char* property_name) { + grpc_auth_property_iterator it = + grpc_auth_context_find_properties_by_name(context, property_name); + const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it); + if (prop == nullptr) { + gpr_log(GPR_DEBUG, "No value found for %s property.", property_name); + return ""; + } + if (grpc_auth_property_iterator_next(&it) != nullptr) { + gpr_log(GPR_DEBUG, "Multiple values found for %s property.", property_name); + return ""; + } + return absl::string_view(prop->value, prop->value_length); +} + +void ParseEndpointUri(absl::string_view uri_text, std::string* address, + int* port) { + absl::StatusOr uri = URI::Parse(uri_text); + if (!uri.ok()) { + gpr_log(GPR_DEBUG, "Failed to parse uri."); + return; + } + absl::string_view host_view; + absl::string_view port_view; + if (!SplitHostPort(uri->path(), &host_view, &port_view)) { + gpr_log(GPR_DEBUG, "Failed to split %s into host and port.", + uri->path().c_str()); + return; + } + *address = std::string(host_view); + if (!absl::SimpleAtoi(port_view, port)) { + gpr_log(GPR_DEBUG, "Port %s is out of range or null.", + std::string(port_view).c_str()); + } +} + +} // namespace + +EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context, + grpc_endpoint* endpoint) { + if (auth_context != nullptr) { + transport_security_type = GetAuthPropertyValue( + auth_context, GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME); + spiffe_id = + GetAuthPropertyValue(auth_context, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME); + common_name = + GetAuthPropertyValue(auth_context, GRPC_X509_CN_PROPERTY_NAME); + } + if (endpoint != nullptr) { + ParseEndpointUri(grpc_endpoint_get_local_address(endpoint), &local_address, + &local_port); + ParseEndpointUri(grpc_endpoint_get_peer(endpoint), &peer_address, + &peer_port); + } +} + absl::string_view EvaluateArgs::GetPath() const { absl::string_view path; if (metadata_ != nullptr && metadata_->idx.named.path != nullptr) { @@ -83,76 +135,52 @@ absl::optional EvaluateArgs::GetHeaderValue( } absl::string_view EvaluateArgs::GetLocalAddress() const { - absl::string_view addr = grpc_endpoint_get_local_address(endpoint_); - size_t first_colon = addr.find(":"); - size_t last_colon = addr.rfind(":"); - if (first_colon == std::string::npos || last_colon == std::string::npos) { + if (channel_args_ == nullptr) { return ""; - } else { - return addr.substr(first_colon + 1, last_colon - first_colon - 1); } + return channel_args_->local_address; } int EvaluateArgs::GetLocalPort() const { - if (endpoint_ == nullptr) { + if (channel_args_ == nullptr) { return 0; } - absl::StatusOr uri = - URI::Parse(grpc_endpoint_get_local_address(endpoint_)); - grpc_resolved_address resolved_addr; - if (!uri.ok() || !grpc_parse_uri(*uri, &resolved_addr)) { - return 0; - } - return grpc_sockaddr_get_port(&resolved_addr); + return channel_args_->local_port; } absl::string_view EvaluateArgs::GetPeerAddress() const { - absl::string_view addr = grpc_endpoint_get_peer(endpoint_); - size_t first_colon = addr.find(":"); - size_t last_colon = addr.rfind(":"); - if (first_colon == std::string::npos || last_colon == std::string::npos) { + if (channel_args_ == nullptr) { return ""; - } else { - return addr.substr(first_colon + 1, last_colon - first_colon - 1); } + return channel_args_->peer_address; } int EvaluateArgs::GetPeerPort() const { - if (endpoint_ == nullptr) { - return 0; - } - absl::StatusOr uri = URI::Parse(grpc_endpoint_get_peer(endpoint_)); - grpc_resolved_address resolved_addr; - if (!uri.ok() || !grpc_parse_uri(*uri, &resolved_addr)) { + if (channel_args_ == nullptr) { return 0; } - return grpc_sockaddr_get_port(&resolved_addr); + return channel_args_->peer_port; } -absl::string_view EvaluateArgs::GetSpiffeId() const { - if (auth_context_ == nullptr) { +absl::string_view EvaluateArgs::GetTransportSecurityType() const { + if (channel_args_ == nullptr) { return ""; } - grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( - auth_context_, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME); - const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it); - if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr) { - return ""; - } - return absl::string_view(prop->value, prop->value_length); + return channel_args_->transport_security_type; } -absl::string_view EvaluateArgs::GetCertServerName() const { - if (auth_context_ == nullptr) { +absl::string_view EvaluateArgs::GetSpiffeId() const { + if (channel_args_ == nullptr) { return ""; } - grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( - auth_context_, GRPC_X509_CN_PROPERTY_NAME); - const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it); - if (prop == nullptr || grpc_auth_property_iterator_next(&it) != nullptr) { + return channel_args_->spiffe_id; +} + +absl::string_view EvaluateArgs::GetCommonName() const { + if (channel_args_ == nullptr) { return ""; } - return absl::string_view(prop->value, prop->value_length); + return channel_args_->common_name; } } // namespace grpc_core diff --git a/src/core/lib/security/authorization/evaluate_args.h b/src/core/lib/security/authorization/evaluate_args.h index d2803705d03..b3ac93caa4e 100644 --- a/src/core/lib/security/authorization/evaluate_args.h +++ b/src/core/lib/security/authorization/evaluate_args.h @@ -1,6 +1,4 @@ -// -// -// Copyright 2020 gRPC authors. +// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,8 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// -// #ifndef GRPC_CORE_LIB_SECURITY_AUTHORIZATION_EVALUATE_ARGS_H #define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_EVALUATE_ARGS_H @@ -33,9 +29,22 @@ namespace grpc_core { class EvaluateArgs { public: - EvaluateArgs(grpc_metadata_batch* metadata, grpc_auth_context* auth_context, - grpc_endpoint* endpoint) - : metadata_(metadata), auth_context_(auth_context), endpoint_(endpoint) {} + // Caller is responsible for ensuring auth_context outlives PerChannelArgs + // struct. + struct PerChannelArgs { + PerChannelArgs(grpc_auth_context* auth_context, grpc_endpoint* endpoint); + + absl::string_view transport_security_type; + absl::string_view spiffe_id; + absl::string_view common_name; + std::string local_address; + int local_port = 0; + std::string peer_address; + int peer_port = 0; + }; + + EvaluateArgs(grpc_metadata_batch* metadata, PerChannelArgs* channel_args) + : metadata_(metadata), channel_args_(channel_args) {} absl::string_view GetPath() const; absl::string_view GetHost() const; @@ -50,19 +59,18 @@ class EvaluateArgs { // string_view of that string. absl::optional GetHeaderValue( absl::string_view key, std::string* concatenated_value) const; + absl::string_view GetLocalAddress() const; int GetLocalPort() const; absl::string_view GetPeerAddress() const; int GetPeerPort() const; + absl::string_view GetTransportSecurityType() const; absl::string_view GetSpiffeId() const; - absl::string_view GetCertServerName() const; - - // TODO(unknown): Add a getter function for source.principal + absl::string_view GetCommonName() const; private: grpc_metadata_batch* metadata_; - grpc_auth_context* auth_context_; - grpc_endpoint* endpoint_; + PerChannelArgs* channel_args_; }; } // namespace grpc_core diff --git a/src/core/lib/security/authorization/grpc_authorization_engine.cc b/src/core/lib/security/authorization/grpc_authorization_engine.cc new file mode 100644 index 00000000000..34fc97675ef --- /dev/null +++ b/src/core/lib/security/authorization/grpc_authorization_engine.cc @@ -0,0 +1,49 @@ +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "src/core/lib/security/authorization/grpc_authorization_engine.h" + +namespace grpc_core { + +GrpcAuthorizationEngine::GrpcAuthorizationEngine(Rbac policy) + : action_(policy.action) { + for (auto& sub_policy : policy.policies) { + Policy policy; + policy.name = sub_policy.first; + policy.matcher = absl::make_unique( + std::move(sub_policy.second)); + policies_.push_back(std::move(policy)); + } +} + +AuthorizationEngine::Decision GrpcAuthorizationEngine::Evaluate( + const EvaluateArgs& args) const { + Decision decision; + bool matches = false; + for (const auto& policy : policies_) { + if (policy.matcher->Matches(args)) { + matches = true; + decision.matching_policy_name = policy.name; + break; + } + } + decision.type = (matches == (action_ == Rbac::Action::kAllow)) + ? Decision::Type::kAllow + : Decision::Type::kDeny; + return decision; +} + +} // namespace grpc_core diff --git a/src/core/lib/security/authorization/grpc_authorization_engine.h b/src/core/lib/security/authorization/grpc_authorization_engine.h new file mode 100644 index 00000000000..5b7791ac31c --- /dev/null +++ b/src/core/lib/security/authorization/grpc_authorization_engine.h @@ -0,0 +1,55 @@ +// Copyright 2021 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_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H +#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H + +#include + +#include "src/core/lib/security/authorization/authorization_engine.h" +#include "src/core/lib/security/authorization/matchers.h" +#include "src/core/lib/security/authorization/rbac_policy.h" + +namespace grpc_core { + +// GrpcAuthorizationEngine can be either an Allow engine or Deny engine. This +// engine makes authorization decisions to Allow or Deny incoming RPC request +// based on permission and principal configs in the provided RBAC policy and the +// engine type. This engine ignores condition field in RBAC config. It is the +// caller's responsibility to provide RBAC policies that are compatible with +// this engine. +class GrpcAuthorizationEngine : public AuthorizationEngine { + public: + // Builds GrpcAuthorizationEngine without any policies. + explicit GrpcAuthorizationEngine(Rbac::Action action) : action_(action) {} + // Builds GrpcAuthorizationEngine with allow/deny RBAC policy. + explicit GrpcAuthorizationEngine(Rbac policy); + + // Evaluates incoming request against RBAC policy and makes a decision to + // whether allow/deny this request. + Decision Evaluate(const EvaluateArgs& args) const override; + + private: + struct Policy { + std::string name; + std::unique_ptr matcher; + }; + + Rbac::Action action_; + std::vector policies_; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H diff --git a/src/core/lib/security/authorization/matchers.cc b/src/core/lib/security/authorization/matchers.cc index 24b342d8f18..5613b748ebd 100644 --- a/src/core/lib/security/authorization/matchers.cc +++ b/src/core/lib/security/authorization/matchers.cc @@ -16,324 +16,187 @@ #include "src/core/lib/security/authorization/matchers.h" -#include "absl/memory/memory.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/str_format.h" -#include "absl/strings/str_join.h" -#include "absl/strings/str_split.h" - namespace grpc_core { -// -// StringMatcher -// - -absl::StatusOr StringMatcher::Create(Type type, - const std::string& matcher, - bool case_sensitive) { - if (type == Type::SAFE_REGEX) { - RE2::Options options; - options.set_case_sensitive(case_sensitive); - auto regex_matcher = absl::make_unique(matcher, options); - if (!regex_matcher->ok()) { - return absl::InvalidArgumentError( - "Invalid regex string specified in matcher."); - } - return StringMatcher(std::move(regex_matcher), case_sensitive); - } else { - return StringMatcher(type, matcher, case_sensitive); - } -} - -StringMatcher::StringMatcher(Type type, const std::string& matcher, - bool case_sensitive) - : type_(type), string_matcher_(matcher), case_sensitive_(case_sensitive) {} - -StringMatcher::StringMatcher(std::unique_ptr regex_matcher, - bool case_sensitive) - : type_(Type::SAFE_REGEX), - regex_matcher_(std::move(regex_matcher)), - case_sensitive_(case_sensitive) {} - -StringMatcher::StringMatcher(const StringMatcher& other) - : type_(other.type_), case_sensitive_(other.case_sensitive_) { - if (type_ == Type::SAFE_REGEX) { - RE2::Options options; - options.set_case_sensitive(other.case_sensitive_); - regex_matcher_ = - absl::make_unique(other.regex_matcher_->pattern(), options); - } else { - string_matcher_ = other.string_matcher_; - } -} +namespace { -StringMatcher& StringMatcher::operator=(const StringMatcher& other) { - type_ = other.type_; - if (type_ == Type::SAFE_REGEX) { - RE2::Options options; - options.set_case_sensitive(other.case_sensitive_); - regex_matcher_ = - absl::make_unique(other.regex_matcher_->pattern(), options); - } else { - string_matcher_ = other.string_matcher_; - } - case_sensitive_ = other.case_sensitive_; - return *this; -} - -StringMatcher::StringMatcher(StringMatcher&& other) noexcept - : type_(other.type_), case_sensitive_(other.case_sensitive_) { - if (type_ == Type::SAFE_REGEX) { - regex_matcher_ = std::move(other.regex_matcher_); - } else { - string_matcher_ = std::move(other.string_matcher_); - } -} - -StringMatcher& StringMatcher::operator=(StringMatcher&& other) noexcept { - type_ = other.type_; - if (type_ == Type::SAFE_REGEX) { - regex_matcher_ = std::move(other.regex_matcher_); - } else { - string_matcher_ = std::move(other.string_matcher_); - } - case_sensitive_ = other.case_sensitive_; - return *this; -} - -bool StringMatcher::operator==(const StringMatcher& other) const { - if (type_ != other.type_ || case_sensitive_ != other.case_sensitive_) { +bool AuthenticatedMatchesHelper(const EvaluateArgs& args, + const StringMatcher& matcher) { + if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE) { + // Connection is not authenticated. return false; } - if (type_ == Type::SAFE_REGEX) { - return regex_matcher_->pattern() == other.regex_matcher_->pattern(); - } else { - return string_matcher_ == other.string_matcher_; + if (matcher.string_matcher().empty()) { + // Allows any authenticated user. + return true; + } + absl::string_view spiffe_id = args.GetSpiffeId(); + if (!spiffe_id.empty()) { + return matcher.Match(spiffe_id); + } + // TODO(ashithasantosh): Check principal matches DNS SAN, followed by Subject + // field from certificate. This requires updating tsi_peer to expose these + // fields. + return false; +} + +} // namespace + +std::unique_ptr AuthorizationMatcher::Create( + Rbac::Permission permission) { + switch (permission.type) { + case Rbac::Permission::RuleType::kAnd: + return absl::make_unique( + std::move(permission.permissions), permission.not_rule); + case Rbac::Permission::RuleType::kOr: + return absl::make_unique( + std::move(permission.permissions), permission.not_rule); + case Rbac::Permission::RuleType::kAny: + return absl::make_unique(permission.not_rule); + case Rbac::Permission::RuleType::kHeader: + return absl::make_unique( + std::move(permission.header_matcher), permission.not_rule); + case Rbac::Permission::RuleType::kPath: + return absl::make_unique( + std::move(permission.string_matcher), permission.not_rule); + case Rbac::Permission::RuleType::kDestIp: + return absl::make_unique(std::move(permission.ip), + permission.not_rule); + case Rbac::Permission::RuleType::kDestPort: + return absl::make_unique(permission.port, + permission.not_rule); + case Rbac::Permission::RuleType::kReqServerName: + return absl::make_unique( + std::move(permission.string_matcher), permission.not_rule); + } + return nullptr; +} + +std::unique_ptr AuthorizationMatcher::Create( + Rbac::Principal principal) { + switch (principal.type) { + case Rbac::Principal::RuleType::kAnd: + return absl::make_unique( + std::move(principal.principals), principal.not_rule); + case Rbac::Principal::RuleType::kOr: + return absl::make_unique( + std::move(principal.principals), principal.not_rule); + case Rbac::Principal::RuleType::kAny: + return absl::make_unique(principal.not_rule); + case Rbac::Principal::RuleType::kPrincipalName: + return absl::make_unique( + std::move(principal.string_matcher), principal.not_rule); + case Rbac::Principal::RuleType::kSourceIp: + case Rbac::Principal::RuleType::kDirectRemoteIp: + case Rbac::Principal::RuleType::kRemoteIp: + return absl::make_unique(std::move(principal.ip), + principal.not_rule); + case Rbac::Principal::RuleType::kHeader: + return absl::make_unique( + std::move(principal.header_matcher), principal.not_rule); + case Rbac::Principal::RuleType::kPath: + return absl::make_unique( + std::move(principal.string_matcher), principal.not_rule); + } + return nullptr; +} + +AndAuthorizationMatcher::AndAuthorizationMatcher( + std::vector> rules, bool not_rule) + : not_rule_(not_rule) { + for (auto& rule : rules) { + matchers_.push_back(AuthorizationMatcher::Create(std::move(*rule))); + } +} + +AndAuthorizationMatcher::AndAuthorizationMatcher( + std::vector> ids, bool not_rule) + : not_rule_(not_rule) { + for (const auto& id : ids) { + matchers_.push_back(AuthorizationMatcher::Create(std::move(*id))); + } +} + +bool AndAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + bool matches = true; + for (const auto& matcher : matchers_) { + if (!matcher->Matches(args)) { + matches = false; + break; + } } + return matches != not_rule_; } -bool StringMatcher::Match(absl::string_view value) const { - switch (type_) { - case Type::EXACT: - return case_sensitive_ ? value == string_matcher_ - : absl::EqualsIgnoreCase(value, string_matcher_); - case StringMatcher::Type::PREFIX: - return case_sensitive_ - ? absl::StartsWith(value, string_matcher_) - : absl::StartsWithIgnoreCase(value, string_matcher_); - case StringMatcher::Type::SUFFIX: - return case_sensitive_ ? absl::EndsWith(value, string_matcher_) - : absl::EndsWithIgnoreCase(value, string_matcher_); - case StringMatcher::Type::CONTAINS: - return case_sensitive_ - ? absl::StrContains(value, string_matcher_) - : absl::StrContains(absl::AsciiStrToLower(value), - absl::AsciiStrToLower(string_matcher_)); - case StringMatcher::Type::SAFE_REGEX: - return RE2::FullMatch(std::string(value), *regex_matcher_); - default: - return false; +OrAuthorizationMatcher::OrAuthorizationMatcher( + std::vector> rules, bool not_rule) + : not_rule_(not_rule) { + for (const auto& rule : rules) { + matchers_.push_back(AuthorizationMatcher::Create(std::move(*rule))); } } -std::string StringMatcher::ToString() const { - switch (type_) { - case Type::EXACT: - return absl::StrFormat("StringMatcher{exact=%s%s}", string_matcher_, - case_sensitive_ ? "" : ", case_sensitive=false"); - case Type::PREFIX: - return absl::StrFormat("StringMatcher{prefix=%s%s}", string_matcher_, - case_sensitive_ ? "" : ", case_sensitive=false"); - case Type::SUFFIX: - return absl::StrFormat("StringMatcher{suffix=%s%s}", string_matcher_, - case_sensitive_ ? "" : ", case_sensitive=false"); - case Type::CONTAINS: - return absl::StrFormat("StringMatcher{contains=%s%s}", string_matcher_, - case_sensitive_ ? "" : ", case_sensitive=false"); - case Type::SAFE_REGEX: - return absl::StrFormat("StringMatcher{safe_regex=%s%s}", - regex_matcher_->pattern(), - case_sensitive_ ? "" : ", case_sensitive=false"); - default: - return ""; +OrAuthorizationMatcher::OrAuthorizationMatcher( + std::vector> ids, bool not_rule) + : not_rule_(not_rule) { + for (const auto& id : ids) { + matchers_.push_back(AuthorizationMatcher::Create(std::move(*id))); } } -// -// HeaderMatcher -// - -absl::StatusOr HeaderMatcher::Create( - const std::string& name, Type type, const std::string& matcher, - int64_t range_start, int64_t range_end, bool present_match, - bool invert_match) { - if (static_cast(type) < 5) { - // Only for EXACT, PREFIX, SUFFIX, SAFE_REGEX and CONTAINS. - absl::StatusOr string_matcher = - StringMatcher::Create(static_cast(type), matcher, - /*case_sensitive=*/true); - if (!string_matcher.ok()) { - return string_matcher.status(); - } - return HeaderMatcher(name, type, std::move(string_matcher.value()), - invert_match); - } else if (type == Type::RANGE) { - if (range_start > range_end) { - return absl::InvalidArgumentError( - "Invalid range specifier specified: end cannot be smaller than " - "start."); +bool OrAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + bool matches = false; + for (const auto& matcher : matchers_) { + if (matcher->Matches(args)) { + matches = true; + break; } - return HeaderMatcher(name, range_start, range_end, invert_match); - } else { - return HeaderMatcher(name, present_match, invert_match); } + return matches != not_rule_; } -HeaderMatcher::HeaderMatcher(const std::string& name, Type type, - StringMatcher string_matcher, bool invert_match) - : name_(name), - type_(type), - matcher_(std::move(string_matcher)), - invert_match_(invert_match) {} - -HeaderMatcher::HeaderMatcher(const std::string& name, int64_t range_start, - int64_t range_end, bool invert_match) - : name_(name), - type_(Type::RANGE), - range_start_(range_start), - range_end_(range_end), - invert_match_(invert_match) {} - -HeaderMatcher::HeaderMatcher(const std::string& name, bool present_match, - bool invert_match) - : name_(name), - type_(Type::PRESENT), - present_match_(present_match), - invert_match_(invert_match) {} - -HeaderMatcher::HeaderMatcher(const HeaderMatcher& other) - : name_(other.name_), - type_(other.type_), - invert_match_(other.invert_match_) { - switch (type_) { - case Type::RANGE: - range_start_ = other.range_start_; - range_end_ = other.range_end_; - break; - case Type::PRESENT: - present_match_ = other.present_match_; - break; - default: - matcher_ = other.matcher_; - } +bool HeaderAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + std::string concatenated_value; + bool matches = + matcher_.Match(args.GetHeaderValue(matcher_.name(), &concatenated_value)); + return matches != not_rule_; } -HeaderMatcher& HeaderMatcher::operator=(const HeaderMatcher& other) { - name_ = other.name_; - type_ = other.type_; - invert_match_ = other.invert_match_; - switch (type_) { - case Type::RANGE: - range_start_ = other.range_start_; - range_end_ = other.range_end_; - break; - case Type::PRESENT: - present_match_ = other.present_match_; - break; - default: - matcher_ = other.matcher_; - } - return *this; +// TODO(ashithasantosh): Implement IpAuthorizationMatcher::Matches. +bool IpAuthorizationMatcher::Matches(const EvaluateArgs&) const { + bool matches = false; + return matches != not_rule_; } -HeaderMatcher::HeaderMatcher(HeaderMatcher&& other) noexcept - : name_(std::move(other.name_)), - type_(other.type_), - invert_match_(other.invert_match_) { - switch (type_) { - case Type::RANGE: - range_start_ = other.range_start_; - range_end_ = other.range_end_; - break; - case Type::PRESENT: - present_match_ = other.present_match_; - break; - default: - matcher_ = std::move(other.matcher_); - } +bool PortAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + bool matches = (port_ == args.GetLocalPort()); + return matches != not_rule_; } -HeaderMatcher& HeaderMatcher::operator=(HeaderMatcher&& other) noexcept { - name_ = std::move(other.name_); - type_ = other.type_; - invert_match_ = other.invert_match_; - switch (type_) { - case Type::RANGE: - range_start_ = other.range_start_; - range_end_ = other.range_end_; - break; - case Type::PRESENT: - present_match_ = other.present_match_; - break; - default: - matcher_ = std::move(other.matcher_); - } - return *this; +bool AuthenticatedAuthorizationMatcher::Matches( + const EvaluateArgs& args) const { + bool matches = AuthenticatedMatchesHelper(args, matcher_); + return matches != not_rule_; } -bool HeaderMatcher::operator==(const HeaderMatcher& other) const { - if (name_ != other.name_) return false; - if (type_ != other.type_) return false; - if (invert_match_ != other.invert_match_) return false; - switch (type_) { - case Type::RANGE: - return range_start_ == other.range_start_ && - range_end_ == other.range_end_; - case Type::PRESENT: - return present_match_ == other.present_match_; - default: - return matcher_ == other.matcher_; - } +bool ReqServerNameAuthorizationMatcher::Matches(const EvaluateArgs&) const { + // Currently we do not support matching rules containing + // "requested_server_name". + bool matches = false; + return matches != not_rule_; } -bool HeaderMatcher::Match( - const absl::optional& value) const { - bool match; - if (type_ == Type::PRESENT) { - match = value.has_value() == present_match_; - } else if (!value.has_value()) { - // All other types fail to match if field is not present. - match = false; - } else if (type_ == Type::RANGE) { - int64_t int_value; - match = absl::SimpleAtoi(value.value(), &int_value) && - int_value >= range_start_ && int_value < range_end_; - } else { - match = matcher_.Match(value.value()); +bool PathAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + bool matches = false; + absl::string_view path = args.GetPath(); + if (!path.empty()) { + matches = matcher_.Match(path); } - return match != invert_match_; + return matches != not_rule_; } -std::string HeaderMatcher::ToString() const { - switch (type_) { - case Type::RANGE: - return absl::StrFormat("HeaderMatcher{%s %srange=[%d, %d]}", name_, - invert_match_ ? "not " : "", range_start_, - range_end_); - case Type::PRESENT: - return absl::StrFormat("HeaderMatcher{%s %spresent=%s}", name_, - invert_match_ ? "not " : "", - present_match_ ? "true" : "false"); - case Type::EXACT: - case Type::PREFIX: - case Type::SUFFIX: - case Type::SAFE_REGEX: - case Type::CONTAINS: - return absl::StrFormat("HeaderMatcher{%s %s%s}", name_, - invert_match_ ? "not " : "", matcher_.ToString()); - default: - return ""; - } +bool PolicyAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + return permissions_->Matches(args) && principals_->Matches(args); } } // namespace grpc_core diff --git a/src/core/lib/security/authorization/matchers.h b/src/core/lib/security/authorization/matchers.h index 16d7bc67fd6..86b40ee75b5 100644 --- a/src/core/lib/security/authorization/matchers.h +++ b/src/core/lib/security/authorization/matchers.h @@ -18,141 +18,189 @@ #include #include -#include -#include "absl/status/statusor.h" -#include "absl/strings/string_view.h" -#include "absl/types/optional.h" - -#include "re2/re2.h" +#include "src/core/lib/matchers/matchers.h" +#include "src/core/lib/security/authorization/evaluate_args.h" +#include "src/core/lib/security/authorization/rbac_policy.h" namespace grpc_core { -class StringMatcher { +// Describes the rules for matching permission or principal. +class AuthorizationMatcher { public: - enum class Type { - EXACT, // value stored in string_matcher_ field - PREFIX, // value stored in string_matcher_ field - SUFFIX, // value stored in string_matcher_ field - SAFE_REGEX, // pattern stored in regex_matcher_ field - CONTAINS, // value stored in string_matcher_ field - }; + virtual ~AuthorizationMatcher() = default; - // Creates StringMatcher instance. Returns error status on failure. - static absl::StatusOr Create(Type type, - const std::string& matcher, - bool case_sensitive = true); + // Returns whether or not the permission/principal matches the rules of the + // matcher. + virtual bool Matches(const EvaluateArgs& args) const = 0; - StringMatcher() = default; - StringMatcher(const StringMatcher& other); - StringMatcher& operator=(const StringMatcher& other); - StringMatcher(StringMatcher&& other) noexcept; - StringMatcher& operator=(StringMatcher&& other) noexcept; - bool operator==(const StringMatcher& other) const; + // Creates an instance of a matcher based off the rules defined in Permission + // config. + static std::unique_ptr Create( + Rbac::Permission permission); - bool Match(absl::string_view value) const; + // Creates an instance of a matcher based off the rules defined in Principal + // config. + static std::unique_ptr Create( + Rbac::Principal principal); +}; - std::string ToString() const; +class AlwaysAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit AlwaysAuthorizationMatcher(bool not_rule = false) + : not_rule_(not_rule) {} - Type type() const { return type_; } + bool Matches(const EvaluateArgs&) const override { return !not_rule_; } - // Valid for EXACT, PREFIX, SUFFIX and CONTAINS - const std::string& string_matcher() const { return string_matcher_; } + private: + // Negates matching the provided permission/principal. + const bool not_rule_; +}; - // Valid for SAFE_REGEX - RE2* regex_matcher() const { return regex_matcher_.get(); } +class AndAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit AndAuthorizationMatcher( + std::vector> rules, + bool not_rule = false); + explicit AndAuthorizationMatcher( + std::vector> ids, bool not_rule = false); - bool case_sensitive() const { return case_sensitive_; } + bool Matches(const EvaluateArgs& args) const override; private: - StringMatcher(Type type, const std::string& matcher, bool case_sensitive); - StringMatcher(std::unique_ptr regex_matcher, bool case_sensitive); + std::vector> matchers_; + // Negates matching the provided permission/principal. + const bool not_rule_; +}; - Type type_ = Type::EXACT; - std::string string_matcher_; - std::unique_ptr regex_matcher_; - bool case_sensitive_ = true; +class OrAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit OrAuthorizationMatcher( + std::vector> rules, + bool not_rule = false); + explicit OrAuthorizationMatcher( + std::vector> ids, bool not_rule = false); + + bool Matches(const EvaluateArgs& args) const override; + + private: + std::vector> matchers_; + // Negates matching the provided permission/principal. + const bool not_rule_; }; -class HeaderMatcher { +// TODO(ashithasantosh): Add matcher implementation for metadata field. + +// Perform a match against HTTP headers. +class HeaderAuthorizationMatcher : public AuthorizationMatcher { public: - enum class Type { - EXACT, // value stored in StringMatcher field - PREFIX, // value stored in StringMatcher field - SUFFIX, // value stored in StringMatcher field - SAFE_REGEX, // value stored in StringMatcher field - CONTAINS, // value stored in StringMatcher field - RANGE, // uses range_start and range_end fields - PRESENT, // uses present_match field - }; - - // Make sure that the first five HeaderMatcher::Type enum values match up to - // the corresponding StringMatcher::Type enum values, so that it's safe to - // convert by casting when delegating to StringMatcher. - static_assert(static_cast(Type::EXACT) == - StringMatcher::Type::EXACT, - ""); - static_assert(static_cast(Type::PREFIX) == - StringMatcher::Type::PREFIX, - ""); - static_assert(static_cast(Type::SUFFIX) == - StringMatcher::Type::SUFFIX, - ""); - static_assert(static_cast(Type::SAFE_REGEX) == - StringMatcher::Type::SAFE_REGEX, - ""); - static_assert(static_cast(Type::CONTAINS) == - StringMatcher::Type::CONTAINS, - ""); - - // Creates HeaderMatcher instance. Returns error status on failure. - static absl::StatusOr Create( - const std::string& name, Type type, const std::string& matcher, - int64_t range_start = 0, int64_t range_end = 0, - bool present_match = false, bool invert_match = false); - - HeaderMatcher() = default; - HeaderMatcher(const HeaderMatcher& other); - HeaderMatcher& operator=(const HeaderMatcher& other); - HeaderMatcher(HeaderMatcher&& other) noexcept; - HeaderMatcher& operator=(HeaderMatcher&& other) noexcept; - bool operator==(const HeaderMatcher& other) const; - - const std::string& name() const { return name_; } - - Type type() const { return type_; } - - // Valid for EXACT, PREFIX, SUFFIX and CONTAINS - const std::string& string_matcher() const { - return matcher_.string_matcher(); - } - - // Valid for SAFE_REGEX - RE2* regex_matcher() const { return matcher_.regex_matcher(); } - - bool Match(const absl::optional& value) const; - - std::string ToString() const; + explicit HeaderAuthorizationMatcher(HeaderMatcher matcher, + bool not_rule = false) + : matcher_(std::move(matcher)), not_rule_(not_rule) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const HeaderMatcher matcher_; + // Negates matching the provided permission/principal. + const bool not_rule_; +}; + +// Perform a match against IP Cidr Range. +// TODO(ashithasantosh): Handle type of Ip or use seperate matchers for each +// type. Implement Match functionality, this would require updating EvaluateArgs +// getters, to return format of IP as well. +class IpAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit IpAuthorizationMatcher(Rbac::CidrRange range, bool not_rule = false) + : range_(std::move(range)), not_rule_(not_rule) {} + + bool Matches(const EvaluateArgs&) const override; + + private: + const Rbac::CidrRange range_; + // Negates matching the provided permission/principal. + const bool not_rule_; +}; + +// Perform a match against port number of the destination (local) address. +class PortAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit PortAuthorizationMatcher(int port, bool not_rule = false) + : port_(port), not_rule_(not_rule) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const int port_; + // Negates matching the provided permission/principal. + const bool not_rule_; +}; + +// Matches the principal name as described in the peer certificate. Uses URI SAN +// or DNS SAN in that order, otherwise uses subject field. +class AuthenticatedAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit AuthenticatedAuthorizationMatcher(StringMatcher auth, + bool not_rule = false) + : matcher_(std::move(auth)), not_rule_(not_rule) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const StringMatcher matcher_; + // Negates matching the provided permission/principal. + const bool not_rule_; +}; + +// Perform a match against the request server from the client's connection +// request. This is typically TLS SNI. Currently unsupported. +class ReqServerNameAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit ReqServerNameAuthorizationMatcher( + StringMatcher requested_server_name, bool not_rule = false) + : matcher_(std::move(requested_server_name)), not_rule_(not_rule) {} + + bool Matches(const EvaluateArgs&) const override; + + private: + const StringMatcher matcher_; + // Negates matching the provided permission/principal. + const bool not_rule_; +}; + +// Perform a match against the path header of HTTP request. +class PathAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit PathAuthorizationMatcher(StringMatcher path, bool not_rule = false) + : matcher_(std::move(path)), not_rule_(not_rule) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const StringMatcher matcher_; + // Negates matching the provided permission/principal. + const bool not_rule_; +}; + +// Performs a match for policy field in RBAC, which is a collection of +// permission and principal matchers. Policy matches iff, we find a match in one +// of its permissions and a match in one of its principals. +class PolicyAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit PolicyAuthorizationMatcher(Rbac::Policy policy) + : permissions_( + AuthorizationMatcher::Create(std::move(policy.permissions))), + principals_( + AuthorizationMatcher::Create(std::move(policy.principals))) {} + + bool Matches(const EvaluateArgs& args) const override; private: - // For StringMatcher. - HeaderMatcher(const std::string& name, Type type, StringMatcher matcher, - bool invert_match); - // For RangeMatcher. - HeaderMatcher(const std::string& name, int64_t range_start, int64_t range_end, - bool invert_match); - // For PresentMatcher. - HeaderMatcher(const std::string& name, bool present_match, bool invert_match); - - std::string name_; - Type type_ = Type::EXACT; - StringMatcher matcher_; - int64_t range_start_; - int64_t range_end_; - bool present_match_; - bool invert_match_ = false; + std::unique_ptr permissions_; + std::unique_ptr principals_; }; } // namespace grpc_core -#endif /* GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H */ \ No newline at end of file +#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H diff --git a/src/core/lib/security/authorization/rbac_policy.cc b/src/core/lib/security/authorization/rbac_policy.cc new file mode 100644 index 00000000000..a081c514147 --- /dev/null +++ b/src/core/lib/security/authorization/rbac_policy.cc @@ -0,0 +1,328 @@ +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "src/core/lib/security/authorization/rbac_policy.h" + +#include "absl/strings/str_format.h" +#include "absl/strings/str_join.h" + +namespace grpc_core { + +// +// Rbac +// + +Rbac::Rbac(Rbac::Action action, std::map policies) + : action(action), policies(std::move(policies)) {} + +Rbac::Rbac(Rbac&& other) noexcept + : action(other.action), policies(std::move(other.policies)) {} + +Rbac& Rbac::operator=(Rbac&& other) noexcept { + action = other.action; + policies = std::move(other.policies); + return *this; +} + +std::string Rbac::ToString() const { + std::vector contents; + contents.push_back(absl::StrFormat( + "Rbac action=%s{", action == Rbac::Action::kAllow ? "Allow" : "Deny")); + for (const auto& p : policies) { + contents.push_back(absl::StrFormat("{\n policy_name=%s\n%s\n}", p.first, + p.second.ToString())); + } + contents.push_back("}"); + return absl::StrJoin(contents, "\n"); +} + +// +// CidrRange +// + +Rbac::CidrRange::CidrRange(std::string address_prefix, uint32_t prefix_len) + : address_prefix(std::move(address_prefix)), prefix_len(prefix_len) {} + +Rbac::CidrRange::CidrRange(Rbac::CidrRange&& other) noexcept + : address_prefix(std::move(other.address_prefix)), + prefix_len(other.prefix_len) {} + +Rbac::CidrRange& Rbac::CidrRange::operator=(Rbac::CidrRange&& other) noexcept { + address_prefix = std::move(other.address_prefix); + prefix_len = other.prefix_len; + return *this; +} + +std::string Rbac::CidrRange::ToString() const { + return absl::StrFormat("CidrRange{address_prefix=%s,prefix_len=%d}", + address_prefix, prefix_len); +} + +// +// Permission +// + +Rbac::Permission::Permission( + Permission::RuleType type, + std::vector> permissions, bool not_rule) + : type(type), permissions(std::move(permissions)), not_rule(not_rule) {} +Rbac::Permission::Permission(Permission::RuleType type, bool not_rule) + : type(type), not_rule(not_rule) {} +Rbac::Permission::Permission(Permission::RuleType type, + HeaderMatcher header_matcher, bool not_rule) + : type(type), + header_matcher(std::move(header_matcher)), + not_rule(not_rule) {} +Rbac::Permission::Permission(Permission::RuleType type, + StringMatcher string_matcher, bool not_rule) + : type(type), + string_matcher(std::move(string_matcher)), + not_rule(not_rule) {} +Rbac::Permission::Permission(Permission::RuleType type, CidrRange ip, + bool not_rule) + : type(type), ip(std::move(ip)), not_rule(not_rule) {} +Rbac::Permission::Permission(Permission::RuleType type, int port, bool not_rule) + : type(type), port(port), not_rule(not_rule) {} + +Rbac::Permission::Permission(Rbac::Permission&& other) noexcept + : type(other.type), not_rule(other.not_rule) { + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + permissions = std::move(other.permissions); + break; + case RuleType::kAny: + break; + case RuleType::kHeader: + header_matcher = std::move(other.header_matcher); + break; + case RuleType::kPath: + case RuleType::kReqServerName: + string_matcher = std::move(other.string_matcher); + break; + case RuleType::kDestIp: + ip = std::move(other.ip); + break; + default: + port = other.port; + } +} + +Rbac::Permission& Rbac::Permission::operator=( + Rbac::Permission&& other) noexcept { + type = other.type; + not_rule = other.not_rule; + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + permissions = std::move(other.permissions); + break; + case RuleType::kAny: + break; + case RuleType::kHeader: + header_matcher = std::move(other.header_matcher); + break; + case RuleType::kPath: + case RuleType::kReqServerName: + string_matcher = std::move(other.string_matcher); + break; + case RuleType::kDestIp: + ip = std::move(other.ip); + break; + default: + port = other.port; + } + return *this; +} + +std::string Rbac::Permission::ToString() const { + switch (type) { + case RuleType::kAnd: { + std::vector contents; + contents.reserve(permissions.size()); + for (const auto& permission : permissions) { + contents.push_back(permission->ToString()); + } + return absl::StrFormat("%sand=[%s]", not_rule ? "not " : "", + absl::StrJoin(contents, ",")); + } + case RuleType::kOr: { + std::vector contents; + contents.reserve(permissions.size()); + for (const auto& permission : permissions) { + contents.push_back(permission->ToString()); + } + return absl::StrFormat("%sor=[%s]", not_rule ? "not " : "", + absl::StrJoin(contents, ",")); + } + case RuleType::kAny: + return absl::StrFormat("%sany", not_rule ? "not " : ""); + case RuleType::kHeader: + return absl::StrFormat("%sheader=%s", not_rule ? "not " : "", + header_matcher.ToString()); + case RuleType::kPath: + return absl::StrFormat("%spath=%s", not_rule ? "not " : "", + string_matcher.ToString()); + case RuleType::kDestIp: + return absl::StrFormat("%sdest_ip=%s", not_rule ? "not " : "", + ip.ToString()); + case RuleType::kDestPort: + return absl::StrFormat("%sdest_port=%d", not_rule ? "not " : "", port); + case RuleType::kReqServerName: + return absl::StrFormat("%srequested_server_name=%s", + not_rule ? "not " : "", string_matcher.ToString()); + default: + return ""; + } +} + +// +// Principal +// + +Rbac::Principal::Principal(Principal::RuleType type, + std::vector> principals, + bool not_rule) + : type(type), principals(std::move(principals)), not_rule(not_rule) {} +Rbac::Principal::Principal(Principal::RuleType type, bool not_rule) + : type(type), not_rule(not_rule) {} +Rbac::Principal::Principal(Principal::RuleType type, + StringMatcher string_matcher, bool not_rule) + : type(type), + string_matcher(std::move(string_matcher)), + not_rule(not_rule) {} +Rbac::Principal::Principal(Principal::RuleType type, CidrRange ip, + bool not_rule) + : type(type), ip(std::move(ip)), not_rule(not_rule) {} +Rbac::Principal::Principal(Principal::RuleType type, + HeaderMatcher header_matcher, bool not_rule) + : type(type), + header_matcher(std::move(header_matcher)), + not_rule(not_rule) {} + +Rbac::Principal::Principal(Rbac::Principal&& other) noexcept + : type(other.type), not_rule(other.not_rule) { + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + principals = std::move(other.principals); + break; + case RuleType::kAny: + break; + case RuleType::kHeader: + header_matcher = std::move(other.header_matcher); + break; + case RuleType::kPrincipalName: + case RuleType::kPath: + string_matcher = std::move(other.string_matcher); + break; + default: + ip = std::move(other.ip); + } +} + +Rbac::Principal& Rbac::Principal::operator=(Rbac::Principal&& other) noexcept { + type = other.type; + not_rule = other.not_rule; + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + principals = std::move(other.principals); + break; + case RuleType::kAny: + break; + case RuleType::kHeader: + header_matcher = std::move(other.header_matcher); + break; + case RuleType::kPrincipalName: + case RuleType::kPath: + string_matcher = std::move(other.string_matcher); + break; + default: + ip = std::move(other.ip); + } + return *this; +} + +std::string Rbac::Principal::ToString() const { + switch (type) { + case RuleType::kAnd: { + std::vector contents; + contents.reserve(principals.size()); + for (const auto& principal : principals) { + contents.push_back(principal->ToString()); + } + return absl::StrFormat("%sand=[%s]", not_rule ? "not " : "", + absl::StrJoin(contents, ",")); + } + case RuleType::kOr: { + std::vector contents; + contents.reserve(principals.size()); + for (const auto& principal : principals) { + contents.push_back(principal->ToString()); + } + return absl::StrFormat("%sor=[%s]", not_rule ? "not " : "", + absl::StrJoin(contents, ",")); + } + case RuleType::kAny: + return absl::StrFormat("%sany", not_rule ? "not " : ""); + case RuleType::kPrincipalName: + return absl::StrFormat("%sprincipal_name=%s", not_rule ? "not " : "", + string_matcher.ToString()); + case RuleType::kSourceIp: + return absl::StrFormat("%ssource_ip=%s", not_rule ? "not " : "", + ip.ToString()); + case RuleType::kDirectRemoteIp: + return absl::StrFormat("%sdirect_remote_ip=%s", not_rule ? "not " : "", + ip.ToString()); + case RuleType::kRemoteIp: + return absl::StrFormat("%sremote_ip=%s", not_rule ? "not " : "", + ip.ToString()); + case RuleType::kHeader: + return absl::StrFormat("%sheader=%s", not_rule ? "not " : "", + header_matcher.ToString()); + case RuleType::kPath: + return absl::StrFormat("%spath=%s", not_rule ? "not " : "", + string_matcher.ToString()); + default: + return ""; + } +} + +// +// Policy +// + +Rbac::Policy::Policy(Permission permissions, Principal principals) + : permissions(std::move(permissions)), principals(std::move(principals)) {} + +Rbac::Policy::Policy(Rbac::Policy&& other) noexcept + : permissions(std::move(other.permissions)), + principals(std::move(other.principals)) {} + +Rbac::Policy& Rbac::Policy::operator=(Rbac::Policy&& other) noexcept { + permissions = std::move(other.permissions); + principals = std::move(other.principals); + return *this; +} + +std::string Rbac::Policy::ToString() const { + return absl::StrFormat( + " Policy {\n Permissions{%s}\n Principals{%s}\n }", + permissions.ToString(), principals.ToString()); +} + +} // namespace grpc_core diff --git a/src/core/lib/security/authorization/rbac_policy.h b/src/core/lib/security/authorization/rbac_policy.h new file mode 100644 index 00000000000..027bf92eb26 --- /dev/null +++ b/src/core/lib/security/authorization/rbac_policy.h @@ -0,0 +1,163 @@ +// Copyright 2021 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_AUTHORIZATION_RBAC_POLICY_H +#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_RBAC_POLICY_H + +#include + +#include + +#include "src/core/lib/matchers/matchers.h" + +namespace grpc_core { + +// Represents Envoy RBAC Proto. [See +// https://github.com/envoyproxy/envoy/blob/release/v1.17/api/envoy/config/rbac/v3/rbac.proto] +struct Rbac { + enum class Action { + kAllow, + kDeny, + }; + + struct CidrRange { + CidrRange() = default; + CidrRange(std::string address_prefix, uint32_t prefix_len); + + CidrRange(CidrRange&& other) noexcept; + CidrRange& operator=(CidrRange&& other) noexcept; + + std::string ToString() const; + + std::string address_prefix; + uint32_t prefix_len; + }; + + // TODO(ashithasantosh): Add metadata field to Permission and Principal. + struct Permission { + enum class RuleType { + kAnd, + kOr, + kAny, + kHeader, + kPath, + kDestIp, + kDestPort, + kReqServerName, + }; + + Permission() = default; + // For AND/OR RuleType. + Permission(Permission::RuleType type, + std::vector> permissions, + bool not_rule = false); + // For ANY RuleType. + explicit Permission(Permission::RuleType type, bool not_rule = false); + // For HEADER RuleType. + Permission(Permission::RuleType type, HeaderMatcher header_matcher, + bool not_rule = false); + // For PATH/REQ_SERVER_NAME RuleType. + Permission(Permission::RuleType type, StringMatcher string_matcher, + bool not_rule = false); + // For DEST_IP RuleType. + Permission(Permission::RuleType type, CidrRange ip, bool not_rule = false); + // For DEST_PORT RuleType. + Permission(Permission::RuleType type, int port, bool not_rule = false); + + Permission(Permission&& other) noexcept; + Permission& operator=(Permission&& other) noexcept; + + std::string ToString() const; + + RuleType type; + HeaderMatcher header_matcher; + StringMatcher string_matcher; + CidrRange ip; + int port; + // For type AND/OR. + std::vector> permissions; + bool not_rule = false; + }; + + struct Principal { + enum class RuleType { + kAnd, + kOr, + kAny, + kPrincipalName, + kSourceIp, + kDirectRemoteIp, + kRemoteIp, + kHeader, + kPath, + }; + + Principal() = default; + // For AND/OR RuleType. + Principal(Principal::RuleType type, + std::vector> principals, + bool not_rule = false); + // For ANY RuleType. + explicit Principal(Principal::RuleType type, bool not_rule = false); + // For PRINCIPAL_NAME/PATH RuleType. + Principal(Principal::RuleType type, StringMatcher string_matcher, + bool not_rule = false); + // For SOURCE_IP/DIRECT_REMOTE_IP/REMOTE_IP RuleType. + Principal(Principal::RuleType type, CidrRange ip, bool not_rule = false); + // For HEADER RuleType. + Principal(Principal::RuleType type, HeaderMatcher header_matcher, + bool not_rule = false); + + Principal(Principal&& other) noexcept; + Principal& operator=(Principal&& other) noexcept; + + std::string ToString() const; + + RuleType type; + HeaderMatcher header_matcher; + StringMatcher string_matcher; + CidrRange ip; + // For type AND/OR. + std::vector> principals; + bool not_rule = false; + }; + + struct Policy { + Policy() = default; + Policy(Permission permissions, Principal principals); + + Policy(Policy&& other) noexcept; + Policy& operator=(Policy&& other) noexcept; + + std::string ToString() const; + + Permission permissions; + Principal principals; + }; + + Rbac() = default; + Rbac(Rbac::Action action, std::map policies); + + Rbac(Rbac&& other) noexcept; + Rbac& operator=(Rbac&& other) noexcept; + + std::string ToString() const; + + Action action; + std::map policies; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SECURITY_AUTHORIZATION_RBAC_POLICY_H */ diff --git a/src/core/lib/security/authorization/rbac_translator.cc b/src/core/lib/security/authorization/rbac_translator.cc new file mode 100644 index 00000000000..ea5599dde9a --- /dev/null +++ b/src/core/lib/security/authorization/rbac_translator.cc @@ -0,0 +1,354 @@ +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "src/core/lib/security/authorization/rbac_translator.h" + +#include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" +#include "absl/strings/strip.h" + +#include "src/core/lib/matchers/matchers.h" + +namespace grpc_core { + +namespace { + +absl::string_view GetMatcherType(absl::string_view value, + StringMatcher::Type* type) { + if (value == "*") { + *type = StringMatcher::Type::kPrefix; + return ""; + } else if (absl::StartsWith(value, "*")) { + *type = StringMatcher::Type::kSuffix; + return absl::StripPrefix(value, "*"); + } else if (absl::EndsWith(value, "*")) { + *type = StringMatcher::Type::kPrefix; + return absl::StripSuffix(value, "*"); + } + *type = StringMatcher::Type::kExact; + return value; +} + +absl::StatusOr GetStringMatcher(absl::string_view value) { + StringMatcher::Type type; + absl::string_view matcher = GetMatcherType(value, &type); + return StringMatcher::Create(type, matcher); +} + +absl::StatusOr GetHeaderMatcher(absl::string_view name, + absl::string_view value) { + StringMatcher::Type type; + absl::string_view matcher = GetMatcherType(value, &type); + return HeaderMatcher::Create(name, static_cast(type), + matcher); +} + +absl::StatusOr ParsePrincipalsArray(const Json& json) { + std::vector> principal_names; + for (size_t i = 0; i < json.array_value().size(); ++i) { + const Json& child = json.array_value().at(i); + if (child.type() != Json::Type::STRING) { + return absl::InvalidArgumentError( + absl::StrCat("\"principals\" ", i, ": is not a string.")); + } + auto matcher_or = GetStringMatcher(child.string_value()); + if (!matcher_or.ok()) { + return absl::Status(matcher_or.status().code(), + absl::StrCat("\"principals\" ", i, ": ", + matcher_or.status().message())); + } + principal_names.push_back(absl::make_unique( + Rbac::Principal::RuleType::kPrincipalName, + std::move(matcher_or.value()))); + } + return Rbac::Principal(Rbac::Principal::RuleType::kOr, + std::move(principal_names)); +} + +absl::StatusOr ParsePeer(const Json& json) { + std::vector> peer; + auto it = json.object_value().find("principals"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::ARRAY) { + return absl::InvalidArgumentError("\"principals\" is not an array."); + } + auto principal_names_or = ParsePrincipalsArray(it->second); + if (!principal_names_or.ok()) return principal_names_or.status(); + if (!principal_names_or.value().principals.empty()) { + peer.push_back(absl::make_unique( + std::move(principal_names_or.value()))); + } + } + if (peer.empty()) { + return Rbac::Principal(Rbac::Principal::RuleType::kAny); + } + return Rbac::Principal(Rbac::Principal::RuleType::kAnd, std::move(peer)); +} + +absl::StatusOr ParseHeaderValues( + const Json& json, absl::string_view header_name) { + if (json.array_value().empty()) { + return absl::InvalidArgumentError("\"values\" list is empty."); + } + std::vector> values; + for (size_t i = 0; i < json.array_value().size(); ++i) { + const Json& child = json.array_value().at(i); + if (child.type() != Json::Type::STRING) { + return absl::InvalidArgumentError( + absl::StrCat("\"values\" ", i, ": is not a string.")); + } + auto matcher_or = GetHeaderMatcher(header_name, child.string_value()); + if (!matcher_or.ok()) { + return absl::Status( + matcher_or.status().code(), + absl::StrCat("\"values\" ", i, ": ", matcher_or.status().message())); + } + values.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, std::move(matcher_or.value()))); + } + return Rbac::Permission(Rbac::Permission::RuleType::kOr, std::move(values)); +} + +absl::StatusOr ParseHeaders(const Json& json) { + auto it = json.object_value().find("key"); + if (it == json.object_value().end()) { + return absl::InvalidArgumentError("\"key\" is not present."); + } + if (it->second.type() != Json::Type::STRING) { + return absl::InvalidArgumentError("\"key\" is not a string."); + } + absl::string_view header_name = it->second.string_value(); + // TODO(ashithasantosh): Add connection headers below. + if (absl::StartsWith(header_name, ":") || + absl::StartsWith(header_name, "grpc-") || header_name == "host" || + header_name == "Host") { + return absl::InvalidArgumentError( + absl::StrFormat("Unsupported \"key\" %s.", header_name)); + } + it = json.object_value().find("values"); + if (it == json.object_value().end()) { + return absl::InvalidArgumentError("\"values\" is not present."); + } + if (it->second.type() != Json::Type::ARRAY) { + return absl::InvalidArgumentError("\"values\" is not an array."); + } + return ParseHeaderValues(it->second, header_name); +} + +absl::StatusOr ParseHeadersArray(const Json& json) { + std::vector> headers; + for (size_t i = 0; i < json.array_value().size(); ++i) { + const Json& child = json.array_value().at(i); + if (child.type() != Json::Type::OBJECT) { + return absl::InvalidArgumentError( + absl::StrCat("\"headers\" ", i, ": is not an object.")); + } + auto headers_or = ParseHeaders(child); + if (!headers_or.ok()) { + return absl::Status( + headers_or.status().code(), + absl::StrCat("\"headers\" ", i, ": ", headers_or.status().message())); + } + headers.push_back( + absl::make_unique(std::move(headers_or.value()))); + } + return Rbac::Permission(Rbac::Permission::RuleType::kAnd, std::move(headers)); +} + +absl::StatusOr ParsePathsArray(const Json& json) { + std::vector> paths; + for (size_t i = 0; i < json.array_value().size(); ++i) { + const Json& child = json.array_value().at(i); + if (child.type() != Json::Type::STRING) { + return absl::InvalidArgumentError( + absl::StrCat("\"paths\" ", i, ": is not a string.")); + } + auto matcher_or = GetStringMatcher(child.string_value()); + if (!matcher_or.ok()) { + return absl::Status( + matcher_or.status().code(), + absl::StrCat("\"paths\" ", i, ": ", matcher_or.status().message())); + } + paths.push_back(absl::make_unique( + Rbac::Permission::RuleType::kPath, std::move(matcher_or.value()))); + } + return Rbac::Permission(Rbac::Permission::RuleType::kOr, std::move(paths)); +} + +absl::StatusOr ParseRequest(const Json& json) { + std::vector> request; + auto it = json.object_value().find("paths"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::ARRAY) { + return absl::InvalidArgumentError("\"paths\" is not an array."); + } + auto paths_or = ParsePathsArray(it->second); + if (!paths_or.ok()) return paths_or.status(); + if (!paths_or.value().permissions.empty()) { + request.push_back( + absl::make_unique(std::move(paths_or.value()))); + } + } + it = json.object_value().find("headers"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::ARRAY) { + return absl::InvalidArgumentError("\"headers\" is not an array."); + } + auto headers_or = ParseHeadersArray(it->second); + if (!headers_or.ok()) return headers_or.status(); + if (!headers_or.value().permissions.empty()) { + request.push_back( + absl::make_unique(std::move(headers_or.value()))); + } + } + if (request.empty()) { + return Rbac::Permission(Rbac::Permission::RuleType::kAny); + } + return Rbac::Permission(Rbac::Permission::RuleType::kAnd, std::move(request)); +} + +absl::StatusOr ParseRules(const Json& json) { + Rbac::Principal principals; + auto it = json.object_value().find("source"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::OBJECT) { + return absl::InvalidArgumentError("\"source\" is not an object."); + } + auto peer_or = ParsePeer(it->second); + if (!peer_or.ok()) return peer_or.status(); + principals = std::move(peer_or.value()); + } else { + principals = Rbac::Principal(Rbac::Principal::RuleType::kAny); + } + Rbac::Permission permissions; + it = json.object_value().find("request"); + if (it != json.object_value().end()) { + if (it->second.type() != Json::Type::OBJECT) { + return absl::InvalidArgumentError("\"request\" is not an object."); + } + auto request_or = ParseRequest(it->second); + if (!request_or.ok()) return request_or.status(); + permissions = std::move(request_or.value()); + } else { + permissions = Rbac::Permission(Rbac::Permission::RuleType::kAny); + } + return Rbac::Policy(std::move(permissions), std::move(principals)); +} + +absl::StatusOr> ParseRulesArray( + const Json& json, absl::string_view name) { + std::map policies; + for (size_t i = 0; i < json.array_value().size(); ++i) { + const Json& child = json.array_value().at(i); + if (child.type() != Json::Type::OBJECT) { + return absl::InvalidArgumentError( + absl::StrCat("rules ", i, ": is not an object.")); + } + auto it = child.object_value().find("name"); + if (it == child.object_value().end()) { + return absl::InvalidArgumentError( + absl::StrCat("rules ", i, ": \"name\" is not present.")); + } + if (it->second.type() != Json::Type::STRING) { + return absl::InvalidArgumentError( + absl::StrCat("rules ", i, ": \"name\" is not a string.")); + } + std::string policy_name = + std::string(name) + "_" + it->second.string_value(); + auto policy_or = ParseRules(child); + if (!policy_or.ok()) { + return absl::Status( + policy_or.status().code(), + absl::StrCat("rules ", i, ": ", policy_or.status().message())); + } + policies[policy_name] = std::move(policy_or.value()); + } + return std::move(policies); +} + +absl::StatusOr ParseDenyRulesArray(const Json& json, + absl::string_view name) { + auto policies_or = ParseRulesArray(json, name); + if (!policies_or.ok()) return policies_or.status(); + return Rbac(Rbac::Action::kDeny, std::move(policies_or.value())); +} + +absl::StatusOr ParseAllowRulesArray(const Json& json, + absl::string_view name) { + auto policies_or = ParseRulesArray(json, name); + if (!policies_or.ok()) return policies_or.status(); + return Rbac(Rbac::Action::kAllow, std::move(policies_or.value())); +} + +} // namespace + +absl::StatusOr GenerateRbacPolicies( + absl::string_view authz_policy) { + grpc_error_handle error = GRPC_ERROR_NONE; + Json json = Json::Parse(authz_policy, &error); + if (error != GRPC_ERROR_NONE) { + absl::Status status = absl::InvalidArgumentError( + absl::StrCat("Failed to parse SDK authorization policy. Error: ", + grpc_error_std_string(error))); + GRPC_ERROR_UNREF(error); + return status; + } + if (json.type() != Json::Type::OBJECT) { + return absl::InvalidArgumentError( + "SDK authorization policy is not an object."); + } + auto it = json.mutable_object()->find("name"); + if (it == json.mutable_object()->end()) { + return absl::InvalidArgumentError("\"name\" field is not present."); + } + if (it->second.type() != Json::Type::STRING) { + return absl::InvalidArgumentError("\"name\" is not a string."); + } + absl::string_view name = it->second.string_value(); + RbacPolicies rbac_policies; + it = json.mutable_object()->find("deny_rules"); + if (it != json.mutable_object()->end()) { + if (it->second.type() != Json::Type::ARRAY) { + return absl::InvalidArgumentError("\"deny_rules\" is not an array."); + } + auto deny_policy_or = ParseDenyRulesArray(it->second, name); + if (!deny_policy_or.ok()) { + return absl::Status( + deny_policy_or.status().code(), + absl::StrCat("deny_", deny_policy_or.status().message())); + } + rbac_policies.deny_policy = std::move(deny_policy_or.value()); + } else { + rbac_policies.deny_policy.action = Rbac::Action::kDeny; + } + it = json.mutable_object()->find("allow_rules"); + if (it == json.mutable_object()->end()) { + return absl::InvalidArgumentError("\"allow_rules\" is not present."); + } + if (it->second.type() != Json::Type::ARRAY) { + return absl::InvalidArgumentError("\"allow_rules\" is not an array."); + } + auto allow_policy_or = ParseAllowRulesArray(it->second, name); + if (!allow_policy_or.ok()) { + return absl::Status( + allow_policy_or.status().code(), + absl::StrCat("allow_", allow_policy_or.status().message())); + } + rbac_policies.allow_policy = std::move(allow_policy_or.value()); + return std::move(rbac_policies); +} + +} // namespace grpc_core diff --git a/src/core/lib/security/authorization/rbac_translator.h b/src/core/lib/security/authorization/rbac_translator.h new file mode 100644 index 00000000000..51d7024866a --- /dev/null +++ b/src/core/lib/security/authorization/rbac_translator.h @@ -0,0 +1,39 @@ +// Copyright 2021 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_AUTHORIZATION_RBAC_TRANSLATOR_H +#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_RBAC_TRANSLATOR_H + +#include + +#include "absl/status/statusor.h" +#include "src/core/lib/json/json.h" +#include "src/core/lib/security/authorization/rbac_policy.h" + +namespace grpc_core { + +struct RbacPolicies { + Rbac deny_policy; + Rbac allow_policy; +}; + +// Translates SDK authorization policy to Envoy RBAC policies. Returns error on +// failure. +// authz_policy: Authorization Policy string in JSON format. +absl::StatusOr GenerateRbacPolicies( + absl::string_view authz_policy); + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SECURITY_AUTHORIZATION_RBAC_TRANSLATOR_H */ diff --git a/src/core/lib/security/credentials/composite/composite_credentials.cc b/src/core/lib/security/credentials/composite/composite_credentials.cc index bccc03472e3..5543ad1a244 100644 --- a/src/core/lib/security/credentials/composite/composite_credentials.cc +++ b/src/core/lib/security/credentials/composite/composite_credentials.cc @@ -36,7 +36,7 @@ /* -- Composite call credentials. -- */ -static void composite_call_metadata_cb(void* arg, grpc_error* error); +static void composite_call_metadata_cb(void* arg, grpc_error_handle error); namespace { struct grpc_composite_call_credentials_metadata_context { @@ -64,7 +64,7 @@ struct grpc_composite_call_credentials_metadata_context { }; } // namespace -static void composite_call_metadata_cb(void* arg, grpc_error* error) { +static void composite_call_metadata_cb(void* arg, grpc_error_handle error) { grpc_composite_call_credentials_metadata_context* ctx = static_cast(arg); if (error == GRPC_ERROR_NONE) { @@ -91,7 +91,7 @@ static void composite_call_metadata_cb(void* arg, grpc_error* error) { bool grpc_composite_call_credentials::get_request_metadata( grpc_polling_entity* pollent, grpc_auth_metadata_context auth_md_context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) { + grpc_error_handle* error) { grpc_composite_call_credentials_metadata_context* ctx; ctx = new grpc_composite_call_credentials_metadata_context( this, pollent, auth_md_context, md_array, on_request_metadata); @@ -112,7 +112,7 @@ bool grpc_composite_call_credentials::get_request_metadata( } void grpc_composite_call_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* md_array, grpc_error* error) { + grpc_credentials_mdelem_array* md_array, grpc_error_handle error) { for (size_t i = 0; i < inner_.size(); ++i) { inner_[i]->cancel_get_request_metadata(md_array, GRPC_ERROR_REF(error)); } diff --git a/src/core/lib/security/credentials/composite/composite_credentials.h b/src/core/lib/security/credentials/composite/composite_credentials.h index 6b9e9d114d8..86346275e75 100644 --- a/src/core/lib/security/credentials/composite/composite_credentials.h +++ b/src/core/lib/security/credentials/composite/composite_credentials.h @@ -83,10 +83,10 @@ class grpc_composite_call_credentials : public grpc_call_credentials { grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error* error) override; + grpc_error_handle error) override; grpc_security_level min_security_level() const override { return min_security_level_; diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h index cf9f402be8c..b8609c58d7d 100644 --- a/src/core/lib/security/credentials/credentials.h +++ b/src/core/lib/security/credentials/credentials.h @@ -187,13 +187,13 @@ struct grpc_call_credentials grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) = 0; + grpc_error_handle* error) = 0; // Cancels a pending asynchronous operation started by // grpc_call_credentials_get_request_metadata() with the corresponding // value of \a md_array. virtual void cancel_get_request_metadata( - grpc_credentials_mdelem_array* md_array, grpc_error* error) = 0; + grpc_credentials_mdelem_array* md_array, grpc_error_handle error) = 0; virtual grpc_security_level min_security_level() const { return min_security_level_; diff --git a/src/core/lib/security/credentials/external/aws_external_account_credentials.cc b/src/core/lib/security/credentials/external/aws_external_account_credentials.cc index 3ad09d24785..c479bf067fc 100644 --- a/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/aws_external_account_credentials.cc @@ -30,6 +30,7 @@ namespace { const char* kExpectedEnvironmentId = "aws1"; const char* kRegionEnvVar = "AWS_REGION"; +const char* kDefaultRegionEnvVar = "AWS_DEFAULT_REGION"; const char* kAccessKeyIdEnvVar = "AWS_ACCESS_KEY_ID"; const char* kSecretAccessKeyEnvVar = "AWS_SECRET_ACCESS_KEY"; const char* kSessionTokenEnvVar = "AWS_SESSION_TOKEN"; @@ -57,7 +58,7 @@ std::string UrlEncode(const absl::string_view& s) { RefCountedPtr AwsExternalAccountCredentials::Create(Options options, std::vector scopes, - grpc_error** error) { + grpc_error_handle* error) { auto creds = MakeRefCounted( std::move(options), std::move(scopes), error); if (*error == GRPC_ERROR_NONE) { @@ -68,7 +69,7 @@ AwsExternalAccountCredentials::Create(Options options, } AwsExternalAccountCredentials::AwsExternalAccountCredentials( - Options options, std::vector scopes, grpc_error** error) + Options options, std::vector scopes, grpc_error_handle* error) : ExternalAccountCredentials(options, std::move(scopes)) { audience_ = options.audience; auto it = options.credential_source.object_value().find("environment_id"); @@ -121,7 +122,7 @@ AwsExternalAccountCredentials::AwsExternalAccountCredentials( void AwsExternalAccountCredentials::RetrieveSubjectToken( HTTPRequestContext* ctx, const Options& /*options*/, - std::function cb) { + std::function cb) { if (ctx == nullptr) { FinishRetrieveSubjectToken( "", @@ -140,6 +141,9 @@ void AwsExternalAccountCredentials::RetrieveSubjectToken( void AwsExternalAccountCredentials::RetrieveRegion() { UniquePtr region_from_env(gpr_getenv(kRegionEnvVar)); + if (region_from_env == nullptr) { + region_from_env = UniquePtr(gpr_getenv(kDefaultRegionEnvVar)); + } if (region_from_env != nullptr) { region_ = std::string(region_from_env.get()); if (url_.empty()) { @@ -175,14 +179,14 @@ void AwsExternalAccountCredentials::RetrieveRegion() { } void AwsExternalAccountCredentials::OnRetrieveRegion(void* arg, - grpc_error* error) { + grpc_error_handle error) { AwsExternalAccountCredentials* self = static_cast(arg); self->OnRetrieveRegionInternal(GRPC_ERROR_REF(error)); } void AwsExternalAccountCredentials::OnRetrieveRegionInternal( - grpc_error* error) { + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { FinishRetrieveSubjectToken("", error); return; @@ -224,15 +228,15 @@ void AwsExternalAccountCredentials::RetrieveRoleName() { grpc_http_request_destroy(&request.http); } -void AwsExternalAccountCredentials::OnRetrieveRoleName(void* arg, - grpc_error* error) { +void AwsExternalAccountCredentials::OnRetrieveRoleName( + void* arg, grpc_error_handle error) { AwsExternalAccountCredentials* self = static_cast(arg); self->OnRetrieveRoleNameInternal(GRPC_ERROR_REF(error)); } void AwsExternalAccountCredentials::OnRetrieveRoleNameInternal( - grpc_error* error) { + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { FinishRetrieveSubjectToken("", error); return; @@ -287,15 +291,15 @@ void AwsExternalAccountCredentials::RetrieveSigningKeys() { grpc_http_request_destroy(&request.http); } -void AwsExternalAccountCredentials::OnRetrieveSigningKeys(void* arg, - grpc_error* error) { +void AwsExternalAccountCredentials::OnRetrieveSigningKeys( + void* arg, grpc_error_handle error) { AwsExternalAccountCredentials* self = static_cast(arg); self->OnRetrieveSigningKeysInternal(GRPC_ERROR_REF(error)); } void AwsExternalAccountCredentials::OnRetrieveSigningKeysInternal( - grpc_error* error) { + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { FinishRetrieveSubjectToken("", error); return; @@ -350,7 +354,7 @@ void AwsExternalAccountCredentials::OnRetrieveSigningKeysInternal( } void AwsExternalAccountCredentials::BuildSubjectToken() { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (signer_ == nullptr) { cred_verification_url_ = absl::StrReplaceAll( regional_cred_verification_url_, {{"{region}", region_}}); @@ -396,7 +400,7 @@ void AwsExternalAccountCredentials::BuildSubjectToken() { } void AwsExternalAccountCredentials::FinishRetrieveSubjectToken( - std::string subject_token, grpc_error* error) { + std::string subject_token, grpc_error_handle error) { // Reset context ctx_ = nullptr; // Move object state into local variables. diff --git a/src/core/lib/security/credentials/external/aws_external_account_credentials.h b/src/core/lib/security/credentials/external/aws_external_account_credentials.h index edb7e825868..50ccf1943d3 100644 --- a/src/core/lib/security/credentials/external/aws_external_account_credentials.h +++ b/src/core/lib/security/credentials/external/aws_external_account_credentials.h @@ -28,31 +28,33 @@ namespace grpc_core { class AwsExternalAccountCredentials final : public ExternalAccountCredentials { public: static RefCountedPtr Create( - Options options, std::vector scopes, grpc_error** error); + Options options, std::vector scopes, + grpc_error_handle* error); AwsExternalAccountCredentials(Options options, std::vector scopes, - grpc_error** error); + grpc_error_handle* error); private: void RetrieveSubjectToken( HTTPRequestContext* ctx, const Options& options, - std::function cb) override; + std::function cb) override; void RetrieveRegion(); - static void OnRetrieveRegion(void* arg, grpc_error* error); - void OnRetrieveRegionInternal(grpc_error* error); + static void OnRetrieveRegion(void* arg, grpc_error_handle error); + void OnRetrieveRegionInternal(grpc_error_handle error); void RetrieveRoleName(); - static void OnRetrieveRoleName(void* arg, grpc_error* error); - void OnRetrieveRoleNameInternal(grpc_error* error); + static void OnRetrieveRoleName(void* arg, grpc_error_handle error); + void OnRetrieveRoleNameInternal(grpc_error_handle error); void RetrieveSigningKeys(); - static void OnRetrieveSigningKeys(void* arg, grpc_error* error); - void OnRetrieveSigningKeysInternal(grpc_error* error); + static void OnRetrieveSigningKeys(void* arg, grpc_error_handle error); + void OnRetrieveSigningKeysInternal(grpc_error_handle error); void BuildSubjectToken(); - void FinishRetrieveSubjectToken(std::string subject_token, grpc_error* error); + void FinishRetrieveSubjectToken(std::string subject_token, + grpc_error_handle error); std::string audience_; @@ -72,7 +74,7 @@ class AwsExternalAccountCredentials final : public ExternalAccountCredentials { std::string cred_verification_url_; HTTPRequestContext* ctx_ = nullptr; - std::function cb_ = nullptr; + std::function cb_ = nullptr; }; } // namespace grpc_core diff --git a/src/core/lib/security/credentials/external/aws_request_signer.cc b/src/core/lib/security/credentials/external/aws_request_signer.cc index af8531ee02a..b665701b023 100644 --- a/src/core/lib/security/credentials/external/aws_request_signer.cc +++ b/src/core/lib/security/credentials/external/aws_request_signer.cc @@ -66,7 +66,8 @@ AwsRequestSigner::AwsRequestSigner( std::string access_key_id, std::string secret_access_key, std::string token, std::string method, std::string url, std::string region, std::string request_payload, - std::map additional_headers, grpc_error** error) + std::map additional_headers, + grpc_error_handle* error) : access_key_id_(std::move(access_key_id)), secret_access_key_(std::move(secret_access_key)), token_(std::move(token)), diff --git a/src/core/lib/security/credentials/external/aws_request_signer.h b/src/core/lib/security/credentials/external/aws_request_signer.h index 62e112cf0f4..22c4ad67503 100644 --- a/src/core/lib/security/credentials/external/aws_request_signer.h +++ b/src/core/lib/security/credentials/external/aws_request_signer.h @@ -45,7 +45,7 @@ class AwsRequestSigner { std::string token, std::string method, std::string url, std::string region, std::string request_payload, std::map additional_headers, - grpc_error** error); + grpc_error_handle* error); // This method triggers the signing process then returns the headers of the // signed request as a map. In case there is an error, the input `error` diff --git a/src/core/lib/security/credentials/external/external_account_credentials.cc b/src/core/lib/security/credentials/external/external_account_credentials.cc index 0b9fc198829..f5d9442e362 100644 --- a/src/core/lib/security/credentials/external/external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/external_account_credentials.cc @@ -63,7 +63,8 @@ std::string UrlEncode(const absl::string_view& s) { } // namespace RefCountedPtr ExternalAccountCredentials::Create( - const Json& json, std::vector scopes, grpc_error** error) { + const Json& json, std::vector scopes, + grpc_error_handle* error) { GPR_ASSERT(*error == GRPC_ERROR_NONE); Options options; options.type = GRPC_AUTH_JSON_TYPE_INVALID; @@ -213,14 +214,14 @@ void ExternalAccountCredentials::fetch_oauth2( ctx_ = new HTTPRequestContext(httpcli_context, pollent, deadline); metadata_req_ = metadata_req; response_cb_ = response_cb; - auto cb = [this](std::string token, grpc_error* error) { + auto cb = [this](std::string token, grpc_error_handle error) { OnRetrieveSubjectTokenInternal(token, error); }; RetrieveSubjectToken(ctx_, options_, cb); } void ExternalAccountCredentials::OnRetrieveSubjectTokenInternal( - absl::string_view subject_token, grpc_error* error) { + absl::string_view subject_token, grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { FinishTokenFetch(error); } else { @@ -300,13 +301,15 @@ void ExternalAccountCredentials::ExchangeToken( grpc_http_request_destroy(&request.http); } -void ExternalAccountCredentials::OnExchangeToken(void* arg, grpc_error* error) { +void ExternalAccountCredentials::OnExchangeToken(void* arg, + grpc_error_handle error) { ExternalAccountCredentials* self = static_cast(arg); self->OnExchangeTokenInternal(GRPC_ERROR_REF(error)); } -void ExternalAccountCredentials::OnExchangeTokenInternal(grpc_error* error) { +void ExternalAccountCredentials::OnExchangeTokenInternal( + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { FinishTokenFetch(error); } else { @@ -330,7 +333,7 @@ void ExternalAccountCredentials::OnExchangeTokenInternal(grpc_error* error) { } void ExternalAccountCredentials::ImpersenateServiceAccount() { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; absl::string_view response_body(ctx_->response.body, ctx_->response.body_length); Json json = Json::Parse(response_body, &error); @@ -389,14 +392,14 @@ void ExternalAccountCredentials::ImpersenateServiceAccount() { } void ExternalAccountCredentials::OnImpersenateServiceAccount( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { ExternalAccountCredentials* self = static_cast(arg); self->OnImpersenateServiceAccountInternal(GRPC_ERROR_REF(error)); } void ExternalAccountCredentials::OnImpersenateServiceAccountInternal( - grpc_error* error) { + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { FinishTokenFetch(error); return; @@ -452,7 +455,7 @@ void ExternalAccountCredentials::OnImpersenateServiceAccountInternal( FinishTokenFetch(GRPC_ERROR_NONE); } -void ExternalAccountCredentials::FinishTokenFetch(grpc_error* error) { +void ExternalAccountCredentials::FinishTokenFetch(grpc_error_handle error) { GRPC_LOG_IF_ERROR("Fetch external account credentials access token", GRPC_ERROR_REF(error)); // Move object state into local variables. @@ -473,12 +476,12 @@ void ExternalAccountCredentials::FinishTokenFetch(grpc_error* error) { grpc_call_credentials* grpc_external_account_credentials_create( const char* json_string, const char* scopes_string) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json json = grpc_core::Json::Parse(json_string, &error); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "External account credentials creation failed. Error: %s.", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); return nullptr; } @@ -489,7 +492,7 @@ grpc_call_credentials* grpc_external_account_credentials_create( if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "External account credentials creation failed. Error: %s.", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); return nullptr; } diff --git a/src/core/lib/security/credentials/external/external_account_credentials.h b/src/core/lib/security/credentials/external/external_account_credentials.h index 0da778601ad..3c000968d69 100644 --- a/src/core/lib/security/credentials/external/external_account_credentials.h +++ b/src/core/lib/security/credentials/external/external_account_credentials.h @@ -49,7 +49,8 @@ class ExternalAccountCredentials }; static RefCountedPtr Create( - const Json& json, std::vector scopes, grpc_error** error); + const Json& json, std::vector scopes, + grpc_error_handle* error); ExternalAccountCredentials(Options options, std::vector scopes); ~ExternalAccountCredentials() override; @@ -84,7 +85,7 @@ class ExternalAccountCredentials // back. virtual void RetrieveSubjectToken( HTTPRequestContext* ctx, const Options& options, - std::function cb) = 0; + std::function cb) = 0; private: // This method implements the common token fetch logic and it will be called @@ -95,17 +96,17 @@ class ExternalAccountCredentials grpc_millis deadline) override; void OnRetrieveSubjectTokenInternal(absl::string_view subject_token, - grpc_error* error); + grpc_error_handle error); void ExchangeToken(absl::string_view subject_token); - static void OnExchangeToken(void* arg, grpc_error* error); - void OnExchangeTokenInternal(grpc_error* error); + static void OnExchangeToken(void* arg, grpc_error_handle error); + void OnExchangeTokenInternal(grpc_error_handle error); void ImpersenateServiceAccount(); - static void OnImpersenateServiceAccount(void* arg, grpc_error* error); - void OnImpersenateServiceAccountInternal(grpc_error* error); + static void OnImpersenateServiceAccount(void* arg, grpc_error_handle error); + void OnImpersenateServiceAccountInternal(grpc_error_handle error); - void FinishTokenFetch(grpc_error* error); + void FinishTokenFetch(grpc_error_handle error); Options options_; std::vector scopes_; diff --git a/src/core/lib/security/credentials/external/file_external_account_credentials.cc b/src/core/lib/security/credentials/external/file_external_account_credentials.cc index ec2cd6087d6..d596d29414c 100644 --- a/src/core/lib/security/credentials/external/file_external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/file_external_account_credentials.cc @@ -28,7 +28,7 @@ namespace grpc_core { RefCountedPtr FileExternalAccountCredentials::Create(Options options, std::vector scopes, - grpc_error** error) { + grpc_error_handle* error) { auto creds = MakeRefCounted( std::move(options), std::move(scopes), error); if (*error == GRPC_ERROR_NONE) { @@ -39,7 +39,7 @@ FileExternalAccountCredentials::Create(Options options, } FileExternalAccountCredentials::FileExternalAccountCredentials( - Options options, std::vector scopes, grpc_error** error) + Options options, std::vector scopes, grpc_error_handle* error) : ExternalAccountCredentials(options, std::move(scopes)) { auto it = options.credential_source.object_value().find("file"); if (it == options.credential_source.object_value().end()) { @@ -92,7 +92,7 @@ FileExternalAccountCredentials::FileExternalAccountCredentials( void FileExternalAccountCredentials::RetrieveSubjectToken( HTTPRequestContext* /*ctx*/, const Options& /*options*/, - std::function cb) { + std::function cb) { struct SliceWrapper { ~SliceWrapper() { grpc_slice_unref_internal(slice); } grpc_slice slice = grpc_empty_slice(); @@ -100,7 +100,8 @@ void FileExternalAccountCredentials::RetrieveSubjectToken( SliceWrapper content_slice; // To retrieve the subject token, we read the file every time we make a // request because it may have changed since the last request. - grpc_error* error = grpc_load_file(file_.c_str(), 0, &content_slice.slice); + grpc_error_handle error = + grpc_load_file(file_.c_str(), 0, &content_slice.slice); if (error != GRPC_ERROR_NONE) { cb("", error); return; diff --git a/src/core/lib/security/credentials/external/file_external_account_credentials.h b/src/core/lib/security/credentials/external/file_external_account_credentials.h index 7df5b6b8c2c..23a6b6d6f98 100644 --- a/src/core/lib/security/credentials/external/file_external_account_credentials.h +++ b/src/core/lib/security/credentials/external/file_external_account_credentials.h @@ -26,16 +26,17 @@ namespace grpc_core { class FileExternalAccountCredentials final : public ExternalAccountCredentials { public: static RefCountedPtr Create( - Options options, std::vector scopes, grpc_error** error); + Options options, std::vector scopes, + grpc_error_handle* error); FileExternalAccountCredentials(Options options, std::vector scopes, - grpc_error** error); + grpc_error_handle* error); private: void RetrieveSubjectToken( HTTPRequestContext* ctx, const Options& options, - std::function cb) override; + std::function cb) override; // Fields of credential source std::string file_; diff --git a/src/core/lib/security/credentials/external/url_external_account_credentials.cc b/src/core/lib/security/credentials/external/url_external_account_credentials.cc index 2fa42cb465d..55151b96958 100644 --- a/src/core/lib/security/credentials/external/url_external_account_credentials.cc +++ b/src/core/lib/security/credentials/external/url_external_account_credentials.cc @@ -26,7 +26,7 @@ namespace grpc_core { RefCountedPtr UrlExternalAccountCredentials::Create(Options options, std::vector scopes, - grpc_error** error) { + grpc_error_handle* error) { auto creds = MakeRefCounted( std::move(options), std::move(scopes), error); if (*error == GRPC_ERROR_NONE) { @@ -37,7 +37,7 @@ UrlExternalAccountCredentials::Create(Options options, } UrlExternalAccountCredentials::UrlExternalAccountCredentials( - Options options, std::vector scopes, grpc_error** error) + Options options, std::vector scopes, grpc_error_handle* error) : ExternalAccountCredentials(options, std::move(scopes)) { auto it = options.credential_source.object_value().find("url"); if (it == options.credential_source.object_value().end()) { @@ -113,7 +113,7 @@ UrlExternalAccountCredentials::UrlExternalAccountCredentials( void UrlExternalAccountCredentials::RetrieveSubjectToken( HTTPRequestContext* ctx, const Options& /*options*/, - std::function cb) { + std::function cb) { if (ctx == nullptr) { FinishRetrieveSubjectToken( "", @@ -151,15 +151,15 @@ void UrlExternalAccountCredentials::RetrieveSubjectToken( grpc_http_request_destroy(&request.http); } -void UrlExternalAccountCredentials::OnRetrieveSubjectToken(void* arg, - grpc_error* error) { +void UrlExternalAccountCredentials::OnRetrieveSubjectToken( + void* arg, grpc_error_handle error) { UrlExternalAccountCredentials* self = static_cast(arg); self->OnRetrieveSubjectTokenInternal(GRPC_ERROR_REF(error)); } void UrlExternalAccountCredentials::OnRetrieveSubjectTokenInternal( - grpc_error* error) { + grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { FinishRetrieveSubjectToken("", error); return; @@ -167,7 +167,7 @@ void UrlExternalAccountCredentials::OnRetrieveSubjectTokenInternal( absl::string_view response_body(ctx_->response.body, ctx_->response.body_length); if (format_type_ == "json") { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json response_json = Json::Parse(response_body, &error); if (error != GRPC_ERROR_NONE || response_json.type() != Json::Type::OBJECT) { @@ -196,7 +196,7 @@ void UrlExternalAccountCredentials::OnRetrieveSubjectTokenInternal( } void UrlExternalAccountCredentials::FinishRetrieveSubjectToken( - std::string subject_token, grpc_error* error) { + std::string subject_token, grpc_error_handle error) { // Reset context ctx_ = nullptr; // Move object state into local variables. diff --git a/src/core/lib/security/credentials/external/url_external_account_credentials.h b/src/core/lib/security/credentials/external/url_external_account_credentials.h index 4e37c5735fb..eaf984c745f 100644 --- a/src/core/lib/security/credentials/external/url_external_account_credentials.h +++ b/src/core/lib/security/credentials/external/url_external_account_credentials.h @@ -26,21 +26,23 @@ namespace grpc_core { class UrlExternalAccountCredentials final : public ExternalAccountCredentials { public: static RefCountedPtr Create( - Options options, std::vector scopes, grpc_error** error); + Options options, std::vector scopes, + grpc_error_handle* error); UrlExternalAccountCredentials(Options options, std::vector scopes, - grpc_error** error); + grpc_error_handle* error); private: void RetrieveSubjectToken( HTTPRequestContext* ctx, const Options& options, - std::function cb) override; + std::function cb) override; - static void OnRetrieveSubjectToken(void* arg, grpc_error* error); - void OnRetrieveSubjectTokenInternal(grpc_error* error); + static void OnRetrieveSubjectToken(void* arg, grpc_error_handle error); + void OnRetrieveSubjectTokenInternal(grpc_error_handle error); - void FinishRetrieveSubjectToken(std::string subject_token, grpc_error* error); + void FinishRetrieveSubjectToken(std::string subject_token, + grpc_error_handle error); // Fields of credential source URI url_; @@ -50,7 +52,7 @@ class UrlExternalAccountCredentials final : public ExternalAccountCredentials { std::string format_subject_token_field_name_; HTTPRequestContext* ctx_ = nullptr; - std::function cb_ = nullptr; + std::function cb_ = nullptr; }; } // namespace grpc_core diff --git a/src/core/lib/security/credentials/fake/fake_credentials.cc b/src/core/lib/security/credentials/fake/fake_credentials.cc index c439282ffb1..57a897f0689 100644 --- a/src/core/lib/security/credentials/fake/fake_credentials.cc +++ b/src/core/lib/security/credentials/fake/fake_credentials.cc @@ -92,7 +92,7 @@ const char* grpc_fake_transport_get_expected_targets( bool grpc_md_only_test_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** /*error*/) { + grpc_error_handle* /*error*/) { grpc_credentials_mdelem_array_add(md_array, md_); if (is_async_) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_request_metadata, @@ -103,7 +103,7 @@ bool grpc_md_only_test_credentials::get_request_metadata( } void grpc_md_only_test_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* /*md_array*/, grpc_error* error) { + grpc_credentials_mdelem_array* /*md_array*/, grpc_error_handle error) { GRPC_ERROR_UNREF(error); } diff --git a/src/core/lib/security/credentials/fake/fake_credentials.h b/src/core/lib/security/credentials/fake/fake_credentials.h index 3c2449fac3e..ea8c8136d13 100644 --- a/src/core/lib/security/credentials/fake/fake_credentials.h +++ b/src/core/lib/security/credentials/fake/fake_credentials.h @@ -72,10 +72,10 @@ class grpc_md_only_test_credentials : public grpc_call_credentials { grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error* error) override; + grpc_error_handle error) override; std::string debug_string() override { return "MD only Test Credentials"; }; diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc index 19099343c16..0e1a2a10374 100644 --- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -134,8 +134,8 @@ grpc_channel_args* grpc_google_default_channel_credentials::update_arguments( return updated; } -static void on_metadata_server_detection_http_response(void* user_data, - grpc_error* error) { +static void on_metadata_server_detection_http_response( + void* user_data, grpc_error_handle error) { metadata_server_detector* detector = static_cast(user_data); if (error == GRPC_ERROR_NONE && detector->response.status == 200 && @@ -161,7 +161,7 @@ static void on_metadata_server_detection_http_response(void* user_data, gpr_mu_unlock(g_polling_mu); } -static void destroy_pollset(void* p, grpc_error* /*e*/) { +static void destroy_pollset(void* p, grpc_error_handle /*e*/) { grpc_pollset_destroy(static_cast(p)); } @@ -221,14 +221,14 @@ static int is_metadata_server_reachable() { } /* Takes ownership of creds_path if not NULL. */ -static grpc_error* create_default_creds_from_path( +static grpc_error_handle create_default_creds_from_path( const std::string& creds_path, grpc_core::RefCountedPtr* creds) { grpc_auth_json_key key; grpc_auth_refresh_token token; grpc_core::RefCountedPtr result; grpc_slice creds_data = grpc_empty_slice(); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json; if (creds_path.empty()) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("creds_path unset"); @@ -304,9 +304,9 @@ static bool metadata_server_available() { } static grpc_core::RefCountedPtr make_default_call_creds( - grpc_error** error) { + grpc_error_handle* error) { grpc_core::RefCountedPtr call_creds; - grpc_error* err; + grpc_error_handle err; /* First, try the environment variable. */ char* path_from_env = gpr_getenv(GRPC_GOOGLE_CREDENTIALS_ENV_VAR); @@ -344,7 +344,7 @@ grpc_channel_credentials* grpc_google_default_credentials_create( grpc_call_credentials* call_credentials) { grpc_channel_credentials* result = nullptr; grpc_core::RefCountedPtr call_creds(call_credentials); - grpc_error* error = nullptr; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::ExecCtx exec_ctx; GRPC_API_TRACE("grpc_google_default_credentials_create(%p)", 1, @@ -373,7 +373,7 @@ grpc_channel_credentials* grpc_google_default_credentials_create( GPR_ASSERT(result != nullptr); } else { gpr_log(GPR_ERROR, "Could not create google default credentials: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); } GRPC_ERROR_UNREF(error); return result; diff --git a/src/core/lib/security/credentials/iam/iam_credentials.cc b/src/core/lib/security/credentials/iam/iam_credentials.cc index 1aeaa888010..c9dc223544d 100644 --- a/src/core/lib/security/credentials/iam/iam_credentials.cc +++ b/src/core/lib/security/credentials/iam/iam_credentials.cc @@ -36,13 +36,13 @@ grpc_google_iam_credentials::~grpc_google_iam_credentials() { bool grpc_google_iam_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/, grpc_credentials_mdelem_array* md_array, - grpc_closure* /*on_request_metadata*/, grpc_error** /*error*/) { + grpc_closure* /*on_request_metadata*/, grpc_error_handle* /*error*/) { grpc_credentials_mdelem_array_append(md_array, &md_array_); return true; } void grpc_google_iam_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* /*md_array*/, grpc_error* error) { + grpc_credentials_mdelem_array* /*md_array*/, grpc_error_handle error) { GRPC_ERROR_UNREF(error); } diff --git a/src/core/lib/security/credentials/iam/iam_credentials.h b/src/core/lib/security/credentials/iam/iam_credentials.h index 9d4a1e2e474..881ba26866f 100644 --- a/src/core/lib/security/credentials/iam/iam_credentials.h +++ b/src/core/lib/security/credentials/iam/iam_credentials.h @@ -35,10 +35,10 @@ class grpc_google_iam_credentials : public grpc_call_credentials { grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error* error) override; + grpc_error_handle error) override; std::string debug_string() override { return debug_string_; } private: diff --git a/src/core/lib/security/credentials/jwt/json_token.cc b/src/core/lib/security/credentials/jwt/json_token.cc index 520d60f7afa..5e317c490a5 100644 --- a/src/core/lib/security/credentials/jwt/json_token.cc +++ b/src/core/lib/security/credentials/jwt/json_token.cc @@ -72,7 +72,7 @@ grpc_auth_json_key grpc_auth_json_key_create_from_json(const Json& json) { BIO* bio = nullptr; const char* prop_value; int success = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; memset(&result, 0, sizeof(grpc_auth_json_key)); result.type = GRPC_AUTH_JSON_TYPE_INVALID; @@ -124,7 +124,7 @@ end: grpc_auth_json_key grpc_auth_json_key_create_from_string( const char* json_string) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_string, &error); GRPC_LOG_IF_ERROR("JSON key parsing", error); return grpc_auth_json_key_create_from_json(json); diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.cc b/src/core/lib/security/credentials/jwt/jwt_credentials.cc index e5edc052e3b..27590f4baf5 100644 --- a/src/core/lib/security/credentials/jwt/jwt_credentials.cc +++ b/src/core/lib/security/credentials/jwt/jwt_credentials.cc @@ -59,7 +59,7 @@ grpc_service_account_jwt_access_credentials:: bool grpc_service_account_jwt_access_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, - grpc_closure* /*on_request_metadata*/, grpc_error** error) { + grpc_closure* /*on_request_metadata*/, grpc_error_handle* error) { gpr_timespec refresh_threshold = gpr_time_from_seconds( GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN); @@ -109,7 +109,7 @@ bool grpc_service_account_jwt_access_credentials::get_request_metadata( } void grpc_service_account_jwt_access_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* /*md_array*/, grpc_error* error) { + grpc_credentials_mdelem_array* /*md_array*/, grpc_error_handle error) { GRPC_ERROR_UNREF(error); } @@ -141,7 +141,7 @@ grpc_service_account_jwt_access_credentials_create_from_auth_json_key( } static char* redact_private_key(const char* json_key) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_key, &error); if (error != GRPC_ERROR_NONE || json.type() != Json::Type::OBJECT) { GRPC_ERROR_UNREF(error); diff --git a/src/core/lib/security/credentials/jwt/jwt_credentials.h b/src/core/lib/security/credentials/jwt/jwt_credentials.h index d42fc25fd38..5ae4c1f41fd 100644 --- a/src/core/lib/security/credentials/jwt/jwt_credentials.h +++ b/src/core/lib/security/credentials/jwt/jwt_credentials.h @@ -41,10 +41,10 @@ class grpc_service_account_jwt_access_credentials grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error* error) override; + grpc_error_handle error) override; const gpr_timespec& jwt_lifetime() const { return jwt_lifetime_; } const grpc_auth_json_key& key() const { return key_; } diff --git a/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/src/core/lib/security/credentials/jwt/jwt_verifier.cc index 84205434748..8d43cf988f9 100644 --- a/src/core/lib/security/credentials/jwt/jwt_verifier.cc +++ b/src/core/lib/security/credentials/jwt/jwt_verifier.cc @@ -87,10 +87,11 @@ static Json parse_json_part_from_jwt(const char* str, size_t len) { return Json(); // JSON null } absl::string_view string = grpc_core::StringViewFromSlice(slice); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(string, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parse error: %s", + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); json = Json(); // JSON null } @@ -412,7 +413,7 @@ static Json json_from_http(const grpc_httpcli_response* response) { response->status); return Json(); // JSON null } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse( absl::string_view(response->body, response->body_length), &error); if (error != GRPC_ERROR_NONE) { @@ -627,7 +628,7 @@ end: return result; } -static void on_keys_retrieved(void* user_data, grpc_error* /*error*/) { +static void on_keys_retrieved(void* user_data, grpc_error_handle /*error*/) { verifier_cb_ctx* ctx = static_cast(user_data); Json json = json_from_http(&ctx->responses[HTTP_RESPONSE_KEYS]); EVP_PKEY* verification_key = nullptr; @@ -666,7 +667,8 @@ end: verifier_cb_ctx_destroy(ctx); } -static void on_openid_config_retrieved(void* user_data, grpc_error* /*error*/) { +static void on_openid_config_retrieved(void* user_data, + grpc_error_handle /*error*/) { verifier_cb_ctx* ctx = static_cast(user_data); const grpc_http_response* response = &ctx->responses[HTTP_RESPONSE_OPENID]; Json json = json_from_http(response); diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc index bbd2cb5bae3..50d20e64bbe 100644 --- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc @@ -61,7 +61,7 @@ grpc_auth_refresh_token grpc_auth_refresh_token_create_from_json( grpc_auth_refresh_token result; const char* prop_value; int success = 0; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; memset(&result, 0, sizeof(grpc_auth_refresh_token)); result.type = GRPC_AUTH_JSON_TYPE_INVALID; @@ -94,10 +94,11 @@ end: grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string( const char* json_string) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_string, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parsing failed: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parsing failed: %s", + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); } return grpc_auth_refresh_token_create_from_json(json); @@ -164,11 +165,11 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response( const char* token_type = nullptr; const char* expires_in = nullptr; Json::Object::const_iterator it; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; json = Json::Parse(null_terminated_body, &error); if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Could not parse JSON from %s: %s", - null_terminated_body, grpc_error_string(error)); + null_terminated_body, grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); status = GRPC_CREDENTIALS_ERROR; goto end; @@ -221,7 +222,7 @@ end: } static void on_oauth2_token_fetcher_http_response(void* user_data, - grpc_error* error) { + grpc_error_handle error) { GRPC_LOG_IF_ERROR("oauth_fetch", GRPC_ERROR_REF(error)); grpc_credentials_metadata_request* r = static_cast(user_data); @@ -231,7 +232,7 @@ static void on_oauth2_token_fetcher_http_response(void* user_data, } void grpc_oauth2_token_fetcher_credentials::on_http_response( - grpc_credentials_metadata_request* r, grpc_error* error) { + grpc_credentials_metadata_request* r, grpc_error_handle error) { grpc_mdelem access_token_md = GRPC_MDNULL; grpc_millis token_lifetime = 0; grpc_credentials_status status = @@ -253,7 +254,7 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response( gpr_mu_unlock(&mu_); // Invoke callbacks for all pending requests. while (pending_request != nullptr) { - grpc_error* new_error = GRPC_ERROR_NONE; + grpc_error_handle new_error = GRPC_ERROR_NONE; if (status == GRPC_CREDENTIALS_OK) { grpc_credentials_mdelem_array_add(pending_request->md_array, access_token_md); @@ -277,7 +278,7 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response( bool grpc_oauth2_token_fetcher_credentials::get_request_metadata( grpc_polling_entity* pollent, grpc_auth_metadata_context /*context*/, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** /*error*/) { + grpc_error_handle* /*error*/) { // Check if we can use the cached token. grpc_millis refresh_threshold = GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS * GPR_MS_PER_SEC; @@ -325,7 +326,7 @@ bool grpc_oauth2_token_fetcher_credentials::get_request_metadata( } void grpc_oauth2_token_fetcher_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* md_array, grpc_error* error) { + grpc_credentials_mdelem_array* md_array, grpc_error_handle error) { gpr_mu_lock(&mu_); grpc_oauth2_pending_get_request_metadata* prev = nullptr; grpc_oauth2_pending_get_request_metadata* pending_request = pending_requests_; @@ -525,8 +526,8 @@ void MaybeAddToBody(const char* field_name, const char* field, body->push_back(absl::StrFormat("&%s=%s", field_name, field)); } -grpc_error* LoadTokenFile(const char* path, gpr_slice* token) { - grpc_error* err = grpc_load_file(path, 1, token); +grpc_error_handle LoadTokenFile(const char* path, gpr_slice* token) { + grpc_error_handle err = grpc_load_file(path, 1, token); if (err != GRPC_ERROR_NONE) return err; if (GRPC_SLICE_LENGTH(*token) == 0) { gpr_log(GPR_ERROR, "Token file %s is empty", path); @@ -565,7 +566,7 @@ class StsTokenFetcherCredentials grpc_millis deadline) override { char* body = nullptr; size_t body_length = 0; - grpc_error* err = FillBody(&body, &body_length); + grpc_error_handle err = FillBody(&body, &body_length); if (err != GRPC_ERROR_NONE) { response_cb(metadata_req, err); GRPC_ERROR_UNREF(err); @@ -598,12 +599,12 @@ class StsTokenFetcherCredentials gpr_free(body); } - grpc_error* FillBody(char** body, size_t* body_length) { + grpc_error_handle FillBody(char** body, size_t* body_length) { *body = nullptr; std::vector body_parts; grpc_slice subject_token = grpc_empty_slice(); grpc_slice actor_token = grpc_empty_slice(); - grpc_error* err = GRPC_ERROR_NONE; + grpc_error_handle err = GRPC_ERROR_NONE; auto cleanup = [&body, &body_length, &body_parts, &subject_token, &actor_token, &err]() { @@ -656,7 +657,7 @@ class StsTokenFetcherCredentials absl::StatusOr ValidateStsCredentialsOptions( const grpc_sts_credentials_options* options) { - absl::InlinedVector error_list; + absl::InlinedVector error_list; absl::StatusOr sts_url = URI::Parse(options->token_exchange_service_uri == nullptr ? "" @@ -685,7 +686,8 @@ absl::StatusOr ValidateStsCredentialsOptions( } auto grpc_error_vec = GRPC_ERROR_CREATE_FROM_VECTOR( "Invalid STS Credentials Options", &error_list); - auto retval = absl::InvalidArgumentError(grpc_error_string(grpc_error_vec)); + auto retval = + absl::InvalidArgumentError(grpc_error_std_string(grpc_error_vec)); GRPC_ERROR_UNREF(grpc_error_vec); return retval; } @@ -718,13 +720,13 @@ grpc_access_token_credentials::~grpc_access_token_credentials() { bool grpc_access_token_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/, grpc_credentials_mdelem_array* md_array, - grpc_closure* /*on_request_metadata*/, grpc_error** /*error*/) { + grpc_closure* /*on_request_metadata*/, grpc_error_handle* /*error*/) { grpc_credentials_mdelem_array_add(md_array, access_token_md_); return true; } void grpc_access_token_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* /*md_array*/, grpc_error* error) { + grpc_credentials_mdelem_array* /*md_array*/, grpc_error_handle error) { GRPC_ERROR_UNREF(error); } diff --git a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h index 264291965eb..f174112b0de 100644 --- a/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +++ b/src/core/lib/security/credentials/oauth2/oauth2_credentials.h @@ -78,13 +78,13 @@ class grpc_oauth2_token_fetcher_credentials : public grpc_call_credentials { grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error* error) override; + grpc_error_handle error) override; void on_http_response(grpc_credentials_metadata_request* r, - grpc_error* error); + grpc_error_handle error); std::string debug_string() override; protected: @@ -138,10 +138,10 @@ class grpc_access_token_credentials final : public grpc_call_credentials { grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error* error) override; + grpc_error_handle error) override; std::string debug_string() override; diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.cc b/src/core/lib/security/credentials/plugin/plugin_credentials.cc index a5b01cd84e8..4c583ad363e 100644 --- a/src/core/lib/security/credentials/plugin/plugin_credentials.cc +++ b/src/core/lib/security/credentials/plugin/plugin_credentials.cc @@ -82,10 +82,10 @@ void grpc_plugin_credentials::pending_request_complete(pending_request* r) { Unref(); } -static grpc_error* process_plugin_result( +static grpc_error_handle process_plugin_result( grpc_plugin_credentials::pending_request* r, const grpc_metadata* md, size_t num_md, grpc_status_code status, const char* error_details) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (status != GRPC_STATUS_OK) { error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("Getting metadata from plugin failed with error: ", @@ -142,7 +142,7 @@ static void plugin_md_request_metadata_ready(void* request, r->creds->pending_request_complete(r); // If it has not been cancelled, process it. if (!r->cancelled) { - grpc_error* error = + grpc_error_handle error = process_plugin_result(r, md, num_md, status, error_details); grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_request_metadata, error); } else if (GRPC_TRACE_FLAG_ENABLED(grpc_plugin_credentials_trace)) { @@ -157,7 +157,7 @@ static void plugin_md_request_metadata_ready(void* request, bool grpc_plugin_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) { + grpc_error_handle* error) { bool retval = true; // Synchronous return. if (plugin_.get_metadata != nullptr) { // Create pending_request object. @@ -231,7 +231,7 @@ bool grpc_plugin_credentials::get_request_metadata( } void grpc_plugin_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* md_array, grpc_error* error) { + grpc_credentials_mdelem_array* md_array, grpc_error_handle error) { gpr_mu_lock(&mu_); for (pending_request* pending_request = pending_requests_; pending_request != nullptr; pending_request = pending_request->next) { diff --git a/src/core/lib/security/credentials/plugin/plugin_credentials.h b/src/core/lib/security/credentials/plugin/plugin_credentials.h index 881eded7643..68351868390 100644 --- a/src/core/lib/security/credentials/plugin/plugin_credentials.h +++ b/src/core/lib/security/credentials/plugin/plugin_credentials.h @@ -47,10 +47,10 @@ struct grpc_plugin_credentials final : public grpc_call_credentials { grpc_auth_metadata_context context, grpc_credentials_mdelem_array* md_array, grpc_closure* on_request_metadata, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error* error) override; + grpc_error_handle error) override; // Checks if the request has been cancelled. // If not, removes it from the pending list, so that it cannot be diff --git a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc index 179df8da114..e831aa5c0a2 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.cc @@ -100,8 +100,9 @@ bool grpc_tls_certificate_distributor::HasKeyCertPairs( }; void grpc_tls_certificate_distributor::SetErrorForCert( - const std::string& cert_name, absl::optional root_cert_error, - absl::optional identity_cert_error) { + const std::string& cert_name, + absl::optional root_cert_error, + absl::optional 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]; @@ -112,7 +113,7 @@ void grpc_tls_certificate_distributor::SetErrorForCert( 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; + grpc_error_handle 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; @@ -133,7 +134,7 @@ void grpc_tls_certificate_distributor::SetErrorForCert( 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; + grpc_error_handle 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 @@ -151,7 +152,7 @@ void grpc_tls_certificate_distributor::SetErrorForCert( } }; -void grpc_tls_certificate_distributor::SetError(grpc_error* error) { +void grpc_tls_certificate_distributor::SetError(grpc_error_handle error) { GPR_ASSERT(error != GRPC_ERROR_NONE); grpc_core::MutexLock lock(&mu_); for (const auto& watcher : watchers_) { @@ -194,8 +195,8 @@ void grpc_tls_certificate_distributor::WatchTlsCertificates( identity_cert_name}; absl::optional updated_root_certs; absl::optional updated_identity_pairs; - grpc_error* root_error = GRPC_ERROR_NONE; - grpc_error* identity_error = GRPC_ERROR_NONE; + grpc_error_handle root_error = GRPC_ERROR_NONE; + grpc_error_handle 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(); diff --git a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h index 9ce94433c29..36c46beff9b 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_distributor.h @@ -68,8 +68,8 @@ struct grpc_tls_certificate_distributor // 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; + virtual void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) = 0; }; // Sets the key materials based on their certificate name. @@ -95,14 +95,14 @@ struct grpc_tls_certificate_distributor // @param identity_cert_error The error that the caller encounters when // reloading identity certs. void SetErrorForCert(const std::string& cert_name, - absl::optional root_cert_error, - absl::optional identity_cert_error); + absl::optional root_cert_error, + absl::optional 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); + void SetError(grpc_error_handle error); // Sets the TLS certificate watch status callback function. The // grpc_tls_certificate_distributor will invoke this callback when a new @@ -169,9 +169,9 @@ struct grpc_tls_certificate_distributor // The contents of the identity key-certificate pairs. grpc_core::PemKeyCertPairList pem_key_cert_pairs; // The root cert reloading error propagated by the caller. - grpc_error* root_cert_error = GRPC_ERROR_NONE; + grpc_error_handle root_cert_error = GRPC_ERROR_NONE; // The identity cert reloading error propagated by the caller. - grpc_error* identity_cert_error = GRPC_ERROR_NONE; + grpc_error_handle 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. @@ -185,11 +185,11 @@ struct grpc_tls_certificate_distributor GRPC_ERROR_UNREF(root_cert_error); GRPC_ERROR_UNREF(identity_cert_error); } - void SetRootError(grpc_error* error) { + void SetRootError(grpc_error_handle error) { GRPC_ERROR_UNREF(root_cert_error); root_cert_error = error; } - void SetIdentityError(grpc_error* error) { + void SetIdentityError(grpc_error_handle error) { GRPC_ERROR_UNREF(identity_cert_error); identity_cert_error = error; } diff --git a/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc index 2dae03c99fb..b4b6bf556c9 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc +++ b/src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.cc @@ -60,8 +60,8 @@ StaticDataCertificateProvider::StaticDataCertificateProvider( distributor_->SetKeyMaterials(cert_name, std::move(root_certificate), std::move(pem_key_cert_pairs)); } - grpc_error* root_cert_error = GRPC_ERROR_NONE; - grpc_error* identity_cert_error = GRPC_ERROR_NONE; + grpc_error_handle root_cert_error = GRPC_ERROR_NONE; + grpc_error_handle identity_cert_error = GRPC_ERROR_NONE; if (root_being_watched && !root_has_update) { root_cert_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unable to get latest root certificates."); @@ -150,8 +150,8 @@ FileWatcherCertificateProvider::FileWatcherCertificateProvider( distributor_->SetKeyMaterials(cert_name, root_certificate, pem_key_cert_pairs); } - grpc_error* root_cert_error = GRPC_ERROR_NONE; - grpc_error* identity_cert_error = GRPC_ERROR_NONE; + grpc_error_handle root_cert_error = GRPC_ERROR_NONE; + grpc_error_handle identity_cert_error = GRPC_ERROR_NONE; if (root_being_watched && !root_certificate.has_value()) { root_cert_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unable to get latest root certificates."); @@ -210,10 +210,11 @@ void FileWatcherCertificateProvider::ForceUpdate() { } if (root_cert_changed || identity_cert_changed) { ExecCtx exec_ctx; - grpc_error* root_cert_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + grpc_error_handle root_cert_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Unable to get latest root certificates."); - grpc_error* identity_cert_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Unable to get latest identity certificates."); + grpc_error_handle identity_cert_error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Unable to get latest identity certificates."); for (const auto& p : watcher_info_) { const std::string& cert_name = p.first; const WatcherInfo& info = p.second; @@ -256,11 +257,12 @@ FileWatcherCertificateProvider::ReadRootCertificatesFromFile( const std::string& root_cert_full_path) { // Read the root file. grpc_slice root_slice = grpc_empty_slice(); - grpc_error* root_error = + grpc_error_handle root_error = grpc_load_file(root_cert_full_path.c_str(), 0, &root_slice); if (root_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Reading file %s failed: %s", - root_cert_full_path.c_str(), grpc_error_string(root_error)); + root_cert_full_path.c_str(), + grpc_error_std_string(root_error).c_str()); GRPC_ERROR_UNREF(root_error); return absl::nullopt; } @@ -314,19 +316,21 @@ FileWatcherCertificateProvider::ReadIdentityKeyCertPairFromFiles( } // Read the identity files. SliceWrapper key_slice, cert_slice; - grpc_error* key_error = + grpc_error_handle key_error = grpc_load_file(private_key_path.c_str(), 0, &key_slice.slice); if (key_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Reading file %s failed: %s. Start retrying...", - private_key_path.c_str(), grpc_error_string(key_error)); + private_key_path.c_str(), + grpc_error_std_string(key_error).c_str()); GRPC_ERROR_UNREF(key_error); continue; } - grpc_error* cert_error = + grpc_error_handle cert_error = grpc_load_file(identity_certificate_path.c_str(), 0, &cert_slice.slice); if (cert_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "Reading file %s failed: %s. Start retrying...", - identity_certificate_path.c_str(), grpc_error_string(cert_error)); + identity_certificate_path.c_str(), + grpc_error_std_string(cert_error).c_str()); GRPC_ERROR_UNREF(cert_error); continue; } @@ -367,6 +371,7 @@ FileWatcherCertificateProvider::ReadIdentityKeyCertPairFromFiles( grpc_tls_certificate_provider* grpc_tls_certificate_provider_static_data_create( const char* root_certificate, grpc_tls_identity_pairs* pem_key_cert_pairs) { GPR_ASSERT(root_certificate != nullptr || pem_key_cert_pairs != nullptr); + grpc_core::ExecCtx exec_ctx; grpc_core::PemKeyCertPairList identity_pairs_core; if (pem_key_cert_pairs != nullptr) { identity_pairs_core = std::move(pem_key_cert_pairs->pem_key_cert_pairs); @@ -384,6 +389,7 @@ grpc_tls_certificate_provider* grpc_tls_certificate_provider_file_watcher_create( const char* private_key_path, const char* identity_certificate_path, const char* root_cert_path, unsigned int refresh_interval_sec) { + grpc_core::ExecCtx exec_ctx; return new grpc_core::FileWatcherCertificateProvider( private_key_path == nullptr ? "" : private_key_path, identity_certificate_path == nullptr ? "" : identity_certificate_path, diff --git a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc index cf2b4c60df9..bf26e707e33 100644 --- a/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +++ b/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc @@ -87,6 +87,7 @@ void grpc_tls_server_authorization_check_config::Cancel( /** -- Wrapper APIs declared in grpc_security.h -- **/ grpc_tls_credentials_options* grpc_tls_credentials_options_create() { + grpc_core::ExecCtx exec_ctx; return new grpc_tls_credentials_options(); } @@ -109,6 +110,7 @@ void grpc_tls_credentials_options_set_certificate_provider( grpc_tls_certificate_provider* provider) { GPR_ASSERT(options != nullptr); GPR_ASSERT(provider != nullptr); + grpc_core::ExecCtx exec_ctx; options->set_certificate_provider( provider->Ref(DEBUG_LOCATION, "set_certificate_provider")); } @@ -142,6 +144,7 @@ void grpc_tls_credentials_options_set_server_authorization_check_config( grpc_tls_server_authorization_check_config* config) { GPR_ASSERT(options != nullptr); GPR_ASSERT(config != nullptr); + grpc_core::ExecCtx exec_ctx; options->set_server_authorization_check_config(config->Ref()); } @@ -159,6 +162,7 @@ grpc_tls_server_authorization_check_config_create( "check config."); return nullptr; } + grpc_core::ExecCtx exec_ctx; return new grpc_tls_server_authorization_check_config( config_user_data, schedule, cancel, destruct); } diff --git a/src/core/lib/security/credentials/xds/xds_credentials.cc b/src/core/lib/security/credentials/xds/xds_credentials.cc index a82a7d06c22..15b8e900fcb 100644 --- a/src/core/lib/security/credentials/xds/xds_credentials.cc +++ b/src/core/lib/security/credentials/xds/xds_credentials.cc @@ -40,13 +40,13 @@ bool XdsVerifySubjectAlternativeNames( if (matchers.empty()) return true; for (size_t i = 0; i < subject_alternative_names_size; ++i) { for (const auto& matcher : matchers) { - if (matcher.type() == StringMatcher::Type::EXACT) { - // For EXACT match, use DNS rules for verifying SANs + if (matcher.type() == StringMatcher::Type::kExact) { + // For Exact match, use DNS rules for verifying SANs // TODO(zhenlian): Right now, the SSL layer does not save the type of // the SAN, so we are doing a DNS style verification for all SANs when // the type is EXACT. When we expose the SAN type, change this to only // do this verification when the SAN type is DNS and match type is - // EXACT. For all other cases, we should use matcher.Match(). + // kExact. For all other cases, we should use matcher.Match(). if (VerifySubjectAlternativeName(subject_alternative_names[i], matcher.string_matcher())) { return true; diff --git a/src/core/lib/security/security_connector/alts/alts_security_connector.cc b/src/core/lib/security/security_connector/alts/alts_security_connector.cc index 64c39e6d5e3..131436dfe9d 100644 --- a/src/core/lib/security/security_connector/alts/alts_security_connector.cc +++ b/src/core/lib/security/security_connector/alts/alts_security_connector.cc @@ -54,7 +54,7 @@ void alts_check_peer(tsi_peer peer, *auth_context = grpc_core::internal::grpc_alts_auth_context_from_tsi_peer(&peer); tsi_peer_destruct(&peer); - grpc_error* error = + grpc_error_handle error = *auth_context != nullptr ? GRPC_ERROR_NONE : GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -103,6 +103,11 @@ class grpc_alts_channel_security_connector final alts_check_peer(peer, auth_context, on_peer_checked); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other_sc) const override { auto* other = reinterpret_cast(other_sc); @@ -114,7 +119,7 @@ class grpc_alts_channel_security_connector final bool check_call_host(absl::string_view host, grpc_auth_context* /*auth_context*/, grpc_closure* /*on_call_host_checked*/, - grpc_error** error) override { + grpc_error_handle* error) override { if (host.empty() || host != target_name_) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "ALTS call host does not match target name"); @@ -123,7 +128,7 @@ class grpc_alts_channel_security_connector final } void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/, - grpc_error* error) override { + grpc_error_handle error) override { GRPC_ERROR_UNREF(error); } @@ -168,6 +173,11 @@ class grpc_alts_server_security_connector final alts_check_peer(peer, auth_context, on_peer_checked); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other) const override { return server_security_connector_cmp( static_cast(other)); diff --git a/src/core/lib/security/security_connector/fake/fake_security_connector.cc b/src/core/lib/security/security_connector/fake/fake_security_connector.cc index fdf750f4ede..0e25fb026e6 100644 --- a/src/core/lib/security/security_connector/fake/fake_security_connector.cc +++ b/src/core/lib/security/security_connector/fake/fake_security_connector.cc @@ -79,6 +79,11 @@ class grpc_fake_channel_security_connector final grpc_core::RefCountedPtr* auth_context, grpc_closure* on_peer_checked) override; + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other_sc) const override { auto* other = reinterpret_cast(other_sc); @@ -105,7 +110,7 @@ class grpc_fake_channel_security_connector final bool check_call_host(absl::string_view host, grpc_auth_context* /*auth_context*/, grpc_closure* /*on_call_host_checked*/, - grpc_error** /*error*/) override { + grpc_error_handle* /*error*/) override { absl::string_view authority_hostname; absl::string_view authority_ignored_port; absl::string_view target_hostname; @@ -135,7 +140,7 @@ class grpc_fake_channel_security_connector final } void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/, - grpc_error* error) override { + grpc_error_handle error) override { GRPC_ERROR_UNREF(error); } @@ -214,7 +219,7 @@ static void fake_check_peer( grpc_core::RefCountedPtr* auth_context, grpc_closure* on_peer_checked) { const char* prop_name; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; *auth_context = nullptr; if (peer.property_count != 2) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -287,6 +292,11 @@ class grpc_fake_server_security_connector fake_check_peer(this, peer, auth_context, on_peer_checked); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + void add_handshakers(const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/, grpc_core::HandshakeManager* handshake_mgr) override { diff --git a/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc b/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc index ba0b89a94ec..360764e136a 100644 --- a/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc +++ b/src/core/lib/security/security_connector/insecure/insecure_security_connector.cc @@ -52,13 +52,13 @@ RefCountedPtr TestOnlyMakeInsecureAuthContext() { // provide an insecure channel. bool InsecureChannelSecurityConnector::check_call_host( absl::string_view /*host*/, grpc_auth_context* /*auth_context*/, - grpc_closure* /*on_call_host_checked*/, grpc_error** error) { + grpc_closure* /*on_call_host_checked*/, grpc_error_handle* error) { *error = GRPC_ERROR_NONE; return true; } void InsecureChannelSecurityConnector::cancel_check_call_host( - grpc_closure* /*on_call_host_checked*/, grpc_error* error) { + grpc_closure* /*on_call_host_checked*/, grpc_error_handle error) { GRPC_ERROR_UNREF(error); } diff --git a/src/core/lib/security/security_connector/insecure/insecure_security_connector.h b/src/core/lib/security/security_connector/insecure/insecure_security_connector.h index 7d0f79e90f1..352e346c1aa 100644 --- a/src/core/lib/security/security_connector/insecure/insecure_security_connector.h +++ b/src/core/lib/security/security_connector/insecure/insecure_security_connector.h @@ -47,10 +47,10 @@ class InsecureChannelSecurityConnector bool check_call_host(absl::string_view host, grpc_auth_context* auth_context, grpc_closure* on_call_host_checked, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_check_call_host(grpc_closure* on_call_host_checked, - grpc_error* error) override; + grpc_error_handle error) override; void add_handshakers(const grpc_channel_args* args, grpc_pollset_set* /* interested_parties */, @@ -60,6 +60,11 @@ class InsecureChannelSecurityConnector grpc_core::RefCountedPtr* auth_context, grpc_closure* on_peer_checked) override; + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other_sc) const override; }; @@ -78,6 +83,11 @@ class InsecureServerSecurityConnector : public grpc_server_security_connector { grpc_core::RefCountedPtr* auth_context, grpc_closure* on_peer_checked) override; + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other) const override; }; diff --git a/src/core/lib/security/security_connector/load_system_roots_linux.cc b/src/core/lib/security/security_connector/load_system_roots_linux.cc index f7c6c2cec35..4cd709f77f6 100644 --- a/src/core/lib/security/security_connector/load_system_roots_linux.cc +++ b/src/core/lib/security/security_connector/load_system_roots_linux.cc @@ -63,7 +63,7 @@ grpc_slice GetSystemRootCerts() { grpc_slice valid_bundle_slice = grpc_empty_slice(); size_t num_cert_files_ = GPR_ARRAY_SIZE(kLinuxCertFiles); for (size_t i = 0; i < num_cert_files_; i++) { - grpc_error* error = + grpc_error_handle error = grpc_load_file(kLinuxCertFiles[i], 1, &valid_bundle_slice); if (error == GRPC_ERROR_NONE) { return valid_bundle_slice; diff --git a/src/core/lib/security/security_connector/local/local_security_connector.cc b/src/core/lib/security/security_connector/local/local_security_connector.cc index 2cec0dbb9a5..1c1cfe9248f 100644 --- a/src/core/lib/security/security_connector/local/local_security_connector.cc +++ b/src/core/lib/security/security_connector/local/local_security_connector.cc @@ -29,12 +29,12 @@ #include #include "src/core/ext/filters/client_channel/client_channel.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" #include "src/core/lib/security/credentials/local/local_credentials.h" @@ -103,7 +103,7 @@ void local_check_peer(tsi_peer peer, grpc_endpoint* ep, } } } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (!is_endpoint_local) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Endpoint is neither UDS or TCP loopback address."); @@ -181,10 +181,15 @@ class grpc_local_channel_security_connector final creds->connect_type()); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + bool check_call_host(absl::string_view host, grpc_auth_context* /*auth_context*/, grpc_closure* /*on_call_host_checked*/, - grpc_error** error) override { + grpc_error_handle* error) override { if (host.empty() || host != target_name_) { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "local call host does not match target name"); @@ -193,7 +198,7 @@ class grpc_local_channel_security_connector final } void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/, - grpc_error* error) override { + grpc_error_handle error) override { GRPC_ERROR_UNREF(error); } @@ -230,6 +235,11 @@ class grpc_local_server_security_connector final creds->connect_type()); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other) const override { return server_security_connector_cmp( static_cast(other)); diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h index 204b6957462..50d9af376b7 100644 --- a/src/core/lib/security/security_connector/security_connector.h +++ b/src/core/lib/security/security_connector/security_connector.h @@ -55,13 +55,18 @@ class grpc_security_connector url_scheme_(url_scheme) {} ~grpc_security_connector() override = default; - /* Check the peer. Callee takes ownership of the peer object. - When done, sets *auth_context and invokes on_peer_checked. */ + // Checks the peer. Callee takes ownership of the peer object. + // When done, sets *auth_context and invokes on_peer_checked. virtual void check_peer( tsi_peer peer, grpc_endpoint* ep, grpc_core::RefCountedPtr* auth_context, grpc_closure* on_peer_checked) = 0; + // Cancels the pending check_peer() request associated with on_peer_checked. + // If there is no such request pending, this is a no-op. + virtual void cancel_check_peer(grpc_closure* on_peer_checked, + grpc_error_handle error) = 0; + /* Compares two security connectors. */ virtual int cmp(const grpc_security_connector* other) const = 0; @@ -103,12 +108,12 @@ class grpc_channel_security_connector : public grpc_security_connector { virtual bool check_call_host(absl::string_view host, grpc_auth_context* auth_context, grpc_closure* on_call_host_checked, - grpc_error** error) = 0; + grpc_error_handle* error) = 0; /// Cancels a pending asynchronous call to /// grpc_channel_security_connector_check_call_host() with /// \a on_call_host_checked as its callback. virtual void cancel_check_call_host(grpc_closure* on_call_host_checked, - grpc_error* error) = 0; + grpc_error_handle error) = 0; /// Registers handshakers with \a handshake_mgr. virtual void add_handshakers(const grpc_channel_args* args, grpc_pollset_set* interested_parties, diff --git a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc index ee5672b955a..3e424e35f8b 100644 --- a/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc +++ b/src/core/lib/security/security_connector/ssl/ssl_security_connector.cc @@ -45,10 +45,10 @@ #include "src/core/tsi/transport_security.h" namespace { -grpc_error* ssl_check_peer( +grpc_error_handle ssl_check_peer( const char* peer_name, const tsi_peer* peer, grpc_core::RefCountedPtr* auth_context) { - grpc_error* error = grpc_ssl_check_alpn(peer); + grpc_error_handle error = grpc_ssl_check_alpn(peer); if (error != GRPC_ERROR_NONE) { return error; } @@ -145,7 +145,7 @@ class grpc_ssl_channel_security_connector final const char* target_name = overridden_target_name_.empty() ? target_name_.c_str() : overridden_target_name_.c_str(); - grpc_error* error = ssl_check_peer(target_name, &peer, auth_context); + grpc_error_handle error = ssl_check_peer(target_name, &peer, auth_context); if (error == GRPC_ERROR_NONE && verify_options_->verify_peer_callback != nullptr) { const tsi_peer_property* p = @@ -173,6 +173,11 @@ class grpc_ssl_channel_security_connector final tsi_peer_destruct(&peer); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other_sc) const override { auto* other = reinterpret_cast(other_sc); @@ -185,14 +190,14 @@ class grpc_ssl_channel_security_connector final bool check_call_host(absl::string_view host, grpc_auth_context* auth_context, grpc_closure* /*on_call_host_checked*/, - grpc_error** error) override { + grpc_error_handle* error) override { return grpc_ssl_check_call_host(host, target_name_.c_str(), overridden_target_name_.c_str(), auth_context, error); } void cancel_check_call_host(grpc_closure* /*on_call_host_checked*/, - grpc_error* error) override { + grpc_error_handle error) override { GRPC_ERROR_UNREF(error); } @@ -288,11 +293,16 @@ class grpc_ssl_server_security_connector void check_peer(tsi_peer peer, grpc_endpoint* /*ep*/, grpc_core::RefCountedPtr* auth_context, grpc_closure* on_peer_checked) override { - grpc_error* error = ssl_check_peer(nullptr, &peer, auth_context); + grpc_error_handle error = ssl_check_peer(nullptr, &peer, auth_context); tsi_peer_destruct(&peer); grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); } + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other) const override { return server_security_connector_cmp( static_cast(other)); diff --git a/src/core/lib/security/security_connector/ssl_utils.cc b/src/core/lib/security/security_connector/ssl_utils.cc index b0247cdb8c6..f445be9c77b 100644 --- a/src/core/lib/security/security_connector/ssl_utils.cc +++ b/src/core/lib/security/security_connector/ssl_utils.cc @@ -152,7 +152,7 @@ tsi_tls_version grpc_get_tsi_tls_version(grpc_tls_version tls_version) { } } -grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer) { +grpc_error_handle grpc_ssl_check_alpn(const tsi_peer* peer) { #if TSI_OPENSSL_ALPN_SUPPORT /* Check the ALPN if ALPN is supported. */ const tsi_peer_property* p = @@ -169,8 +169,8 @@ grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer) { return GRPC_ERROR_NONE; } -grpc_error* grpc_ssl_check_peer_name(absl::string_view peer_name, - const tsi_peer* peer) { +grpc_error_handle grpc_ssl_check_peer_name(absl::string_view peer_name, + const tsi_peer* peer) { /* Check the peer name if specified. */ if (!peer_name.empty() && !grpc_ssl_host_matches_name(peer, peer_name)) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -184,7 +184,7 @@ bool grpc_ssl_check_call_host(absl::string_view host, absl::string_view target_name, absl::string_view overridden_target_name, grpc_auth_context* auth_context, - grpc_error** error) { + grpc_error_handle* error) { grpc_security_status status = GRPC_SECURITY_ERROR; tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context); if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK; @@ -305,6 +305,9 @@ grpc_core::RefCountedPtr grpc_ssl_peer_to_auth_context( grpc_auth_context_add_property( ctx.get(), GRPC_TRANSPORT_SECURITY_LEVEL_PROPERTY_NAME, prop->value.data, prop->value.length); + } else if (strcmp(prop->name, TSI_X509_DNS_PEER_PROPERTY) == 0) { + grpc_auth_context_add_property(ctx.get(), GRPC_PEER_DNS_PROPERTY_NAME, + prop->value.data, prop->value.length); } else if (strcmp(prop->name, TSI_X509_URI_PEER_PROPERTY) == 0) { uri_count++; absl::string_view spiffe_id(prop->value.data, prop->value.length); @@ -313,6 +316,12 @@ grpc_core::RefCountedPtr grpc_ssl_peer_to_auth_context( spiffe_length = prop->value.length; has_spiffe_id = true; } + } else if (strcmp(prop->name, TSI_X509_EMAIL_PEER_PROPERTY) == 0) { + grpc_auth_context_add_property(ctx.get(), GRPC_PEER_EMAIL_PROPERTY_NAME, + prop->value.data, prop->value.length); + } else if (strcmp(prop->name, TSI_X509_IP_PEER_PROPERTY) == 0) { + grpc_auth_context_add_property(ctx.get(), GRPC_PEER_IP_PROPERTY_NAME, + prop->value.data, prop->value.length); } } if (peer_identity_property_name != nullptr) { @@ -376,9 +385,18 @@ tsi_peer grpc_shallow_peer_from_ssl_auth_context( 0) { add_shallow_auth_property_to_peer(&peer, prop, TSI_X509_PEM_CERT_CHAIN_PROPERTY); + } else if (strcmp(prop->name, GRPC_PEER_DNS_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer(&peer, prop, + TSI_X509_DNS_PEER_PROPERTY); } else if (strcmp(prop->name, GRPC_PEER_SPIFFE_ID_PROPERTY_NAME) == 0) { add_shallow_auth_property_to_peer(&peer, prop, TSI_X509_URI_PEER_PROPERTY); + } else if (strcmp(prop->name, GRPC_PEER_EMAIL_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer(&peer, prop, + TSI_X509_EMAIL_PEER_PROPERTY); + } else if (strcmp(prop->name, GRPC_PEER_IP_PROPERTY_NAME) == 0) { + add_shallow_auth_property_to_peer(&peer, prop, + TSI_X509_IP_PEER_PROPERTY); } } } diff --git a/src/core/lib/security/security_connector/ssl_utils.h b/src/core/lib/security/security_connector/ssl_utils.h index 562a08c9697..1c41a5434cb 100644 --- a/src/core/lib/security/security_connector/ssl_utils.h +++ b/src/core/lib/security/security_connector/ssl_utils.h @@ -44,11 +44,11 @@ #define GRPC_SSL_URL_SCHEME "https" /* Check ALPN information returned from SSL handshakes. */ -grpc_error* grpc_ssl_check_alpn(const tsi_peer* peer); +grpc_error_handle grpc_ssl_check_alpn(const tsi_peer* peer); /* Check peer name information returned from SSL handshakes. */ -grpc_error* grpc_ssl_check_peer_name(absl::string_view peer_name, - const tsi_peer* peer); +grpc_error_handle grpc_ssl_check_peer_name(absl::string_view peer_name, + const tsi_peer* peer); /* Compare targer_name information extracted from SSL security connectors. */ int grpc_ssl_cmp_target_name(absl::string_view target_name, absl::string_view other_target_name, @@ -59,7 +59,7 @@ bool grpc_ssl_check_call_host(absl::string_view host, absl::string_view target_name, absl::string_view overridden_target_name, grpc_auth_context* auth_context, - grpc_error** error); + grpc_error_handle* error); /* Return HTTP2-compliant cipher suites that gRPC accepts by default. */ const char* grpc_get_ssl_cipher_suites(void); diff --git a/src/core/lib/security/security_connector/tls/tls_security_connector.cc b/src/core/lib/security/security_connector/tls/tls_security_connector.cc index 22cc616b39b..ea6b42e07d6 100644 --- a/src/core/lib/security/security_connector/tls/tls_security_connector.cc +++ b/src/core/lib/security/security_connector/tls/tls_security_connector.cc @@ -46,7 +46,7 @@ namespace grpc_core { namespace { tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair( - const grpc_core::PemKeyCertPairList& cert_pair_list) { + const PemKeyCertPairList& cert_pair_list) { tsi_ssl_pem_key_cert_pair* tsi_pairs = nullptr; size_t num_key_cert_pairs = cert_pair_list.size(); if (num_key_cert_pairs > 0) { @@ -68,11 +68,11 @@ tsi_ssl_pem_key_cert_pair* ConvertToTsiPemKeyCertPair( } // namespace // -------------------channel security connector------------------- -grpc_core::RefCountedPtr +RefCountedPtr TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector( - grpc_core::RefCountedPtr channel_creds, - grpc_core::RefCountedPtr options, - grpc_core::RefCountedPtr request_metadata_creds, + RefCountedPtr channel_creds, + RefCountedPtr options, + RefCountedPtr request_metadata_creds, const char* target_name, const char* overridden_target_name, tsi_ssl_session_cache* ssl_session_cache) { if (channel_creds == nullptr) { @@ -93,18 +93,16 @@ TlsChannelSecurityConnector::CreateTlsChannelSecurityConnector( "TlsChannelSecurityConnectorCreate()"); return nullptr; } - grpc_core::RefCountedPtr c = - grpc_core::MakeRefCounted( - std::move(channel_creds), std::move(options), - std::move(request_metadata_creds), target_name, - overridden_target_name, ssl_session_cache); - return c; + return MakeRefCounted( + std::move(channel_creds), std::move(options), + std::move(request_metadata_creds), target_name, overridden_target_name, + ssl_session_cache); } TlsChannelSecurityConnector::TlsChannelSecurityConnector( - grpc_core::RefCountedPtr channel_creds, - grpc_core::RefCountedPtr options, - grpc_core::RefCountedPtr request_metadata_creds, + RefCountedPtr channel_creds, + RefCountedPtr options, + RefCountedPtr request_metadata_creds, const char* target_name, const char* overridden_target_name, tsi_ssl_session_cache* ssl_session_cache) : grpc_channel_security_connector(GRPC_SSL_URL_SCHEME, @@ -120,7 +118,7 @@ TlsChannelSecurityConnector::TlsChannelSecurityConnector( check_arg_ = ServerAuthorizationCheckArgCreate(this); absl::string_view host; absl::string_view port; - grpc_core::SplitHostPort(target_name, &host, &port); + SplitHostPort(target_name, &host, &port); target_name_ = std::string(host); // Create a watcher. auto watcher_ptr = absl::make_unique(this); @@ -172,8 +170,8 @@ TlsChannelSecurityConnector::~TlsChannelSecurityConnector() { void TlsChannelSecurityConnector::add_handshakers( const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/, - grpc_core::HandshakeManager* handshake_mgr) { - grpc_core::MutexLock lock(&mu_); + HandshakeManager* handshake_mgr) { + MutexLock lock(&mu_); if (client_handshaker_factory_ != nullptr) { // Instantiate TSI handshaker. tsi_handshaker* tsi_hs = nullptr; @@ -188,7 +186,7 @@ void TlsChannelSecurityConnector::add_handshakers( return; } // Create handshakers. - handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args)); + handshake_mgr->Add(SecurityHandshakerCreate(tsi_hs, this, args)); return; } // TODO(ZhenLian): Implement the logic(delegation to @@ -199,14 +197,14 @@ void TlsChannelSecurityConnector::add_handshakers( void TlsChannelSecurityConnector::check_peer( tsi_peer peer, grpc_endpoint* /*ep*/, - grpc_core::RefCountedPtr* auth_context, + RefCountedPtr* auth_context, grpc_closure* on_peer_checked) { const char* target_name = overridden_target_name_.empty() ? target_name_.c_str() : overridden_target_name_.c_str(); - grpc_error* error = grpc_ssl_check_alpn(&peer); + grpc_error_handle error = grpc_ssl_check_alpn(&peer); if (error != GRPC_ERROR_NONE) { - grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); + ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); tsi_peer_destruct(&peer); return; } @@ -216,7 +214,7 @@ void TlsChannelSecurityConnector::check_peer( /* Do the default host name check if specifying the target name. */ error = internal::TlsCheckHostName(target_name, &peer); if (error != GRPC_ERROR_NONE) { - grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); + ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); tsi_peer_destruct(&peer); return; } @@ -299,7 +297,7 @@ void TlsChannelSecurityConnector::check_peer( error = ProcessServerAuthorizationCheckResult(check_arg_); } } - grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); + ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); tsi_peer_destruct(&peer); } @@ -317,7 +315,7 @@ int TlsChannelSecurityConnector::cmp( bool TlsChannelSecurityConnector::check_call_host( absl::string_view host, grpc_auth_context* auth_context, - grpc_closure* /*on_call_host_checked*/, grpc_error** error) { + grpc_closure* /*on_call_host_checked*/, grpc_error_handle* error) { if (options_->server_verification_option() == GRPC_TLS_SKIP_HOSTNAME_VERIFICATION || options_->server_verification_option() == @@ -330,16 +328,15 @@ bool TlsChannelSecurityConnector::check_call_host( } void TlsChannelSecurityConnector::cancel_check_call_host( - grpc_closure* /*on_call_host_checked*/, grpc_error* error) { + grpc_closure* /*on_call_host_checked*/, grpc_error_handle error) { GRPC_ERROR_UNREF(error); } void TlsChannelSecurityConnector::TlsChannelCertificateWatcher:: - OnCertificatesChanged( - absl::optional root_certs, - absl::optional key_cert_pairs) { + OnCertificatesChanged(absl::optional root_certs, + absl::optional key_cert_pairs) { GPR_ASSERT(security_connector_ != nullptr); - grpc_core::MutexLock lock(&security_connector_->mu_); + MutexLock lock(&security_connector_->mu_); if (root_certs.has_value()) { security_connector_->pem_root_certs_ = root_certs; } @@ -362,16 +359,16 @@ void TlsChannelSecurityConnector::TlsChannelCertificateWatcher:: // TODO(ZhenLian): implement the logic to signal waiting handshakers once // BlockOnInitialCredentialHandshaker is implemented. void TlsChannelSecurityConnector::TlsChannelCertificateWatcher::OnError( - grpc_error* root_cert_error, grpc_error* identity_cert_error) { + grpc_error_handle root_cert_error, grpc_error_handle identity_cert_error) { if (root_cert_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "TlsChannelCertificateWatcher getting root_cert_error: %s", - grpc_error_string(root_cert_error)); + grpc_error_std_string(root_cert_error).c_str()); } if (identity_cert_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "TlsChannelCertificateWatcher getting identity_cert_error: %s", - grpc_error_string(identity_cert_error)); + grpc_error_std_string(identity_cert_error).c_str()); } GRPC_ERROR_UNREF(root_cert_error); GRPC_ERROR_UNREF(identity_cert_error); @@ -417,16 +414,17 @@ TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() { void TlsChannelSecurityConnector::ServerAuthorizationCheckDone( grpc_tls_server_authorization_check_arg* arg) { GPR_ASSERT(arg != nullptr); - grpc_core::ExecCtx exec_ctx; - grpc_error* error = ProcessServerAuthorizationCheckResult(arg); + ExecCtx exec_ctx; + grpc_error_handle error = ProcessServerAuthorizationCheckResult(arg); TlsChannelSecurityConnector* connector = static_cast(arg->cb_user_data); - grpc_core::ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error); + ExecCtx::Run(DEBUG_LOCATION, connector->on_peer_checked_, error); } -grpc_error* TlsChannelSecurityConnector::ProcessServerAuthorizationCheckResult( +grpc_error_handle +TlsChannelSecurityConnector::ProcessServerAuthorizationCheckResult( grpc_tls_server_authorization_check_arg* arg) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; /* Server authorization check is cancelled by caller. */ if (arg->status == GRPC_STATUS_CANCELLED) { error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( @@ -491,10 +489,10 @@ void TlsChannelSecurityConnector::ServerAuthorizationCheckArgDestroy( } // -------------------server security connector------------------- -grpc_core::RefCountedPtr +RefCountedPtr TlsServerSecurityConnector::CreateTlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds, - grpc_core::RefCountedPtr options) { + RefCountedPtr server_creds, + RefCountedPtr options) { if (server_creds == nullptr) { gpr_log(GPR_ERROR, "server_creds is nullptr in " @@ -507,15 +505,13 @@ TlsServerSecurityConnector::CreateTlsServerSecurityConnector( "TlsServerSecurityConnectorCreate()"); return nullptr; } - grpc_core::RefCountedPtr c = - grpc_core::MakeRefCounted( - std::move(server_creds), std::move(options)); - return c; + return MakeRefCounted(std::move(server_creds), + std::move(options)); } TlsServerSecurityConnector::TlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds, - grpc_core::RefCountedPtr options) + RefCountedPtr server_creds, + RefCountedPtr options) : grpc_server_security_connector(GRPC_SSL_URL_SCHEME, std::move(server_creds)), options_(std::move(options)) { @@ -551,8 +547,8 @@ TlsServerSecurityConnector::~TlsServerSecurityConnector() { void TlsServerSecurityConnector::add_handshakers( const grpc_channel_args* args, grpc_pollset_set* /*interested_parties*/, - grpc_core::HandshakeManager* handshake_mgr) { - grpc_core::MutexLock lock(&mu_); + HandshakeManager* handshake_mgr) { + MutexLock lock(&mu_); if (server_handshaker_factory_ != nullptr) { // Instantiate TSI handshaker. tsi_handshaker* tsi_hs = nullptr; @@ -564,7 +560,7 @@ void TlsServerSecurityConnector::add_handshakers( return; } // Create handshakers. - handshake_mgr->Add(grpc_core::SecurityHandshakerCreate(tsi_hs, this, args)); + handshake_mgr->Add(SecurityHandshakerCreate(tsi_hs, this, args)); return; } // TODO(ZhenLian): Implement the logic(delegation to @@ -575,13 +571,13 @@ void TlsServerSecurityConnector::add_handshakers( void TlsServerSecurityConnector::check_peer( tsi_peer peer, grpc_endpoint* /*ep*/, - grpc_core::RefCountedPtr* auth_context, + RefCountedPtr* auth_context, grpc_closure* on_peer_checked) { - grpc_error* error = grpc_ssl_check_alpn(&peer); + grpc_error_handle error = grpc_ssl_check_alpn(&peer); *auth_context = grpc_ssl_peer_to_auth_context(&peer, GRPC_TLS_TRANSPORT_SECURITY_TYPE); tsi_peer_destruct(&peer); - grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); + ExecCtx::Run(DEBUG_LOCATION, on_peer_checked, error); } int TlsServerSecurityConnector::cmp( @@ -591,11 +587,10 @@ int TlsServerSecurityConnector::cmp( } void TlsServerSecurityConnector::TlsServerCertificateWatcher:: - OnCertificatesChanged( - absl::optional root_certs, - absl::optional key_cert_pairs) { + OnCertificatesChanged(absl::optional root_certs, + absl::optional key_cert_pairs) { GPR_ASSERT(security_connector_ != nullptr); - grpc_core::MutexLock lock(&security_connector_->mu_); + MutexLock lock(&security_connector_->mu_); if (root_certs.has_value()) { security_connector_->pem_root_certs_ = root_certs; } @@ -622,16 +617,16 @@ void TlsServerSecurityConnector::TlsServerCertificateWatcher:: // TODO(ZhenLian): implement the logic to signal waiting handshakers once // BlockOnInitialCredentialHandshaker is implemented. void TlsServerSecurityConnector::TlsServerCertificateWatcher::OnError( - grpc_error* root_cert_error, grpc_error* identity_cert_error) { + grpc_error_handle root_cert_error, grpc_error_handle identity_cert_error) { if (root_cert_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "TlsServerCertificateWatcher getting root_cert_error: %s", - grpc_error_string(root_cert_error)); + grpc_error_std_string(root_cert_error).c_str()); } if (identity_cert_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "TlsServerCertificateWatcher getting identity_cert_error: %s", - grpc_error_string(identity_cert_error)); + grpc_error_std_string(identity_cert_error).c_str()); } GRPC_ERROR_UNREF(root_cert_error); GRPC_ERROR_UNREF(identity_cert_error); @@ -672,7 +667,8 @@ TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() { namespace internal { -grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer) { +grpc_error_handle TlsCheckHostName(const char* peer_name, + const tsi_peer* peer) { /* Check the peer name if specified. */ if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) { return GRPC_ERROR_CREATE_FROM_COPIED_STRING( diff --git a/src/core/lib/security/security_connector/tls/tls_security_connector.h b/src/core/lib/security/security_connector/tls/tls_security_connector.h index 453c531925d..80c26954ac8 100644 --- a/src/core/lib/security/security_connector/tls/tls_security_connector.h +++ b/src/core/lib/security/security_connector/tls/tls_security_connector.h @@ -35,18 +35,18 @@ class TlsChannelSecurityConnector final : public grpc_channel_security_connector { public: // static factory method to create a TLS channel security connector. - static grpc_core::RefCountedPtr + static RefCountedPtr CreateTlsChannelSecurityConnector( - grpc_core::RefCountedPtr channel_creds, - grpc_core::RefCountedPtr options, - grpc_core::RefCountedPtr request_metadata_creds, + RefCountedPtr channel_creds, + RefCountedPtr options, + RefCountedPtr request_metadata_creds, const char* target_name, const char* overridden_target_name, tsi_ssl_session_cache* ssl_session_cache); TlsChannelSecurityConnector( - grpc_core::RefCountedPtr channel_creds, - grpc_core::RefCountedPtr options, - grpc_core::RefCountedPtr request_metadata_creds, + RefCountedPtr channel_creds, + RefCountedPtr options, + RefCountedPtr request_metadata_creds, const char* target_name, const char* overridden_target_name, tsi_ssl_session_cache* ssl_session_cache); @@ -54,33 +54,39 @@ class TlsChannelSecurityConnector final void add_handshakers(const grpc_channel_args* args, grpc_pollset_set* interested_parties, - grpc_core::HandshakeManager* handshake_mgr) override; + HandshakeManager* handshake_mgr) override; void check_peer(tsi_peer peer, grpc_endpoint* ep, - grpc_core::RefCountedPtr* auth_context, + RefCountedPtr* auth_context, grpc_closure* on_peer_checked) override; + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + // TODO(ZhenLian): call verifier->cancel() once the verifier is ready. + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other_sc) const override; bool check_call_host(absl::string_view host, grpc_auth_context* auth_context, grpc_closure* on_call_host_checked, - grpc_error** error) override; + grpc_error_handle* error) override; void cancel_check_call_host(grpc_closure* on_call_host_checked, - grpc_error* error) override; + grpc_error_handle error) override; tsi_ssl_client_handshaker_factory* ClientHandshakerFactoryForTesting() { - grpc_core::MutexLock lock(&mu_); + MutexLock lock(&mu_); return client_handshaker_factory_; }; absl::optional RootCertsForTesting() { - grpc_core::MutexLock lock(&mu_); + MutexLock lock(&mu_); return pem_root_certs_; } - absl::optional KeyCertPairListForTesting() { - grpc_core::MutexLock lock(&mu_); + absl::optional KeyCertPairListForTesting() { + MutexLock lock(&mu_); return pem_key_cert_pair_list_; } @@ -96,9 +102,9 @@ class TlsChannelSecurityConnector final : security_connector_(security_connector) {} void OnCertificatesChanged( absl::optional root_certs, - absl::optional key_cert_pairs) override; - void OnError(grpc_error* root_cert_error, - grpc_error* identity_cert_error) override; + absl::optional key_cert_pairs) override; + void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) override; private: TlsChannelSecurityConnector* security_connector_ = nullptr; @@ -106,7 +112,8 @@ class TlsChannelSecurityConnector final // Updates |client_handshaker_factory_| when the certificates that // |certificate_watcher_| is watching get updated. - grpc_security_status UpdateHandshakerFactoryLocked(); + grpc_security_status UpdateHandshakerFactoryLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); // gRPC-provided callback executed by application, which servers to bring the // control back to gRPC core. @@ -114,7 +121,7 @@ class TlsChannelSecurityConnector final grpc_tls_server_authorization_check_arg* arg); // A util function to process server authorization check result. - static grpc_error* ProcessServerAuthorizationCheckResult( + static grpc_error_handle ProcessServerAuthorizationCheckResult( grpc_tls_server_authorization_check_arg* arg); // A util function to create a server authorization check arg instance. @@ -125,57 +132,65 @@ class TlsChannelSecurityConnector final static void ServerAuthorizationCheckArgDestroy( grpc_tls_server_authorization_check_arg* arg); - grpc_core::Mutex mu_; - grpc_core::RefCountedPtr options_; + RefCountedPtr options_; grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface* certificate_watcher_ = nullptr; grpc_closure* on_peer_checked_ = nullptr; std::string target_name_; std::string overridden_target_name_; - tsi_ssl_client_handshaker_factory* client_handshaker_factory_ = nullptr; grpc_tls_server_authorization_check_arg* check_arg_ = nullptr; - tsi_ssl_session_cache* ssl_session_cache_ = nullptr; - absl::optional pem_root_certs_; - absl::optional pem_key_cert_pair_list_; + + Mutex mu_; + tsi_ssl_client_handshaker_factory* client_handshaker_factory_ + ABSL_GUARDED_BY(mu_) = nullptr; + tsi_ssl_session_cache* ssl_session_cache_ ABSL_GUARDED_BY(mu_) = nullptr; + absl::optional pem_root_certs_ ABSL_GUARDED_BY(mu_); + absl::optional pem_key_cert_pair_list_ + ABSL_GUARDED_BY(mu_); }; // Server security connector using TLS as transport security protocol. class TlsServerSecurityConnector final : public grpc_server_security_connector { public: // static factory method to create a TLS server security connector. - static grpc_core::RefCountedPtr + static RefCountedPtr CreateTlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds, - grpc_core::RefCountedPtr options); + RefCountedPtr server_creds, + RefCountedPtr options); TlsServerSecurityConnector( - grpc_core::RefCountedPtr server_creds, - grpc_core::RefCountedPtr options); + RefCountedPtr server_creds, + RefCountedPtr options); ~TlsServerSecurityConnector() override; void add_handshakers(const grpc_channel_args* args, grpc_pollset_set* interested_parties, - grpc_core::HandshakeManager* handshake_mgr) override; + HandshakeManager* handshake_mgr) override; void check_peer(tsi_peer peer, grpc_endpoint* ep, - grpc_core::RefCountedPtr* auth_context, + RefCountedPtr* auth_context, grpc_closure* on_peer_checked) override; + void cancel_check_peer(grpc_closure* /*on_peer_checked*/, + grpc_error_handle error) override { + // TODO(ZhenLian): call verifier->cancel() once the verifier is ready. + GRPC_ERROR_UNREF(error); + } + int cmp(const grpc_security_connector* other) const override; tsi_ssl_server_handshaker_factory* ServerHandshakerFactoryForTesting() { - grpc_core::MutexLock lock(&mu_); + MutexLock lock(&mu_); return server_handshaker_factory_; }; const absl::optional& RootCertsForTesting() { - grpc_core::MutexLock lock(&mu_); + MutexLock lock(&mu_); return pem_root_certs_; } - const absl::optional& - KeyCertPairListForTesting() { - grpc_core::MutexLock lock(&mu_); + const absl::optional& KeyCertPairListForTesting() { + MutexLock lock(&mu_); return pem_key_cert_pair_list_; } @@ -191,9 +206,9 @@ class TlsServerSecurityConnector final : public grpc_server_security_connector { : security_connector_(security_connector) {} void OnCertificatesChanged( absl::optional root_certs, - absl::optional key_cert_pairs) override; - void OnError(grpc_error* root_cert_error, - grpc_error* identity_cert_error) override; + absl::optional key_cert_pairs) override; + void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) override; private: TlsServerSecurityConnector* security_connector_ = nullptr; @@ -201,16 +216,19 @@ class TlsServerSecurityConnector final : public grpc_server_security_connector { // Updates |server_handshaker_factory_| when the certificates that // |certificate_watcher_| is watching get updated. - grpc_security_status UpdateHandshakerFactoryLocked(); + grpc_security_status UpdateHandshakerFactoryLocked() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); - grpc_core::Mutex mu_; - grpc_core::RefCountedPtr options_; + RefCountedPtr options_; grpc_tls_certificate_distributor::TlsCertificatesWatcherInterface* certificate_watcher_ = nullptr; - tsi_ssl_server_handshaker_factory* server_handshaker_factory_ = nullptr; - absl::optional pem_root_certs_; - absl::optional pem_key_cert_pair_list_; + Mutex mu_; + tsi_ssl_server_handshaker_factory* server_handshaker_factory_ + ABSL_GUARDED_BY(mu_) = nullptr; + absl::optional pem_root_certs_ ABSL_GUARDED_BY(mu_); + absl::optional pem_key_cert_pair_list_ + ABSL_GUARDED_BY(mu_); }; // ---- Functions below are exposed for testing only ----------------------- @@ -218,7 +236,7 @@ namespace internal { // TlsCheckHostName checks if |peer_name| matches the identity information // contained in |peer|. This is AKA hostname check. -grpc_error* TlsCheckHostName(const char* peer_name, const tsi_peer* peer); +grpc_error_handle TlsCheckHostName(const char* peer_name, const tsi_peer* peer); } // namespace internal diff --git a/src/core/lib/security/transport/client_auth_filter.cc b/src/core/lib/security/transport/client_auth_filter.cc index c155be81230..babc90fb8cd 100644 --- a/src/core/lib/security/transport/client_auth_filter.cc +++ b/src/core/lib/security/transport/client_auth_filter.cc @@ -146,7 +146,7 @@ void grpc_auth_metadata_context_reset( } } -static void add_error(grpc_error** combined, grpc_error* error) { +static void add_error(grpc_error_handle* combined, grpc_error_handle error) { if (error == GRPC_ERROR_NONE) return; if (*combined == GRPC_ERROR_NONE) { *combined = GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -155,14 +155,14 @@ static void add_error(grpc_error** combined, grpc_error* error) { *combined = grpc_error_add_child(*combined, error); } -static void on_credentials_metadata(void* arg, grpc_error* input_error) { +static void on_credentials_metadata(void* arg, grpc_error_handle input_error) { grpc_transport_stream_op_batch* batch = static_cast(arg); grpc_call_element* elem = static_cast(batch->handler_private.extra_arg); call_data* calld = static_cast(elem->call_data); grpc_auth_metadata_context_reset(&calld->auth_md_context); - grpc_error* error = GRPC_ERROR_REF(input_error); + grpc_error_handle error = GRPC_ERROR_REF(input_error); if (error == GRPC_ERROR_NONE) { GPR_ASSERT(calld->md_array.size <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(batch->send_initial_metadata); @@ -225,13 +225,14 @@ void grpc_auth_metadata_context_build( gpr_free(host_and_port); } -static void cancel_get_request_metadata(void* arg, grpc_error* error) { +static void cancel_get_request_metadata(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { calld->creds->cancel_get_request_metadata(&calld->md_array, GRPC_ERROR_REF(error)); } + GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_get_request_metadata"); } static void send_security_metadata(grpc_call_element* elem, @@ -311,7 +312,7 @@ static void send_security_metadata(grpc_call_element* elem, GRPC_CALL_STACK_REF(calld->owning_call, "get_request_metadata"); GRPC_CLOSURE_INIT(&calld->async_result_closure, on_credentials_metadata, batch, grpc_schedule_on_exec_ctx); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (calld->creds->get_request_metadata( calld->pollent, calld->auth_md_context, &calld->md_array, &calld->async_result_closure, &error)) { @@ -320,13 +321,16 @@ static void send_security_metadata(grpc_call_element* elem, GRPC_ERROR_UNREF(error); } else { // Async return; register cancellation closure with call combiner. + // TODO(yashykt): We would not need this ref if call combiners used + // Closure::Run() instead of ExecCtx::Run() + GRPC_CALL_STACK_REF(calld->owning_call, "cancel_get_request_metadata"); calld->call_combiner->SetNotifyOnCancel(GRPC_CLOSURE_INIT( &calld->get_request_metadata_cancel_closure, cancel_get_request_metadata, elem, grpc_schedule_on_exec_ctx)); } } -static void on_host_checked(void* arg, grpc_error* error) { +static void on_host_checked(void* arg, grpc_error_handle error) { grpc_transport_stream_op_batch* batch = static_cast(arg); grpc_call_element* elem = @@ -348,7 +352,7 @@ static void on_host_checked(void* arg, grpc_error* error) { GRPC_CALL_STACK_UNREF(calld->owning_call, "check_call_host"); } -static void cancel_check_call_host(void* arg, grpc_error* error) { +static void cancel_check_call_host(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); channel_data* chand = static_cast(elem->channel_data); @@ -356,6 +360,7 @@ static void cancel_check_call_host(void* arg, grpc_error* error) { chand->security_connector->cancel_check_call_host( &calld->async_result_closure, GRPC_ERROR_REF(error)); } + GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_check_call_host"); } static void client_auth_start_transport_stream_op_batch( @@ -381,7 +386,7 @@ static void client_auth_start_transport_stream_op_batch( GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch, grpc_schedule_on_exec_ctx); absl::string_view call_host(grpc_core::StringViewFromSlice(calld->host)); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (chand->security_connector->check_call_host( call_host, chand->auth_context.get(), &calld->async_result_closure, &error)) { @@ -390,6 +395,9 @@ static void client_auth_start_transport_stream_op_batch( GRPC_ERROR_UNREF(error); } else { // Async return; register cancellation closure with call combiner. + // TODO(yashykt): We would not need this ref if call combiners used + // Closure::Run() instead of ExecCtx::Run() + GRPC_CALL_STACK_REF(calld->owning_call, "cancel_check_call_host"); calld->call_combiner->SetNotifyOnCancel(GRPC_CLOSURE_INIT( &calld->check_call_host_cancel_closure, cancel_check_call_host, elem, grpc_schedule_on_exec_ctx)); @@ -403,7 +411,7 @@ static void client_auth_start_transport_stream_op_batch( } /* Constructor for call_data */ -static grpc_error* client_auth_init_call_elem( +static grpc_error_handle client_auth_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* args) { new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; @@ -424,7 +432,7 @@ static void client_auth_destroy_call_elem( } /* Constructor for channel_data */ -static grpc_error* client_auth_init_channel_elem( +static grpc_error_handle client_auth_init_channel_elem( grpc_channel_element* elem, grpc_channel_element_args* args) { /* The first and the last filters tend to be implemented differently to handle the case that there's no 'next' filter to call on the up or down diff --git a/src/core/lib/security/transport/secure_endpoint.cc b/src/core/lib/security/transport/secure_endpoint.cc index 7ab4d7b779c..fc1fb7e846f 100644 --- a/src/core/lib/security/transport/secure_endpoint.cc +++ b/src/core/lib/security/transport/secure_endpoint.cc @@ -43,7 +43,7 @@ #define STAGING_BUFFER_SIZE 8192 -static void on_read(void* user_data, grpc_error* error); +static void on_read(void* user_data, grpc_error_handle error); namespace { struct secure_endpoint { @@ -154,7 +154,7 @@ static void flush_read_staging_buffer(secure_endpoint* ep, uint8_t** cur, *end = GRPC_SLICE_END_PTR(ep->read_staging_buffer); } -static void call_read_cb(secure_endpoint* ep, grpc_error* error) { +static void call_read_cb(secure_endpoint* ep, grpc_error_handle error) { if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_secure_endpoint)) { size_t i; for (i = 0; i < ep->read_buffer->count; i++) { @@ -169,7 +169,7 @@ static void call_read_cb(secure_endpoint* ep, grpc_error* error) { SECURE_ENDPOINT_UNREF(ep, "read"); } -static void on_read(void* user_data, grpc_error* error) { +static void on_read(void* user_data, grpc_error_handle error) { unsigned i; uint8_t keep_looping = 0; tsi_result result = TSI_OK; @@ -373,7 +373,7 @@ static void endpoint_write(grpc_endpoint* secure_ep, grpc_slice_buffer* slices, grpc_endpoint_write(ep->wrapped_ep, &ep->output_buffer, cb, arg); } -static void endpoint_shutdown(grpc_endpoint* secure_ep, grpc_error* why) { +static void endpoint_shutdown(grpc_endpoint* secure_ep, grpc_error_handle why) { secure_endpoint* ep = reinterpret_cast(secure_ep); grpc_endpoint_shutdown(ep->wrapped_ep, why); } diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc index 9e0e4032aa5..6d05c97078b 100644 --- a/src/core/lib/security/transport/security_handshaker.cc +++ b/src/core/lib/security/transport/security_handshaker.cc @@ -29,6 +29,7 @@ #include #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/channel/channelz.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" @@ -50,35 +51,36 @@ class SecurityHandshaker : public Handshaker { grpc_security_connector* connector, const grpc_channel_args* args); ~SecurityHandshaker() override; - void Shutdown(grpc_error* why) override; + void Shutdown(grpc_error_handle why) override; void DoHandshake(grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, HandshakerArgs* args) override; const char* name() const override { return "security"; } private: - grpc_error* DoHandshakerNextLocked(const unsigned char* bytes_received, - size_t bytes_received_size); + grpc_error_handle DoHandshakerNextLocked(const unsigned char* bytes_received, + size_t bytes_received_size); - grpc_error* OnHandshakeNextDoneLocked( + grpc_error_handle OnHandshakeNextDoneLocked( tsi_result result, const unsigned char* bytes_to_send, size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result); - void HandshakeFailedLocked(grpc_error* error); + void HandshakeFailedLocked(grpc_error_handle error); void CleanupArgsForFailureLocked(); - static void OnHandshakeDataReceivedFromPeerFn(void* arg, grpc_error* error); - static void OnHandshakeDataSentToPeerFn(void* arg, grpc_error* error); - static void OnHandshakeDataReceivedFromPeerFnScheduler(void* arg, - grpc_error* error); + static void OnHandshakeDataReceivedFromPeerFn(void* arg, + grpc_error_handle error); + static void OnHandshakeDataSentToPeerFn(void* arg, grpc_error_handle error); + static void OnHandshakeDataReceivedFromPeerFnScheduler( + void* arg, grpc_error_handle error); static void OnHandshakeDataSentToPeerFnScheduler(void* arg, - grpc_error* error); + grpc_error_handle error); static void OnHandshakeNextDoneGrpcWrapper( tsi_result result, void* user_data, const unsigned char* bytes_to_send, size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result); - static void OnPeerCheckedFn(void* arg, grpc_error* error); - void OnPeerCheckedInner(grpc_error* error); + static void OnPeerCheckedFn(void* arg, grpc_error_handle error); + void OnPeerCheckedInner(grpc_error_handle error); size_t MoveReadBufferIntoHandshakeBuffer(); - grpc_error* CheckPeerLocked(); + grpc_error_handle CheckPeerLocked(); // State set at creation time. tsi_handshaker* handshaker_; @@ -172,15 +174,14 @@ void SecurityHandshaker::CleanupArgsForFailureLocked() { // If the handshake failed or we're shutting down, clean up and invoke the // callback with the error. -void SecurityHandshaker::HandshakeFailedLocked(grpc_error* error) { +void SecurityHandshaker::HandshakeFailedLocked(grpc_error_handle error) { if (error == GRPC_ERROR_NONE) { // If we were shut down after the handshake succeeded but before an // endpoint callback was invoked, we need to generate our own error. error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); } - const char* msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg); - + gpr_log(GPR_DEBUG, "Security handshake failed: %s", + grpc_error_std_string(error).c_str()); if (!is_shutdown_) { tsi_handshaker_shutdown(handshaker_); // TODO(ctiller): It is currently necessary to shutdown endpoints @@ -199,7 +200,32 @@ void SecurityHandshaker::HandshakeFailedLocked(grpc_error* error) { ExecCtx::Run(DEBUG_LOCATION, on_handshake_done_, error); } -void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) { +namespace { + +RefCountedPtr +MakeChannelzSecurityFromAuthContext(grpc_auth_context* auth_context) { + RefCountedPtr security = + MakeRefCounted(); + // TODO(yashykt): Currently, we are assuming TLS by default and are only able + // to fill in the remote certificate but we should ideally be able to fill in + // other fields in + // https://github.com/grpc/grpc/blob/fcd43e90304862a823316b224ee733d17a8cfd90/src/proto/grpc/channelz/channelz.proto#L326 + // from grpc_auth_context. + security->type = channelz::SocketNode::Security::ModelType::kTls; + security->tls = absl::make_optional(); + grpc_auth_property_iterator it = grpc_auth_context_find_properties_by_name( + auth_context, GRPC_X509_PEM_CERT_PROPERTY_NAME); + const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it); + if (prop != nullptr) { + security->tls->remote_certificate = + std::string(prop->value, prop->value_length); + } + return security; +} + +} // namespace + +void SecurityHandshaker::OnPeerCheckedInner(grpc_error_handle error) { MutexLock lock(&mu_); if (error != GRPC_ERROR_NONE || is_shutdown_) { HandshakeFailedLocked(error); @@ -251,9 +277,13 @@ void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) { tsi_handshaker_result_destroy(handshaker_result_); handshaker_result_ = nullptr; // Add auth context to channel args. - grpc_arg auth_context_arg = grpc_auth_context_to_arg(auth_context_.get()); + absl::InlinedVector args_to_add; + args_to_add.push_back(grpc_auth_context_to_arg(auth_context_.get())); + auto security = MakeChannelzSecurityFromAuthContext(auth_context_.get()); + args_to_add.push_back(security->MakeChannelArg()); grpc_channel_args* tmp_args = args_->args; - args_->args = grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); + args_->args = grpc_channel_args_copy_and_add(tmp_args, args_to_add.data(), + args_to_add.size()); grpc_channel_args_destroy(tmp_args); // Invoke callback. ExecCtx::Run(DEBUG_LOCATION, on_handshake_done_, GRPC_ERROR_NONE); @@ -262,12 +292,12 @@ void SecurityHandshaker::OnPeerCheckedInner(grpc_error* error) { is_shutdown_ = true; } -void SecurityHandshaker::OnPeerCheckedFn(void* arg, grpc_error* error) { +void SecurityHandshaker::OnPeerCheckedFn(void* arg, grpc_error_handle error) { RefCountedPtr(static_cast(arg)) ->OnPeerCheckedInner(GRPC_ERROR_REF(error)); } -grpc_error* SecurityHandshaker::CheckPeerLocked() { +grpc_error_handle SecurityHandshaker::CheckPeerLocked() { tsi_peer peer; tsi_result result = tsi_handshaker_result_extract_peer(handshaker_result_, &peer); @@ -280,10 +310,10 @@ grpc_error* SecurityHandshaker::CheckPeerLocked() { return GRPC_ERROR_NONE; } -grpc_error* SecurityHandshaker::OnHandshakeNextDoneLocked( +grpc_error_handle SecurityHandshaker::OnHandshakeNextDoneLocked( tsi_result result, const unsigned char* bytes_to_send, size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; // Handshaker was shutdown. if (is_shutdown_) { return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown"); @@ -344,7 +374,7 @@ void SecurityHandshaker::OnHandshakeNextDoneGrpcWrapper( RefCountedPtr h( static_cast(user_data)); MutexLock lock(&h->mu_); - grpc_error* error = h->OnHandshakeNextDoneLocked( + grpc_error_handle error = h->OnHandshakeNextDoneLocked( result, bytes_to_send, bytes_to_send_size, handshaker_result); if (error != GRPC_ERROR_NONE) { h->HandshakeFailedLocked(error); @@ -353,7 +383,7 @@ void SecurityHandshaker::OnHandshakeNextDoneGrpcWrapper( } } -grpc_error* SecurityHandshaker::DoHandshakerNextLocked( +grpc_error_handle SecurityHandshaker::DoHandshakerNextLocked( const unsigned char* bytes_received, size_t bytes_received_size) { // Invoke TSI handshaker. const unsigned char* bytes_to_send = nullptr; @@ -376,7 +406,7 @@ grpc_error* SecurityHandshaker::DoHandshakerNextLocked( // This callback might be run inline while we are still holding on to the mutex, // so schedule OnHandshakeDataReceivedFromPeerFn on ExecCtx to avoid a deadlock. void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { SecurityHandshaker* h = static_cast(arg); grpc_core::ExecCtx::Run( DEBUG_LOCATION, @@ -386,8 +416,8 @@ void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFnScheduler( GRPC_ERROR_REF(error)); } -void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(void* arg, - grpc_error* error) { +void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn( + void* arg, grpc_error_handle error) { RefCountedPtr h(static_cast(arg)); MutexLock lock(&h->mu_); if (error != GRPC_ERROR_NONE || h->is_shutdown_) { @@ -410,7 +440,7 @@ void SecurityHandshaker::OnHandshakeDataReceivedFromPeerFn(void* arg, // This callback might be run inline while we are still holding on to the mutex, // so schedule OnHandshakeDataSentToPeerFn on ExecCtx to avoid a deadlock. void SecurityHandshaker::OnHandshakeDataSentToPeerFnScheduler( - void* arg, grpc_error* error) { + void* arg, grpc_error_handle error) { SecurityHandshaker* h = static_cast(arg); grpc_core::ExecCtx::Run( DEBUG_LOCATION, @@ -421,7 +451,7 @@ void SecurityHandshaker::OnHandshakeDataSentToPeerFnScheduler( } void SecurityHandshaker::OnHandshakeDataSentToPeerFn(void* arg, - grpc_error* error) { + grpc_error_handle error) { RefCountedPtr h(static_cast(arg)); MutexLock lock(&h->mu_); if (error != GRPC_ERROR_NONE || h->is_shutdown_) { @@ -452,10 +482,11 @@ void SecurityHandshaker::OnHandshakeDataSentToPeerFn(void* arg, // public handshaker API // -void SecurityHandshaker::Shutdown(grpc_error* why) { +void SecurityHandshaker::Shutdown(grpc_error_handle why) { MutexLock lock(&mu_); if (!is_shutdown_) { is_shutdown_ = true; + connector_->cancel_check_peer(&on_peer_checked_, GRPC_ERROR_REF(why)); tsi_handshaker_shutdown(handshaker_); grpc_endpoint_shutdown(args_->endpoint, GRPC_ERROR_REF(why)); CleanupArgsForFailureLocked(); @@ -471,7 +502,7 @@ void SecurityHandshaker::DoHandshake(grpc_tcp_server_acceptor* /*acceptor*/, args_ = args; on_handshake_done_ = on_handshake_done; size_t bytes_received_size = MoveReadBufferIntoHandshakeBuffer(); - grpc_error* error = + grpc_error_handle error = DoHandshakerNextLocked(handshake_buffer_, bytes_received_size); if (error != GRPC_ERROR_NONE) { HandshakeFailedLocked(error); @@ -487,7 +518,7 @@ void SecurityHandshaker::DoHandshake(grpc_tcp_server_acceptor* /*acceptor*/, class FailHandshaker : public Handshaker { public: const char* name() const override { return "security_fail"; } - void Shutdown(grpc_error* why) override { GRPC_ERROR_UNREF(why); } + void Shutdown(grpc_error_handle why) override { GRPC_ERROR_UNREF(why); } void DoHandshake(grpc_tcp_server_acceptor* /*acceptor*/, grpc_closure* on_handshake_done, HandshakerArgs* /*args*/) override { diff --git a/src/core/lib/security/transport/server_auth_filter.cc b/src/core/lib/security/transport/server_auth_filter.cc index 67351892ed6..65a7e405569 100644 --- a/src/core/lib/security/transport/server_auth_filter.cc +++ b/src/core/lib/security/transport/server_auth_filter.cc @@ -28,8 +28,9 @@ #include "src/core/lib/security/transport/auth_filters.h" #include "src/core/lib/slice/slice_internal.h" -static void recv_initial_metadata_ready(void* arg, grpc_error* error); -static void recv_trailing_metadata_ready(void* user_data, grpc_error* error); +static void recv_initial_metadata_ready(void* arg, grpc_error_handle error); +static void recv_trailing_metadata_ready(void* user_data, + grpc_error_handle error); namespace { enum async_state { @@ -79,10 +80,10 @@ struct call_data { grpc_transport_stream_op_batch* recv_initial_metadata_batch; grpc_closure* original_recv_initial_metadata_ready; grpc_closure recv_initial_metadata_ready; - grpc_error* recv_initial_metadata_error = GRPC_ERROR_NONE; + grpc_error_handle recv_initial_metadata_error = GRPC_ERROR_NONE; grpc_closure recv_trailing_metadata_ready; grpc_closure* original_recv_trailing_metadata_ready; - grpc_error* recv_trailing_metadata_error; + grpc_error_handle recv_trailing_metadata_error; bool seen_recv_trailing_metadata_ready = false; grpc_metadata_array md; const grpc_metadata* consumed_md; @@ -135,7 +136,7 @@ static void on_md_processing_done_inner(grpc_call_element* elem, size_t num_consumed_md, const grpc_metadata* response_md, size_t num_response_md, - grpc_error* error) { + grpc_error_handle error) { call_data* calld = static_cast(elem->call_data); grpc_transport_stream_op_batch* batch = calld->recv_initial_metadata_batch; /* TODO(jboeuf): Implement support for response_md. */ @@ -175,7 +176,7 @@ static void on_md_processing_done( // If the call was not cancelled while we were in flight, process the result. if (gpr_atm_full_cas(&calld->state, static_cast(STATE_INIT), static_cast(STATE_DONE))) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (status != GRPC_STATUS_OK) { if (error_details == nullptr) { error_details = "Authentication metadata processing failed."; @@ -196,7 +197,7 @@ static void on_md_processing_done( GRPC_CALL_STACK_UNREF(calld->owning_call, "server_auth_metadata"); } -static void cancel_call(void* arg, grpc_error* error) { +static void cancel_call(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); // If the result was not already processed, invoke the callback now. @@ -206,9 +207,10 @@ static void cancel_call(void* arg, grpc_error* error) { on_md_processing_done_inner(elem, nullptr, 0, nullptr, 0, GRPC_ERROR_REF(error)); } + GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_call"); } -static void recv_initial_metadata_ready(void* arg, grpc_error* error) { +static void recv_initial_metadata_ready(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); channel_data* chand = static_cast(elem->channel_data); call_data* calld = static_cast(elem->call_data); @@ -218,6 +220,9 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { chand->creds->auth_metadata_processor().process != nullptr) { // We're calling out to the application, so we need to make sure // to drop the call combiner early if we get cancelled. + // TODO(yashykt): We would not need this ref if call combiners used + // Closure::Run() instead of ExecCtx::Run() + GRPC_CALL_STACK_REF(calld->owning_call, "cancel_call"); GRPC_CLOSURE_INIT(&calld->cancel_closure, cancel_call, elem, grpc_schedule_on_exec_ctx); calld->call_combiner->SetNotifyOnCancel(&calld->cancel_closure); @@ -242,7 +247,8 @@ static void recv_initial_metadata_ready(void* arg, grpc_error* error) { grpc_core::Closure::Run(DEBUG_LOCATION, closure, GRPC_ERROR_REF(error)); } -static void recv_trailing_metadata_ready(void* user_data, grpc_error* err) { +static void recv_trailing_metadata_ready(void* user_data, + grpc_error_handle err) { grpc_call_element* elem = static_cast(user_data); call_data* calld = static_cast(elem->call_data); if (calld->original_recv_initial_metadata_ready != nullptr) { @@ -280,7 +286,7 @@ static void server_auth_start_transport_stream_op_batch( } /* Constructor for call_data */ -static grpc_error* server_auth_init_call_elem( +static grpc_error_handle server_auth_init_call_elem( grpc_call_element* elem, const grpc_call_element_args* args) { new (elem->call_data) call_data(elem, *args); return GRPC_ERROR_NONE; @@ -295,11 +301,18 @@ static void server_auth_destroy_call_elem( } /* Constructor for channel_data */ -static grpc_error* server_auth_init_channel_elem( +static grpc_error_handle server_auth_init_channel_elem( grpc_channel_element* elem, grpc_channel_element_args* args) { GPR_ASSERT(!args->is_last); grpc_auth_context* auth_context = grpc_find_auth_context_in_args(args->channel_args); + if (auth_context == nullptr) { + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No authorization context found. This might be a TRANSIENT failure due " + "to certificates not having been loaded yet."); + gpr_log(GPR_DEBUG, "%s", grpc_error_std_string(error).c_str()); + return error; + } GPR_ASSERT(auth_context != nullptr); grpc_server_credentials* creds = grpc_find_server_credentials_in_args(args->channel_args); diff --git a/src/core/lib/security/transport/tsi_error.cc b/src/core/lib/security/transport/tsi_error.cc index f78bb8df38f..4d337b4622f 100644 --- a/src/core/lib/security/transport/tsi_error.cc +++ b/src/core/lib/security/transport/tsi_error.cc @@ -20,7 +20,8 @@ #include "src/core/lib/security/transport/tsi_error.h" -grpc_error* grpc_set_tsi_error_result(grpc_error* error, tsi_result result) { +grpc_error_handle grpc_set_tsi_error_result(grpc_error_handle error, + tsi_result result) { return grpc_error_set_int( grpc_error_set_str( error, GRPC_ERROR_STR_TSI_ERROR, diff --git a/src/core/lib/security/transport/tsi_error.h b/src/core/lib/security/transport/tsi_error.h index 16e04f70f1e..26b8806dd21 100644 --- a/src/core/lib/security/transport/tsi_error.h +++ b/src/core/lib/security/transport/tsi_error.h @@ -24,6 +24,7 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/tsi/transport_security_interface.h" -grpc_error* grpc_set_tsi_error_result(grpc_error* error, tsi_result result); +grpc_error_handle grpc_set_tsi_error_result(grpc_error_handle error, + tsi_result result); #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_TSI_ERROR_H */ diff --git a/src/core/lib/security/util/json_util.cc b/src/core/lib/security/util/json_util.cc index ff2fbc80324..34bf88f4db4 100644 --- a/src/core/lib/security/util/json_util.cc +++ b/src/core/lib/security/util/json_util.cc @@ -30,7 +30,7 @@ const char* grpc_json_get_string_property(const grpc_core::Json& json, const char* prop_name, - grpc_error** error) { + grpc_error_handle* error) { if (json.type() != grpc_core::Json::Type::OBJECT) { if (error != nullptr) { *error = @@ -62,7 +62,7 @@ const char* grpc_json_get_string_property(const grpc_core::Json& json, bool grpc_copy_json_string_property(const grpc_core::Json& json, const char* prop_name, char** copied_value) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; const char* prop_value = grpc_json_get_string_property(json, prop_name, &error); GRPC_LOG_IF_ERROR("Could not copy JSON property", error); diff --git a/src/core/lib/security/util/json_util.h b/src/core/lib/security/util/json_util.h index cde9ca97ffd..d3c6ec31277 100644 --- a/src/core/lib/security/util/json_util.h +++ b/src/core/lib/security/util/json_util.h @@ -35,7 +35,7 @@ // Gets a child property from a json node. const char* grpc_json_get_string_property(const grpc_core::Json& json, const char* prop_name, - grpc_error** error); + grpc_error_handle* error); // Copies the value of the json child property specified by prop_name. // Returns false if the property was not found. diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc index d749d396eda..ac0854c2210 100644 --- a/src/core/lib/surface/call.cc +++ b/src/core/lib/surface/call.cc @@ -290,14 +290,15 @@ static void execute_batch(grpc_call* call, static void cancel_with_status(grpc_call* c, grpc_status_code status, const char* description); -static void cancel_with_error(grpc_call* c, grpc_error* error); -static void destroy_call(void* call_stack, grpc_error* error); -static void receiving_slice_ready(void* bctlp, grpc_error* error); -static void set_final_status(grpc_call* call, grpc_error* error); +static void cancel_with_error(grpc_call* c, grpc_error_handle error); +static void destroy_call(void* call_stack, grpc_error_handle error); +static void receiving_slice_ready(void* bctlp, grpc_error_handle error); +static void set_final_status(grpc_call* call, grpc_error_handle error); static void process_data_after_md(batch_control* bctl); static void post_batch_completion(batch_control* bctl); -static void add_init_error(grpc_error** composite, grpc_error* new_err) { +static void add_init_error(grpc_error_handle* composite, + grpc_error_handle new_err) { if (new_err == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) { *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Call creation failed"); @@ -335,15 +336,15 @@ size_t grpc_call_get_initial_size_estimate() { sizeof(grpc_linked_mdelem) * ESTIMATED_MDELEM_COUNT; } -grpc_error* grpc_call_create(const grpc_call_create_args* args, - grpc_call** out_call) { +grpc_error_handle grpc_call_create(const grpc_call_create_args* args, + grpc_call** out_call) { GPR_TIMER_SCOPE("grpc_call_create", 0); GRPC_CHANNEL_INTERNAL_REF(args->channel, "call"); grpc_core::Arena* arena; grpc_call* call; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_channel_stack* channel_stack = grpc_channel_get_channel_stack(args->channel); size_t initial_size = grpc_channel_get_call_size_estimate(args->channel); @@ -524,7 +525,7 @@ void grpc_call_internal_unref(grpc_call* c REF_ARG) { GRPC_CALL_STACK_UNREF(CALL_STACK_FROM_CALL(c), REF_REASON); } -static void release_call(void* call, grpc_error* /*error*/) { +static void release_call(void* call, grpc_error_handle /*error*/) { grpc_call* c = static_cast(call); grpc_channel* channel = c->channel; grpc_core::Arena* arena = c->arena; @@ -533,7 +534,7 @@ static void release_call(void* call, grpc_error* /*error*/) { GRPC_CHANNEL_INTERNAL_UNREF(channel, "call"); } -static void destroy_call(void* call, grpc_error* /*error*/) { +static void destroy_call(void* call, grpc_error_handle /*error*/) { GPR_TIMER_SCOPE("destroy_call", 0); size_t i; int ii; @@ -559,8 +560,8 @@ static void destroy_call(void* call, grpc_error* /*error*/) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } - grpc_error* status_error = - reinterpret_cast(gpr_atm_acq_load(&c->status_error)); + grpc_error_handle status_error = + reinterpret_cast(gpr_atm_acq_load(&c->status_error)); grpc_error_get_status(status_error, c->send_deadline, &c->final_info.final_status, nullptr, nullptr, &(c->final_info.error_string)); @@ -610,11 +611,8 @@ void grpc_call_unref(grpc_call* c) { // Unset the call combiner cancellation closure. This has the // effect of scheduling the previously set cancellation closure, if // any, so that it can release any internal references it may be - // holding to the call stack. Also flush the closures on exec_ctx so that - // filters that schedule cancel notification closures on exec_ctx do not - // need to take a ref of the call stack to guarantee closure liveness. + // holding to the call stack. c->call_combiner.SetNotifyOnCancel(nullptr); - grpc_core::ExecCtx::Get()->Flush(); } GRPC_CALL_INTERNAL_UNREF(c, "destroy"); } @@ -630,7 +628,8 @@ grpc_call_error grpc_call_cancel(grpc_call* call, void* reserved) { // This is called via the call combiner to start sending a batch down // the filter stack. -static void execute_batch_in_call_combiner(void* arg, grpc_error* /*ignored*/) { +static void execute_batch_in_call_combiner(void* arg, + grpc_error_handle /*ignored*/) { GPR_TIMER_SCOPE("execute_batch_in_call_combiner", 0); grpc_transport_stream_op_batch* batch = static_cast(arg); @@ -691,7 +690,7 @@ struct cancel_state { }; // The on_complete callback used when sending a cancel_stream batch down // the filter stack. Yields the call combiner when the batch is done. -static void done_termination(void* arg, grpc_error* /*error*/) { +static void done_termination(void* arg, grpc_error_handle /*error*/) { cancel_state* state = static_cast(arg); GRPC_CALL_COMBINER_STOP(&state->call->call_combiner, "on_complete for cancel_stream op"); @@ -699,7 +698,7 @@ static void done_termination(void* arg, grpc_error* /*error*/) { gpr_free(state); } -static void cancel_with_error(grpc_call* c, grpc_error* error) { +static void cancel_with_error(grpc_call* c, grpc_error_handle error) { if (!gpr_atm_rel_cas(&c->cancelled_with_error, 0, 1)) { GRPC_ERROR_UNREF(error); return; @@ -725,8 +724,8 @@ void grpc_call_cancel_internal(grpc_call* call) { cancel_with_error(call, GRPC_ERROR_CANCELLED); } -static grpc_error* error_from_status(grpc_status_code status, - const char* description) { +static grpc_error_handle error_from_status(grpc_status_code status, + const char* description) { // copying 'description' is needed to ensure the grpc_call_cancel_with_status // guarantee that can be short-lived. return grpc_error_set_int( @@ -741,10 +740,10 @@ static void cancel_with_status(grpc_call* c, grpc_status_code status, cancel_with_error(c, error_from_status(status, description)); } -static void set_final_status(grpc_call* call, grpc_error* error) { +static void set_final_status(grpc_call* call, grpc_error_handle error) { if (GRPC_TRACE_FLAG_ENABLED(grpc_call_error_trace)) { gpr_log(GPR_DEBUG, "set_final_status %s", call->is_client ? "CLI" : "SVR"); - gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); + gpr_log(GPR_DEBUG, "%s", grpc_error_std_string(error).c_str()); } if (call->is_client) { grpc_error_get_status(error, call->send_deadline, @@ -770,7 +769,7 @@ static void set_final_status(grpc_call* call, grpc_error* error) { call->final_op.server.core_server->channelz_node(); if (channelz_node != nullptr) { if (*call->final_op.server.cancelled || - reinterpret_cast( + reinterpret_cast( gpr_atm_acq_load(&call->status_error)) != GRPC_ERROR_NONE) { channelz_node->RecordCallFailed(); } else { @@ -952,7 +951,7 @@ static int prepare_application_metadata(grpc_call* call, int count, for (i = 0; i < total_count; i++) { grpc_metadata* md = get_md_elem(metadata, additional_metadata, i, count); grpc_linked_mdelem* l = linked_from_md(md); - grpc_error* error = grpc_metadata_batch_link_tail(batch, l); + grpc_error_handle error = grpc_metadata_batch_link_tail(batch, l); if (error != GRPC_ERROR_NONE) { GRPC_MDELEM_UNREF(l->md); } @@ -1053,14 +1052,14 @@ static void recv_initial_filter(grpc_call* call, grpc_metadata_batch* b) { } static void recv_trailing_filter(void* args, grpc_metadata_batch* b, - grpc_error* batch_error) { + grpc_error_handle batch_error) { grpc_call* call = static_cast(args); if (batch_error != GRPC_ERROR_NONE) { set_final_status(call, batch_error); } else if (b->idx.named.grpc_status != nullptr) { grpc_status_code status_code = grpc_get_status_code_from_metadata(b->idx.named.grpc_status->md); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (status_code != GRPC_STATUS_OK) { char* peer = grpc_call_get_peer(call); error = grpc_error_set_int( @@ -1171,8 +1170,8 @@ static void finish_batch_completion(void* user_data, } static void reset_batch_errors(batch_control* bctl) { - GRPC_ERROR_UNREF( - reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); + GRPC_ERROR_UNREF(reinterpret_cast( + gpr_atm_acq_load(&bctl->batch_error))); gpr_atm_rel_store(&bctl->batch_error, reinterpret_cast(GRPC_ERROR_NONE)); } @@ -1180,8 +1179,8 @@ static void reset_batch_errors(batch_control* bctl) { static void post_batch_completion(batch_control* bctl) { grpc_call* next_child_call; grpc_call* call = bctl->call; - grpc_error* error = GRPC_ERROR_REF( - reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error))); + grpc_error_handle error = GRPC_ERROR_REF(reinterpret_cast( + gpr_atm_acq_load(&bctl->batch_error))); if (bctl->op.send_initial_metadata) { grpc_metadata_batch_destroy( @@ -1254,7 +1253,7 @@ static void finish_batch_step(batch_control* bctl) { } static void continue_receiving_slices(batch_control* bctl) { - grpc_error* error; + grpc_error_handle error; grpc_call* call = bctl->call; for (;;) { size_t remaining = call->receiving_stream->length() - @@ -1285,7 +1284,7 @@ static void continue_receiving_slices(batch_control* bctl) { } } -static void receiving_slice_ready(void* bctlp, grpc_error* error) { +static void receiving_slice_ready(void* bctlp, grpc_error_handle error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; bool release_error = false; @@ -1345,13 +1344,13 @@ static void process_data_after_md(batch_control* bctl) { } } -static void receiving_stream_ready(void* bctlp, grpc_error* error) { +static void receiving_stream_ready(void* bctlp, grpc_error_handle error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; if (error != GRPC_ERROR_NONE) { call->receiving_stream.reset(); - if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == - GRPC_ERROR_NONE) { + if (reinterpret_cast( + gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { gpr_atm_rel_store(&bctl->batch_error, reinterpret_cast(GRPC_ERROR_REF(error))); } @@ -1371,7 +1370,7 @@ static void receiving_stream_ready(void* bctlp, grpc_error* error) { // a recv_message op down the filter stack. Yields the call combiner // before processing the received message. static void receiving_stream_ready_in_call_combiner(void* bctlp, - grpc_error* error) { + grpc_error_handle error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_message_ready"); @@ -1464,7 +1463,8 @@ static void validate_filtered_metadata(batch_control* bctl) { } } -static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { +static void receiving_initial_metadata_ready(void* bctlp, + grpc_error_handle error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; @@ -1483,8 +1483,8 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { call->send_deadline = md->deadline; } } else { - if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == - GRPC_ERROR_NONE) { + if (reinterpret_cast( + gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { gpr_atm_rel_store(&bctl->batch_error, reinterpret_cast(GRPC_ERROR_REF(error))); } @@ -1523,7 +1523,8 @@ static void receiving_initial_metadata_ready(void* bctlp, grpc_error* error) { finish_batch_step(bctl); } -static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { +static void receiving_trailing_metadata_ready(void* bctlp, + grpc_error_handle error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "recv_trailing_metadata_ready"); @@ -1533,12 +1534,12 @@ static void receiving_trailing_metadata_ready(void* bctlp, grpc_error* error) { finish_batch_step(bctl); } -static void finish_batch(void* bctlp, grpc_error* error) { +static void finish_batch(void* bctlp, grpc_error_handle error) { batch_control* bctl = static_cast(bctlp); grpc_call* call = bctl->call; GRPC_CALL_COMBINER_STOP(&call->call_combiner, "on_complete"); - if (reinterpret_cast(gpr_atm_acq_load(&bctl->batch_error)) == - GRPC_ERROR_NONE) { + if (reinterpret_cast( + gpr_atm_acq_load(&bctl->batch_error)) == GRPC_ERROR_NONE) { gpr_atm_rel_store(&bctl->batch_error, reinterpret_cast(GRPC_ERROR_REF(error))); } @@ -1755,7 +1756,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->send_extra_metadata_count = 1; call->send_extra_metadata[0].md = grpc_get_reffed_status_elem( op->data.send_status_from_server.status); - grpc_error* status_error = + grpc_error_handle status_error = op->data.send_status_from_server.status == GRPC_STATUS_OK ? GRPC_ERROR_NONE : grpc_error_set_int( diff --git a/src/core/lib/surface/call.h b/src/core/lib/surface/call.h index 34d01db9029..a6ad3cae173 100644 --- a/src/core/lib/surface/call.h +++ b/src/core/lib/surface/call.h @@ -55,8 +55,8 @@ typedef struct grpc_call_create_args { /* Create a new call based on \a args. Regardless of success or failure, always returns a valid new call into *call */ -grpc_error* grpc_call_create(const grpc_call_create_args* args, - grpc_call** call); +grpc_error_handle grpc_call_create(const grpc_call_create_args* args, + grpc_call** call); void grpc_call_set_completion_queue(grpc_call* call, grpc_completion_queue* cq); diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc index d68f43fced3..d3552c874f3 100644 --- a/src/core/lib/surface/channel.cc +++ b/src/core/lib/surface/channel.cc @@ -54,11 +54,11 @@ * (OK, Cancelled, Unknown). */ #define NUM_CACHED_STATUS_ELEMS 3 -static void destroy_channel(void* arg, grpc_error* error); +static void destroy_channel(void* arg, grpc_error_handle error); grpc_channel* grpc_channel_create_with_builder( grpc_channel_stack_builder* builder, - grpc_channel_stack_type channel_stack_type, grpc_error** error) { + grpc_channel_stack_type channel_stack_type, grpc_error_handle* error) { char* target = gpr_strdup(grpc_channel_stack_builder_get_target(builder)); grpc_channel_args* args = grpc_channel_args_copy( grpc_channel_stack_builder_get_channel_arguments(builder)); @@ -70,12 +70,12 @@ grpc_channel* grpc_channel_create_with_builder( } else { GRPC_STATS_INC_CLIENT_CHANNELS_CREATED(); } - grpc_error* builder_error = grpc_channel_stack_builder_finish( + grpc_error_handle builder_error = grpc_channel_stack_builder_finish( builder, sizeof(grpc_channel), 1, destroy_channel, nullptr, reinterpret_cast(&channel)); if (builder_error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "channel stack builder failed: %s", - grpc_error_string(builder_error)); + grpc_error_std_string(builder_error).c_str()); GPR_ASSERT(channel == nullptr); if (error != nullptr) { *error = builder_error; @@ -225,7 +225,7 @@ grpc_channel* grpc_channel_create(const char* target, grpc_channel_stack_type channel_stack_type, grpc_transport* optional_transport, grpc_resource_user* resource_user, - grpc_error** error) { + grpc_error_handle* error) { // We need to make sure that grpc_shutdown() does not shut things down // until after the channel is destroyed. However, the channel may not // actually be destroyed by the time grpc_channel_destroy() returns, @@ -497,7 +497,7 @@ grpc_call* grpc_channel_create_registered_call( return call; } -static void destroy_channel(void* arg, grpc_error* /*error*/) { +static void destroy_channel(void* arg, grpc_error_handle /*error*/) { grpc_channel* channel = static_cast(arg); if (channel->channelz_node != nullptr) { channel->channelz_node->AddTraceEvent( diff --git a/src/core/lib/surface/channel.h b/src/core/lib/surface/channel.h index bb723636b89..8a14a72d131 100644 --- a/src/core/lib/surface/channel.h +++ b/src/core/lib/surface/channel.h @@ -35,7 +35,7 @@ grpc_channel* grpc_channel_create(const char* target, grpc_channel_stack_type channel_stack_type, grpc_transport* optional_transport, grpc_resource_user* resource_user = nullptr, - grpc_error** error = nullptr); + grpc_error_handle* error = nullptr); /** The same as grpc_channel_destroy, but doesn't create an ExecCtx, and so * is safe to use from within core. */ @@ -43,7 +43,8 @@ void grpc_channel_destroy_internal(grpc_channel* channel); grpc_channel* grpc_channel_create_with_builder( grpc_channel_stack_builder* builder, - grpc_channel_stack_type channel_stack_type, grpc_error** error = nullptr); + grpc_channel_stack_type channel_stack_type, + grpc_error_handle* error = nullptr); /** Create a call given a grpc_channel, in order to call \a method. Progress is tied to activity on \a pollset_set. The returned call object is diff --git a/src/core/lib/surface/channel_ping.cc b/src/core/lib/surface/channel_ping.cc index 82e552194b8..a6e53ec409e 100644 --- a/src/core/lib/surface/channel_ping.cc +++ b/src/core/lib/surface/channel_ping.cc @@ -38,7 +38,7 @@ static void ping_destroy(void* arg, grpc_cq_completion* /*storage*/) { gpr_free(arg); } -static void ping_done(void* arg, grpc_error* error) { +static void ping_done(void* arg, grpc_error_handle error) { ping_result* pr = static_cast(arg); grpc_cq_end_op(pr->cq, pr->tag, GRPC_ERROR_REF(error), ping_destroy, pr, &pr->completion_storage); diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc index 9091c9d442e..2b889e0de5c 100644 --- a/src/core/lib/surface/completion_queue.cc +++ b/src/core/lib/surface/completion_queue.cc @@ -70,10 +70,10 @@ struct cq_poller_vtable { bool can_listen; size_t (*size)(void); void (*init)(grpc_pollset* pollset, gpr_mu** mu); - grpc_error* (*kick)(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker); - grpc_error* (*work)(grpc_pollset* pollset, grpc_pollset_worker** worker, - grpc_millis deadline); + grpc_error_handle (*kick)(grpc_pollset* pollset, + grpc_pollset_worker* specific_worker); + grpc_error_handle (*work)(grpc_pollset* pollset, grpc_pollset_worker** worker, + grpc_millis deadline); void (*shutdown)(grpc_pollset* pollset, grpc_closure* closure); void (*destroy)(grpc_pollset* pollset); }; @@ -103,9 +103,9 @@ void non_polling_poller_destroy(grpc_pollset* pollset) { gpr_mu_destroy(&npp->mu); } -grpc_error* non_polling_poller_work(grpc_pollset* pollset, - grpc_pollset_worker** worker, - grpc_millis deadline) { +grpc_error_handle non_polling_poller_work(grpc_pollset* pollset, + grpc_pollset_worker** worker, + grpc_millis deadline) { non_polling_poller* npp = reinterpret_cast(pollset); if (npp->shutdown) return GRPC_ERROR_NONE; if (npp->kicked_without_poller) { @@ -145,8 +145,8 @@ grpc_error* non_polling_poller_work(grpc_pollset* pollset, return GRPC_ERROR_NONE; } -grpc_error* non_polling_poller_kick(grpc_pollset* pollset, - grpc_pollset_worker* specific_worker) { +grpc_error_handle non_polling_poller_kick( + grpc_pollset* pollset, grpc_pollset_worker* specific_worker) { non_polling_poller* p = reinterpret_cast(pollset); if (specific_worker == nullptr) { specific_worker = reinterpret_cast(p->root); @@ -202,7 +202,7 @@ struct cq_vtable { void (*shutdown)(grpc_completion_queue* cq); void (*destroy)(void* data); bool (*begin_op)(grpc_completion_queue* cq, void* tag); - void (*end_op)(grpc_completion_queue* cq, void* tag, grpc_error* error, + void (*end_op)(grpc_completion_queue* cq, void* tag, grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool internal); grpc_event (*next)(grpc_completion_queue* cq, gpr_timespec deadline, @@ -376,17 +376,17 @@ static bool cq_begin_op_for_callback(grpc_completion_queue* cq, void* tag); // safe to free up that storage. The storage MUST NOT be freed until the // done callback is invoked. static void cq_end_op_for_next( - grpc_completion_queue* cq, void* tag, grpc_error* error, + grpc_completion_queue* cq, void* tag, grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool internal); static void cq_end_op_for_pluck( - grpc_completion_queue* cq, void* tag, grpc_error* error, + grpc_completion_queue* cq, void* tag, grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool internal); static void cq_end_op_for_callback( - grpc_completion_queue* cq, void* tag, grpc_error* error, + grpc_completion_queue* cq, void* tag, grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool internal); @@ -439,7 +439,7 @@ grpc_core::TraceFlag grpc_cq_pluck_trace(false, "queue_pluck"); } \ } while (0) -static void on_pollset_shutdown_done(void* arg, grpc_error* error); +static void on_pollset_shutdown_done(void* arg, grpc_error_handle error); void grpc_cq_global_init() { gpr_tls_init(&g_cached_event); @@ -604,7 +604,7 @@ void grpc_cq_internal_ref(grpc_completion_queue* cq) { cq->owning_refs.Ref(debug_location, reason); } -static void on_pollset_shutdown_done(void* arg, grpc_error* /*error*/) { +static void on_pollset_shutdown_done(void* arg, grpc_error_handle /*error*/) { grpc_completion_queue* cq = static_cast(arg); GRPC_CQ_INTERNAL_UNREF(cq, "pollset_destroy"); } @@ -690,7 +690,7 @@ bool grpc_cq_begin_op(grpc_completion_queue* cq, void* tag) { * completion * type of GRPC_CQ_NEXT) */ static void cq_end_op_for_next( - grpc_completion_queue* cq, void* tag, grpc_error* error, + grpc_completion_queue* cq, void* tag, grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool /*internal*/) { GPR_TIMER_SCOPE("cq_end_op_for_next", 0); @@ -698,14 +698,15 @@ static void cq_end_op_for_next( if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) || (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures) && error != GRPC_ERROR_NONE)) { - const char* errmsg = grpc_error_string(error); + std::string errmsg = grpc_error_std_string(error); GRPC_API_TRACE( "cq_end_op_for_next(cq=%p, tag=%p, error=%s, " "done=%p, done_arg=%p, storage=%p)", - 6, (cq, tag, errmsg, done, done_arg, storage)); + 6, (cq, tag, errmsg.c_str(), done, done_arg, storage)); if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures) && error != GRPC_ERROR_NONE) { - gpr_log(GPR_INFO, "Operation failed: tag=%p, error=%s", tag, errmsg); + gpr_log(GPR_INFO, "Operation failed: tag=%p, error=%s", tag, + errmsg.c_str()); } } cq_next_data* cqd = static_cast DATA_FROM_CQ(cq); @@ -736,13 +737,13 @@ static void cq_end_op_for_next( /* Only kick if this is the first item queued */ if (is_first) { gpr_mu_lock(cq->mu); - grpc_error* kick_error = + grpc_error_handle kick_error = cq->poller_vtable->kick(POLLSET_FROM_CQ(cq), nullptr); gpr_mu_unlock(cq->mu); if (kick_error != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(kick_error); - gpr_log(GPR_ERROR, "Kick failed: %s", msg); + gpr_log(GPR_ERROR, "Kick failed: %s", + grpc_error_std_string(kick_error).c_str()); GRPC_ERROR_UNREF(kick_error); } } @@ -771,7 +772,7 @@ static void cq_end_op_for_next( * completion * type of GRPC_CQ_PLUCK) */ static void cq_end_op_for_pluck( - grpc_completion_queue* cq, void* tag, grpc_error* error, + grpc_completion_queue* cq, void* tag, grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool /*internal*/) { GPR_TIMER_SCOPE("cq_end_op_for_pluck", 0); @@ -782,14 +783,15 @@ static void cq_end_op_for_pluck( if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) || (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures) && error != GRPC_ERROR_NONE)) { - const char* errmsg = grpc_error_string(error); + std::string errmsg = grpc_error_std_string(error).c_str(); GRPC_API_TRACE( "cq_end_op_for_pluck(cq=%p, tag=%p, error=%s, " "done=%p, done_arg=%p, storage=%p)", - 6, (cq, tag, errmsg, done, done_arg, storage)); + 6, (cq, tag, errmsg.c_str(), done, done_arg, storage)); if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures) && error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg); + gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, + errmsg.c_str()); } } @@ -820,15 +822,12 @@ static void cq_end_op_for_pluck( } } - grpc_error* kick_error = + grpc_error_handle kick_error = cq->poller_vtable->kick(POLLSET_FROM_CQ(cq), pluck_worker); - gpr_mu_unlock(cq->mu); - if (kick_error != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(kick_error); - gpr_log(GPR_ERROR, "Kick failed: %s", msg); - + gpr_log(GPR_ERROR, "Kick failed: %s", + grpc_error_std_string(kick_error).c_str()); GRPC_ERROR_UNREF(kick_error); } } @@ -836,14 +835,14 @@ static void cq_end_op_for_pluck( GRPC_ERROR_UNREF(error); } -static void functor_callback(void* arg, grpc_error* error) { +static void functor_callback(void* arg, grpc_error_handle error) { auto* functor = static_cast(arg); functor->functor_run(functor, error == GRPC_ERROR_NONE); } /* Complete an event on a completion queue of type GRPC_CQ_CALLBACK */ static void cq_end_op_for_callback( - grpc_completion_queue* cq, void* tag, grpc_error* error, + grpc_completion_queue* cq, void* tag, grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool internal) { GPR_TIMER_SCOPE("cq_end_op_for_callback", 0); @@ -853,14 +852,15 @@ static void cq_end_op_for_callback( if (GRPC_TRACE_FLAG_ENABLED(grpc_api_trace) || (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures) && error != GRPC_ERROR_NONE)) { - const char* errmsg = grpc_error_string(error); + std::string errmsg = grpc_error_std_string(error); GRPC_API_TRACE( "cq_end_op_for_callback(cq=%p, tag=%p, error=%s, " "done=%p, done_arg=%p, storage=%p)", - 6, (cq, tag, errmsg, done, done_arg, storage)); + 6, (cq, tag, errmsg.c_str(), done, done_arg, storage)); if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_operation_failures) && error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, errmsg); + gpr_log(GPR_ERROR, "Operation failed: tag=%p, error=%s", tag, + errmsg.c_str()); } } @@ -896,7 +896,8 @@ static void cq_end_op_for_callback( GRPC_CLOSURE_CREATE(functor_callback, functor, nullptr), error); } -void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, grpc_error* error, +void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, + grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool internal) { @@ -1056,14 +1057,13 @@ static grpc_event cq_next(grpc_completion_queue* cq, gpr_timespec deadline, /* The main polling work happens in grpc_pollset_work */ gpr_mu_lock(cq->mu); cq->num_polls++; - grpc_error* err = cq->poller_vtable->work(POLLSET_FROM_CQ(cq), nullptr, - iteration_deadline); + grpc_error_handle err = cq->poller_vtable->work( + POLLSET_FROM_CQ(cq), nullptr, iteration_deadline); gpr_mu_unlock(cq->mu); if (err != GRPC_ERROR_NONE) { - const char* msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "Completion queue next failed: %s", msg); - + gpr_log(GPR_ERROR, "Completion queue next failed: %s", + grpc_error_std_string(err).c_str()); GRPC_ERROR_UNREF(err); ret.type = GRPC_QUEUE_TIMEOUT; ret.success = 0; @@ -1299,14 +1299,13 @@ static grpc_event cq_pluck(grpc_completion_queue* cq, void* tag, break; } cq->num_polls++; - grpc_error* err = + grpc_error_handle err = cq->poller_vtable->work(POLLSET_FROM_CQ(cq), &worker, deadline_millis); if (err != GRPC_ERROR_NONE) { del_plucker(cq, tag, &worker); gpr_mu_unlock(cq->mu); - const char* msg = grpc_error_string(err); - gpr_log(GPR_ERROR, "Completion queue pluck failed: %s", msg); - + gpr_log(GPR_ERROR, "Completion queue pluck failed: %s", + grpc_error_std_string(err).c_str()); GRPC_ERROR_UNREF(err); ret.type = GRPC_QUEUE_TIMEOUT; ret.success = 0; diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h index 59116d43281..2bf91faf6f9 100644 --- a/src/core/lib/surface/completion_queue.h +++ b/src/core/lib/surface/completion_queue.h @@ -77,7 +77,8 @@ bool grpc_cq_begin_op(grpc_completion_queue* cq, void* tag); /* Queue a GRPC_OP_COMPLETED operation; tag must correspond to the tag passed to grpc_cq_begin_op */ -void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, grpc_error* error, +void grpc_cq_end_op(grpc_completion_queue* cq, void* tag, + grpc_error_handle error, void (*done)(void* done_arg, grpc_cq_completion* storage), void* done_arg, grpc_cq_completion* storage, bool internal = false); diff --git a/src/core/lib/surface/lame_client.cc b/src/core/lib/surface/lame_client.cc index f92c1920df3..65e659ac763 100644 --- a/src/core/lib/surface/lame_client.cc +++ b/src/core/lib/surface/lame_client.cc @@ -44,14 +44,14 @@ namespace { struct ChannelData { explicit ChannelData(grpc_channel_element_args* args) : state_tracker("lame_channel", GRPC_CHANNEL_SHUTDOWN) { - grpc_error* err = grpc_channel_args_find_pointer( + grpc_error_handle err = grpc_channel_args_find_pointer( args->channel_args, GRPC_ARG_LAME_FILTER_ERROR); if (err != nullptr) error = GRPC_ERROR_REF(err); } ~ChannelData() { GRPC_ERROR_UNREF(error); } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Mutex mu; ConnectivityStateTracker state_tracker; }; @@ -98,8 +98,8 @@ static void lame_start_transport_op(grpc_channel_element* elem, } } -static grpc_error* lame_init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { +static grpc_error_handle lame_init_call_elem( + grpc_call_element* elem, const grpc_call_element_args* args) { CallData* calld = static_cast(elem->call_data); calld->call_combiner = args->call_combiner; return GRPC_ERROR_NONE; @@ -111,8 +111,8 @@ static void lame_destroy_call_elem(grpc_call_element* /*elem*/, ExecCtx::Run(DEBUG_LOCATION, then_schedule_closure, GRPC_ERROR_NONE); } -static grpc_error* lame_init_channel_elem(grpc_channel_element* elem, - grpc_channel_element_args* args) { +static grpc_error_handle lame_init_channel_elem( + grpc_channel_element* elem, grpc_channel_element_args* args) { new (elem->channel_data) ChannelData(args); return GRPC_ERROR_NONE; } @@ -122,13 +122,13 @@ static void lame_destroy_channel_elem(grpc_channel_element* elem) { chand->~ChannelData(); } -// Channel arg vtable for a grpc_error*. +// Channel arg vtable for a grpc_error_handle. void* ErrorCopy(void* p) { - grpc_error* error = static_cast(p); + grpc_error_handle error = static_cast(p); return GRPC_ERROR_REF(error); } void ErrorDestroy(void* p) { - grpc_error* error = static_cast(p); + grpc_error_handle error = static_cast(p); GRPC_ERROR_UNREF(error); } int ErrorCompare(void* p, void* q) { return GPR_ICMP(p, q); } @@ -137,7 +137,7 @@ const grpc_arg_pointer_vtable kLameFilterErrorArgVtable = { } // namespace -grpc_arg MakeLameClientErrorArg(grpc_error* error) { +grpc_arg MakeLameClientErrorArg(grpc_error_handle error) { return grpc_channel_arg_pointer_create( const_cast(GRPC_ARG_LAME_FILTER_ERROR), error, &kLameFilterErrorArgVtable); @@ -169,7 +169,7 @@ grpc_channel* grpc_lame_client_channel_create(const char* target, "grpc_lame_client_channel_create(target=%s, error_code=%d, " "error_message=%s)", 3, (target, (int)error_code, error_message)); - grpc_error* error = grpc_error_set_str( + grpc_error_handle error = grpc_error_set_str( grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("lame client channel"), GRPC_ERROR_INT_GRPC_STATUS, error_code), diff --git a/src/core/lib/surface/lame_client.h b/src/core/lib/surface/lame_client.h index 94c7e553ad8..41759cbb8ce 100644 --- a/src/core/lib/surface/lame_client.h +++ b/src/core/lib/surface/lame_client.h @@ -25,7 +25,7 @@ namespace grpc_core { // Does NOT take ownership of error. -grpc_arg MakeLameClientErrorArg(grpc_error* error); +grpc_arg MakeLameClientErrorArg(grpc_error_handle error); } // namespace grpc_core extern const grpc_channel_filter grpc_lame_filter; diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc index 7dce6c7ee8e..a8b4aaaecf9 100644 --- a/src/core/lib/surface/server.cc +++ b/src/core/lib/surface/server.cc @@ -159,7 +159,7 @@ class Server::RequestMatcherInterface { // Mark all application-requested RPCs failed if they have not been matched to // an incoming RPC. The error parameter indicates why the RPCs are being // failed (always server shutdown in all current implementations). - virtual void KillRequests(grpc_error* error) = 0; + virtual void KillRequests(grpc_error_handle error) = 0; // How many request queues are supported by this matcher. This is an abstract // concept that essentially maps to gRPC completion queues. @@ -211,7 +211,7 @@ class Server::RealRequestMatcher : public RequestMatcherInterface { } } - void KillRequests(grpc_error* error) override { + void KillRequests(grpc_error_handle error) override { for (size_t i = 0; i < requests_per_cq_.size(); i++) { RequestedCall* rc; while ((rc = reinterpret_cast( @@ -336,7 +336,9 @@ class Server::AllocatingRequestMatcherBase : public RequestMatcherInterface { void ZombifyPending() override {} - void KillRequests(grpc_error* error) override { GRPC_ERROR_UNREF(error); } + void KillRequests(grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } size_t request_queue_count() const override { return 0; } @@ -444,7 +446,7 @@ class ChannelBroadcaster { } // Broadcasts a shutdown on each channel. - void BroadcastShutdown(bool send_goaway, grpc_error* force_disconnect) { + void BroadcastShutdown(bool send_goaway, grpc_error_handle force_disconnect) { for (grpc_channel* channel : channels_) { SendShutdown(channel, send_goaway, GRPC_ERROR_REF(force_disconnect)); GRPC_CHANNEL_INTERNAL_UNREF(channel, "broadcast"); @@ -459,14 +461,14 @@ class ChannelBroadcaster { grpc_slice slice; }; - static void ShutdownCleanup(void* arg, grpc_error* /*error*/) { + static void ShutdownCleanup(void* arg, grpc_error_handle /*error*/) { ShutdownCleanupArgs* a = static_cast(arg); grpc_slice_unref_internal(a->slice); delete a; } static void SendShutdown(grpc_channel* channel, bool send_goaway, - grpc_error* send_disconnect) { + grpc_error_handle send_disconnect) { ShutdownCleanupArgs* sc = new ShutdownCleanupArgs; GRPC_CLOSURE_INIT(&sc->closure, ShutdownCleanup, sc, grpc_schedule_on_exec_ctx); @@ -607,13 +609,13 @@ void Server::Start() { starting_cv_.Signal(); } -grpc_error* Server::SetupTransport( +grpc_error_handle Server::SetupTransport( grpc_transport* transport, grpc_pollset* accepting_pollset, const grpc_channel_args* args, const RefCountedPtr& socket_node, grpc_resource_user* resource_user) { // Create channel. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_channel* channel = grpc_channel_create( nullptr, args, GRPC_SERVER_CHANNEL, transport, resource_user, &error); if (channel == nullptr) { @@ -710,7 +712,8 @@ void Server::DoneRequestEvent(void* req, grpc_cq_completion* /*c*/) { delete static_cast(req); } -void Server::FailCall(size_t cq_idx, RequestedCall* rc, grpc_error* error) { +void Server::FailCall(size_t cq_idx, RequestedCall* rc, + grpc_error_handle error) { *rc->call = nullptr; rc->initial_metadata->count = 0; GPR_ASSERT(error != GRPC_ERROR_NONE); @@ -750,7 +753,7 @@ void Server::MaybeFinishShutdown() { } } -void Server::KillPendingWorkLocked(grpc_error* error) { +void Server::KillPendingWorkLocked(grpc_error_handle error) { if (started_) { unregistered_request_matcher_->KillRequests(GRPC_ERROR_REF(error)); unregistered_request_matcher_->ZombifyPending(); @@ -772,7 +775,7 @@ std::vector Server::GetChannelsLocked() const { return channels; } -void Server::ListenerDestroyDone(void* arg, grpc_error* /*error*/) { +void Server::ListenerDestroyDone(void* arg, grpc_error_handle /*error*/) { Server* server = static_cast(arg); MutexLock lock(&server->mu_global_); server->listeners_destroyed_++; @@ -877,7 +880,7 @@ grpc_call_error Server::ValidateServerRequest( (rm->payload_handling == GRPC_SRM_PAYLOAD_NONE)))) { return GRPC_CALL_ERROR_PAYLOAD_TYPE_MISMATCH; } - if (grpc_cq_begin_op(cq_for_notification, tag) == false) { + if (!grpc_cq_begin_op(cq_for_notification, tag)) { return GRPC_CALL_ERROR_COMPLETION_QUEUE_SHUTDOWN; } return GRPC_CALL_OK; @@ -1134,7 +1137,7 @@ void Server::ChannelData::AcceptStream(void* arg, grpc_transport* /*transport*/, args.add_initial_metadata_count = 0; args.send_deadline = GRPC_MILLIS_INF_FUTURE; grpc_call* call; - grpc_error* error = grpc_call_create(&args, &call); + grpc_error_handle error = grpc_call_create(&args, &call); grpc_call_element* elem = grpc_call_stack_element(grpc_call_get_call_stack(call), 0); auto* calld = static_cast(elem->call_data); @@ -1146,7 +1149,8 @@ void Server::ChannelData::AcceptStream(void* arg, grpc_transport* /*transport*/, calld->Start(elem); } -void Server::ChannelData::FinishDestroy(void* arg, grpc_error* /*error*/) { +void Server::ChannelData::FinishDestroy(void* arg, + grpc_error_handle /*error*/) { auto* chand = static_cast(arg); Server* server = chand->server_.get(); GRPC_CHANNEL_INTERNAL_UNREF(chand->channel_, "server"); @@ -1173,7 +1177,7 @@ void Server::ChannelData::Destroy() { op); } -grpc_error* Server::ChannelData::InitChannelElement( +grpc_error_handle Server::ChannelData::InitChannelElement( grpc_channel_element* elem, grpc_channel_element_args* args) { GPR_ASSERT(args->is_first); GPR_ASSERT(!args->is_last); @@ -1284,7 +1288,7 @@ void Server::CallData::Publish(size_t cq_idx, RequestedCall* rc) { rc, &rc->completion, true); } -void Server::CallData::PublishNewRpc(void* arg, grpc_error* error) { +void Server::CallData::PublishNewRpc(void* arg, grpc_error_handle error) { grpc_call_element* call_elem = static_cast(arg); auto* calld = static_cast(call_elem->call_data); auto* chand = static_cast(call_elem->channel_data); @@ -1300,7 +1304,7 @@ void Server::CallData::PublishNewRpc(void* arg, grpc_error* error) { namespace { -void KillZombieClosure(void* call, grpc_error* /*error*/) { +void KillZombieClosure(void* call, grpc_error_handle /*error*/) { grpc_call_unref(static_cast(call)); } @@ -1352,8 +1356,8 @@ void Server::CallData::StartNewRpc(grpc_call_element* elem) { } } -void Server::CallData::RecvInitialMetadataBatchComplete(void* arg, - grpc_error* error) { +void Server::CallData::RecvInitialMetadataBatchComplete( + void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); auto* calld = static_cast(elem->call_data); if (error != GRPC_ERROR_NONE) { @@ -1385,7 +1389,8 @@ void Server::CallData::StartTransportStreamOpBatchImpl( grpc_call_next_op(elem, batch); } -void Server::CallData::RecvInitialMetadataReady(void* arg, grpc_error* error) { +void Server::CallData::RecvInitialMetadataReady(void* arg, + grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); CallData* calld = static_cast(elem->call_data); grpc_millis op_deadline; @@ -1411,7 +1416,7 @@ void Server::CallData::RecvInitialMetadataReady(void* arg, grpc_error* error) { /* do nothing */ } else { /* Pass the error reference to calld->recv_initial_metadata_error */ - grpc_error* src_error = error; + grpc_error_handle src_error = error; error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Missing :authority or :path", &src_error, 1); GRPC_ERROR_UNREF(src_error); @@ -1428,7 +1433,8 @@ void Server::CallData::RecvInitialMetadataReady(void* arg, grpc_error* error) { Closure::Run(DEBUG_LOCATION, closure, error); } -void Server::CallData::RecvTrailingMetadataReady(void* arg, grpc_error* error) { +void Server::CallData::RecvTrailingMetadataReady(void* arg, + grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); CallData* calld = static_cast(elem->call_data); if (calld->original_recv_initial_metadata_ready_ != nullptr) { @@ -1449,7 +1455,7 @@ void Server::CallData::RecvTrailingMetadataReady(void* arg, grpc_error* error) { error); } -grpc_error* Server::CallData::InitCallElement( +grpc_error_handle Server::CallData::InitCallElement( grpc_call_element* elem, const grpc_call_element_args* args) { auto* chand = static_cast(elem->channel_data); new (elem->call_data) Server::CallData(elem, *args, chand->server()); diff --git a/src/core/lib/surface/server.h b/src/core/lib/surface/server.h index fee963ba0ee..413a5a8a0a2 100644 --- a/src/core/lib/surface/server.h +++ b/src/core/lib/surface/server.h @@ -22,6 +22,7 @@ #include #include +#include "absl/status/statusor.h" #include "absl/types/optional.h" #include @@ -31,6 +32,7 @@ #include "src/core/lib/channel/channelz.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/atomic.h" +#include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/transport/transport.h" @@ -126,7 +128,7 @@ class Server : public InternallyRefCounted { // Sets up a transport. Creates a channel stack and binds the transport to // the server. Called from the listener when a new connection is accepted. - grpc_error* SetupTransport( + grpc_error_handle SetupTransport( grpc_transport* transport, grpc_pollset* accepting_pollset, const grpc_channel_args* args, const RefCountedPtr& socket_node, @@ -200,8 +202,8 @@ class Server : public InternallyRefCounted { bool is_idempotent); // Filter vtable functions. - static grpc_error* InitChannelElement(grpc_channel_element* elem, - grpc_channel_element_args* args); + static grpc_error_handle InitChannelElement( + grpc_channel_element* elem, grpc_channel_element_args* args); static void DestroyChannelElement(grpc_channel_element* elem); private: @@ -212,7 +214,7 @@ class Server : public InternallyRefCounted { void Destroy() ABSL_EXCLUSIVE_LOCKS_REQUIRED(server_->mu_global_); - static void FinishDestroy(void* arg, grpc_error* error); + static void FinishDestroy(void* arg, grpc_error_handle error); RefCountedPtr server_; grpc_channel* channel_; @@ -262,8 +264,8 @@ class Server : public InternallyRefCounted { void FailCallCreation(); // Filter vtable functions. - static grpc_error* InitCallElement(grpc_call_element* elem, - const grpc_call_element_args* args); + static grpc_error_handle InitCallElement( + grpc_call_element* elem, const grpc_call_element_args* args); static void DestroyCallElement(grpc_call_element* elem, const grpc_call_final_info* /*final_info*/, grpc_closure* /*ignored*/); @@ -272,15 +274,16 @@ class Server : public InternallyRefCounted { private: // Helper functions for handling calls at the top of the call stack. - static void RecvInitialMetadataBatchComplete(void* arg, grpc_error* error); + static void RecvInitialMetadataBatchComplete(void* arg, + grpc_error_handle error); void StartNewRpc(grpc_call_element* elem); - static void PublishNewRpc(void* arg, grpc_error* error); + static void PublishNewRpc(void* arg, grpc_error_handle error); // Functions used inside the call stack. void StartTransportStreamOpBatchImpl(grpc_call_element* elem, grpc_transport_stream_op_batch* batch); - static void RecvInitialMetadataReady(void* arg, grpc_error* error); - static void RecvTrailingMetadataReady(void* arg, grpc_error* error); + static void RecvInitialMetadataReady(void* arg, grpc_error_handle error); + static void RecvTrailingMetadataReady(void* arg, grpc_error_handle error); RefCountedPtr server_; @@ -307,12 +310,12 @@ class Server : public InternallyRefCounted { uint32_t recv_initial_metadata_flags_ = 0; grpc_closure recv_initial_metadata_ready_; grpc_closure* original_recv_initial_metadata_ready_; - grpc_error* recv_initial_metadata_error_ = GRPC_ERROR_NONE; + grpc_error_handle recv_initial_metadata_error_ = GRPC_ERROR_NONE; bool seen_recv_trailing_metadata_ready_ = false; grpc_closure recv_trailing_metadata_ready_; grpc_closure* original_recv_trailing_metadata_ready_; - grpc_error* recv_trailing_metadata_error_ = GRPC_ERROR_NONE; + grpc_error_handle recv_trailing_metadata_error_ = GRPC_ERROR_NONE; grpc_closure publish_; @@ -334,7 +337,7 @@ class Server : public InternallyRefCounted { grpc_cq_completion completion; }; - static void ListenerDestroyDone(void* arg, grpc_error* error); + static void ListenerDestroyDone(void* arg, grpc_error_handle error); static void DoneShutdownEvent(void* server, grpc_cq_completion* /*completion*/) { @@ -343,13 +346,13 @@ class Server : public InternallyRefCounted { static void DoneRequestEvent(void* req, grpc_cq_completion* completion); - void FailCall(size_t cq_idx, RequestedCall* rc, grpc_error* error); + void FailCall(size_t cq_idx, RequestedCall* rc, grpc_error_handle error); grpc_call_error QueueRequestedCall(size_t cq_idx, RequestedCall* rc); void MaybeFinishShutdown() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_global_) ABSL_LOCKS_EXCLUDED(mu_call_); - void KillPendingWorkLocked(grpc_error* error) + void KillPendingWorkLocked(grpc_error_handle error) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_call_); static grpc_call_error ValidateServerRequest( @@ -456,11 +459,24 @@ struct grpc_server { // approaches here. struct grpc_server_config_fetcher { public: + class ConnectionManager : public grpc_core::RefCounted { + public: + // Ownership of \a args is transfered. + virtual absl::StatusOr UpdateChannelArgsForConnection( + grpc_channel_args* args, grpc_endpoint* tcp) = 0; + }; + class WatcherInterface { public: virtual ~WatcherInterface() = default; - // Ownership of \a args is transferred. - virtual void UpdateConfig(grpc_channel_args* args) = 0; + // UpdateConnectionManager() is invoked by the config fetcher when a new + // config is available. Implementations should update the connection manager + // and start serving if not already serving. + virtual void UpdateConnectionManager( + grpc_core::RefCountedPtr manager) = 0; + // Implementations should stop serving when this is called. Serving should + // only resume when UpdateConfig() is invoked. + virtual void StopServing() = 0; }; virtual ~grpc_server_config_fetcher() = default; diff --git a/src/core/lib/surface/validate_metadata.cc b/src/core/lib/surface/validate_metadata.cc index 138f5745e51..c1ec936e471 100644 --- a/src/core/lib/surface/validate_metadata.cc +++ b/src/core/lib/surface/validate_metadata.cc @@ -30,9 +30,9 @@ #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/validate_metadata.h" -static grpc_error* conforms_to(const grpc_slice& slice, - const uint8_t* legal_bits, - const char* err_desc) { +static grpc_error_handle conforms_to(const grpc_slice& slice, + const uint8_t* legal_bits, + const char* err_desc) { const uint8_t* p = GRPC_SLICE_START_PTR(slice); const uint8_t* e = GRPC_SLICE_END_PTR(slice); for (; p != e; p++) { @@ -40,7 +40,7 @@ static grpc_error* conforms_to(const grpc_slice& slice, int byte = idx / 8; int bit = idx % 8; if ((legal_bits[byte] & (1 << bit)) == 0) { - grpc_error* error = grpc_error_set_str( + grpc_error_handle error = grpc_error_set_str( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_desc), GRPC_ERROR_INT_OFFSET, p - GRPC_SLICE_START_PTR(slice)), @@ -52,13 +52,13 @@ static grpc_error* conforms_to(const grpc_slice& slice, return GRPC_ERROR_NONE; } -static int error2int(grpc_error* error) { +static int error2int(grpc_error_handle error) { int r = (error == GRPC_ERROR_NONE); GRPC_ERROR_UNREF(error); return r; } -grpc_error* grpc_validate_header_key_is_legal(const grpc_slice& slice) { +grpc_error_handle grpc_validate_header_key_is_legal(const grpc_slice& slice) { static const uint8_t legal_header_bits[256 / 8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xff, 0x03, 0x00, 0x00, 0x00, 0x80, 0xfe, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -82,7 +82,7 @@ int grpc_header_key_is_legal(grpc_slice slice) { return error2int(grpc_validate_header_key_is_legal(slice)); } -grpc_error* grpc_validate_header_nonbin_value_is_legal( +grpc_error_handle grpc_validate_header_nonbin_value_is_legal( const grpc_slice& slice) { static const uint8_t legal_header_bits[256 / 8] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/src/core/lib/surface/validate_metadata.h b/src/core/lib/surface/validate_metadata.h index 07c802c98b8..daaaa1a3783 100644 --- a/src/core/lib/surface/validate_metadata.h +++ b/src/core/lib/surface/validate_metadata.h @@ -27,8 +27,9 @@ #include "src/core/lib/iomgr/error.h" -grpc_error* grpc_validate_header_key_is_legal(const grpc_slice& slice); -grpc_error* grpc_validate_header_nonbin_value_is_legal(const grpc_slice& slice); +grpc_error_handle grpc_validate_header_key_is_legal(const grpc_slice& slice); +grpc_error_handle grpc_validate_header_nonbin_value_is_legal( + const grpc_slice& slice); int grpc_is_binary_header_internal(const grpc_slice& slice); inline int grpc_key_is_binary_header(const uint8_t* buf, size_t length) { diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc index 737c2eb1bff..8061df0cf42 100644 --- a/src/core/lib/surface/version.cc +++ b/src/core/lib/surface/version.cc @@ -23,6 +23,8 @@ #include -const char* grpc_version_string(void) { return "15.0.0"; } +const char* grpc_version_string(void) { return "16.0.0"; } -const char* grpc_g_stands_for(void) { return "gilded"; } +const char* grpc_g_stands_for(void) { + return "guadalupe_river_park_conservancy"; +} diff --git a/src/core/lib/transport/byte_stream.cc b/src/core/lib/transport/byte_stream.cc index 82f34ca1504..3cc5275e51d 100644 --- a/src/core/lib/transport/byte_stream.cc +++ b/src/core/lib/transport/byte_stream.cc @@ -59,7 +59,7 @@ bool SliceBufferByteStream::Next(size_t /*max_size_hint*/, return true; } -grpc_error* SliceBufferByteStream::Pull(grpc_slice* slice) { +grpc_error_handle SliceBufferByteStream::Pull(grpc_slice* slice) { if (GPR_UNLIKELY(shutdown_error_ != GRPC_ERROR_NONE)) { return GRPC_ERROR_REF(shutdown_error_); } @@ -67,7 +67,7 @@ grpc_error* SliceBufferByteStream::Pull(grpc_slice* slice) { return GRPC_ERROR_NONE; } -void SliceBufferByteStream::Shutdown(grpc_error* error) { +void SliceBufferByteStream::Shutdown(grpc_error_handle error) { GRPC_ERROR_UNREF(shutdown_error_); shutdown_error_ = error; } @@ -117,7 +117,7 @@ bool ByteStreamCache::CachingByteStream::Next(size_t max_size_hint, return cache_->underlying_stream_->Next(max_size_hint, on_complete); } -grpc_error* ByteStreamCache::CachingByteStream::Pull(grpc_slice* slice) { +grpc_error_handle ByteStreamCache::CachingByteStream::Pull(grpc_slice* slice) { if (shutdown_error_ != GRPC_ERROR_NONE) { return GRPC_ERROR_REF(shutdown_error_); } @@ -128,7 +128,7 @@ grpc_error* ByteStreamCache::CachingByteStream::Pull(grpc_slice* slice) { return GRPC_ERROR_NONE; } GPR_ASSERT(cache_->underlying_stream_ != nullptr); - grpc_error* error = cache_->underlying_stream_->Pull(slice); + grpc_error_handle error = cache_->underlying_stream_->Pull(slice); if (error == GRPC_ERROR_NONE) { grpc_slice_buffer_add(&cache_->cache_buffer_, grpc_slice_ref_internal(*slice)); @@ -142,7 +142,7 @@ grpc_error* ByteStreamCache::CachingByteStream::Pull(grpc_slice* slice) { return error; } -void ByteStreamCache::CachingByteStream::Shutdown(grpc_error* error) { +void ByteStreamCache::CachingByteStream::Shutdown(grpc_error_handle error) { GRPC_ERROR_UNREF(shutdown_error_); shutdown_error_ = GRPC_ERROR_REF(error); if (cache_->underlying_stream_ != nullptr) { diff --git a/src/core/lib/transport/byte_stream.h b/src/core/lib/transport/byte_stream.h index e83fb626b32..09a3032641d 100644 --- a/src/core/lib/transport/byte_stream.h +++ b/src/core/lib/transport/byte_stream.h @@ -56,7 +56,7 @@ class ByteStream : public Orphanable { // indicated by Next(). // // Once a slice is returned into *slice, it is owned by the caller. - virtual grpc_error* Pull(grpc_slice* slice) = 0; + virtual grpc_error_handle Pull(grpc_slice* slice) = 0; // Shuts down the byte stream. // @@ -65,7 +65,7 @@ class ByteStream : public Orphanable { // // The next call to Pull() (if any) will return the error passed to // Shutdown(). - virtual void Shutdown(grpc_error* error) = 0; + virtual void Shutdown(grpc_error_handle error) = 0; uint32_t length() const { return length_; } uint32_t flags() const { return flags_; } @@ -97,11 +97,11 @@ class SliceBufferByteStream : public ByteStream { void Orphan() override; bool Next(size_t max_size_hint, grpc_closure* on_complete) override; - grpc_error* Pull(grpc_slice* slice) override; - void Shutdown(grpc_error* error) override; + grpc_error_handle Pull(grpc_slice* slice) override; + void Shutdown(grpc_error_handle error) override; private: - grpc_error* shutdown_error_ = GRPC_ERROR_NONE; + grpc_error_handle shutdown_error_ = GRPC_ERROR_NONE; grpc_slice_buffer backing_buffer_; }; @@ -131,8 +131,8 @@ class ByteStreamCache { void Orphan() override; bool Next(size_t max_size_hint, grpc_closure* on_complete) override; - grpc_error* Pull(grpc_slice* slice) override; - void Shutdown(grpc_error* error) override; + grpc_error_handle Pull(grpc_slice* slice) override; + void Shutdown(grpc_error_handle error) override; // Resets the byte stream to the start of the underlying stream. void Reset(); @@ -141,7 +141,7 @@ class ByteStreamCache { ByteStreamCache* cache_; size_t cursor_ = 0; size_t offset_ = 0; - grpc_error* shutdown_error_ = GRPC_ERROR_NONE; + grpc_error_handle shutdown_error_ = GRPC_ERROR_NONE; }; explicit ByteStreamCache(OrphanablePtr underlying_stream); diff --git a/src/core/lib/transport/connectivity_state.cc b/src/core/lib/transport/connectivity_state.cc index c2008ab82b7..01a4f5cbf82 100644 --- a/src/core/lib/transport/connectivity_state.cc +++ b/src/core/lib/transport/connectivity_state.cc @@ -73,7 +73,7 @@ class AsyncConnectivityStateWatcherInterface::Notifier { } private: - static void SendNotification(void* arg, grpc_error* /*ignored*/) { + static void SendNotification(void* arg, grpc_error_handle /*ignored*/) { Notifier* self = static_cast(arg); if (GRPC_TRACE_FLAG_ENABLED(grpc_connectivity_state_trace)) { gpr_log(GPR_INFO, "watcher %p: delivering async notification for %s (%s)", diff --git a/src/core/lib/transport/error_utils.cc b/src/core/lib/transport/error_utils.cc index c6ef8ae636b..e8f05550c96 100644 --- a/src/core/lib/transport/error_utils.cc +++ b/src/core/lib/transport/error_utils.cc @@ -25,8 +25,8 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/status_conversion.h" -static grpc_error* recursively_find_error_with_field(grpc_error* error, - grpc_error_ints which) { +static grpc_error_handle recursively_find_error_with_field( + grpc_error_handle error, grpc_error_ints which) { intptr_t unused; // If the error itself has a status code, return it. if (grpc_error_get_int(error, which, &unused)) { @@ -38,14 +38,15 @@ static grpc_error* recursively_find_error_with_field(grpc_error* error, while (slot != UINT8_MAX) { grpc_linked_error* lerr = reinterpret_cast(error->arena + slot); - grpc_error* result = recursively_find_error_with_field(lerr->err, which); + grpc_error_handle result = + recursively_find_error_with_field(lerr->err, which); if (result) return result; slot = lerr->next; } return nullptr; } -void grpc_error_get_status(grpc_error* error, grpc_millis deadline, +void grpc_error_get_status(grpc_error_handle error, grpc_millis deadline, grpc_status_code* code, grpc_slice* slice, grpc_http2_error_code* http_error, const char** error_string) { @@ -71,7 +72,7 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline, // Start with the parent error and recurse through the tree of children // until we find the first one that has a status code. - grpc_error* found_error = + grpc_error_handle found_error = recursively_find_error_with_field(error, GRPC_ERROR_INT_GRPC_STATUS); if (found_error == nullptr) { /// If no grpc-status exists, retry through the tree to find a http2 error @@ -96,7 +97,7 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline, if (code != nullptr) *code = status; if (error_string != nullptr && status != GRPC_STATUS_OK) { - *error_string = gpr_strdup(grpc_error_string(error)); + *error_string = gpr_strdup(grpc_error_std_string(error).c_str()); } if (http_error != nullptr) { @@ -123,7 +124,7 @@ void grpc_error_get_status(grpc_error* error, grpc_millis deadline, } } -absl::Status grpc_error_to_absl_status(grpc_error* error) { +absl::Status grpc_error_to_absl_status(grpc_error_handle error) { grpc_status_code status; // TODO(yashykt): This should be updated once we decide on how to use the // absl::Status payload to capture all the contents of grpc_error. @@ -136,7 +137,17 @@ absl::Status grpc_error_to_absl_status(grpc_error* error) { GRPC_SLICE_LENGTH(message))); } -bool grpc_error_has_clear_grpc_status(grpc_error* error) { +grpc_error_handle absl_status_to_grpc_error(absl::Status status) { + // Special error checks + if (status.ok()) { + return GRPC_ERROR_NONE; + } + return grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STRING_VIEW(status.message()), + GRPC_ERROR_INT_GRPC_STATUS, static_cast(status.code())); +} + +bool grpc_error_has_clear_grpc_status(grpc_error_handle error) { intptr_t unused; if (grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &unused)) { return true; diff --git a/src/core/lib/transport/error_utils.h b/src/core/lib/transport/error_utils.h index c61320d42b9..777e63230fa 100644 --- a/src/core/lib/transport/error_utils.h +++ b/src/core/lib/transport/error_utils.h @@ -34,19 +34,25 @@ /// be populated with the entire error string. If any of the attributes (code, /// msg, http_status, error_string) are unneeded, they can be passed as /// NULL. -void grpc_error_get_status(grpc_error* error, grpc_millis deadline, +void grpc_error_get_status(grpc_error_handle error, grpc_millis deadline, grpc_status_code* code, grpc_slice* slice, grpc_http2_error_code* http_error, const char** error_string); -/// Utility Function to convert a grpc_error * \a error to an absl::Status. -/// Does NOT consume a ref to grpc_error. -absl::Status grpc_error_to_absl_status(grpc_error* error); +/// Utility Function to convert a grpc_error_handle \a error to an +/// absl::Status. Does NOT consume a ref to grpc_error. +absl::Status grpc_error_to_absl_status(grpc_error_handle error); + +/// Utility function to convert an absl::Status \a status to grpc_error. Note +/// that this method does not return "special case" errors such as +/// GRPC_ERROR_CANCELLED, with the exception of GRPC_ERROR_NONE returned for +/// \a absl::OkStatus(). +grpc_error_handle absl_status_to_grpc_error(absl::Status status); /// A utility function to check whether there is a clear status code that /// doesn't need to be guessed in \a error. This means that \a error or some /// child has GRPC_ERROR_INT_GRPC_STATUS set, or that it is GRPC_ERROR_NONE or /// GRPC_ERROR_CANCELLED -bool grpc_error_has_clear_grpc_status(grpc_error* error); +bool grpc_error_has_clear_grpc_status(grpc_error_handle error); #endif /* GRPC_CORE_LIB_TRANSPORT_ERROR_UTILS_H */ diff --git a/src/core/lib/transport/metadata_batch.cc b/src/core/lib/transport/metadata_batch.cc index 410d810788a..e85b476ca42 100644 --- a/src/core/lib/transport/metadata_batch.cc +++ b/src/core/lib/transport/metadata_batch.cc @@ -94,22 +94,23 @@ void grpc_metadata_batch_destroy(grpc_metadata_batch* batch) { } } -grpc_error* grpc_attach_md_to_error(grpc_error* src, grpc_mdelem md) { - grpc_error* out = grpc_error_set_str( +grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src, + grpc_mdelem md) { + grpc_error_handle out = grpc_error_set_str( grpc_error_set_str(src, GRPC_ERROR_STR_KEY, grpc_slice_ref_internal(GRPC_MDKEY(md))), GRPC_ERROR_STR_VALUE, grpc_slice_ref_internal(GRPC_MDVALUE(md))); return out; } -static grpc_error* GPR_ATTRIBUTE_NOINLINE error_with_md(grpc_mdelem md) { +static grpc_error_handle GPR_ATTRIBUTE_NOINLINE error_with_md(grpc_mdelem md) { return grpc_attach_md_to_error( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unallowed duplicate metadata"), md); } -static grpc_error* link_callout(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) { +static grpc_error_handle link_callout(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage, + grpc_metadata_batch_callouts_index idx) { GPR_DEBUG_ASSERT(idx >= 0 && idx < GRPC_BATCH_CALLOUTS_COUNT); if (GPR_LIKELY(batch->idx.array[idx] == nullptr)) { ++batch->list.default_count; @@ -119,12 +120,12 @@ static grpc_error* link_callout(grpc_metadata_batch* batch, return error_with_md(storage->md); } -static grpc_error* maybe_link_callout(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) +static grpc_error_handle maybe_link_callout(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; -static grpc_error* maybe_link_callout(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { +static grpc_error_handle maybe_link_callout(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage) { grpc_metadata_batch_callouts_index idx = GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); if (idx == GRPC_BATCH_CALLOUTS_COUNT) { @@ -145,9 +146,9 @@ static void maybe_unlink_callout(grpc_metadata_batch* batch, batch->idx.array[idx] = nullptr; } -grpc_error* grpc_metadata_batch_add_head(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { +grpc_error_handle grpc_metadata_batch_add_head(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage, + grpc_mdelem elem_to_add) { GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; return grpc_metadata_batch_link_head(batch, storage); @@ -169,10 +170,10 @@ static void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { assert_valid_list(list); } -grpc_error* grpc_metadata_batch_link_head(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { +grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage) { assert_valid_callouts(batch); - grpc_error* err = maybe_link_callout(batch, storage); + grpc_error_handle err = maybe_link_callout(batch, storage); if (err != GRPC_ERROR_NONE) { assert_valid_callouts(batch); return err; @@ -185,12 +186,12 @@ grpc_error* grpc_metadata_batch_link_head(grpc_metadata_batch* batch, // TODO(arjunroy): Need to revisit this and see what guarantees exist between // C-core and the internal-metadata subsystem. E.g. can we ensure a particular // metadata is never added twice, even in the presence of user supplied data? -grpc_error* grpc_metadata_batch_link_head( +grpc_error_handle grpc_metadata_batch_link_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx); assert_valid_callouts(batch); - grpc_error* err = link_callout(batch, storage, idx); + grpc_error_handle err = link_callout(batch, storage, idx); if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) { assert_valid_callouts(batch); return err; @@ -200,9 +201,9 @@ grpc_error* grpc_metadata_batch_link_head( return GRPC_ERROR_NONE; } -grpc_error* grpc_metadata_batch_add_tail(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { +grpc_error_handle grpc_metadata_batch_add_tail(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage, + grpc_mdelem elem_to_add) { GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); storage->md = elem_to_add; return grpc_metadata_batch_link_tail(batch, storage); @@ -224,10 +225,10 @@ static void link_tail(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { assert_valid_list(list); } -grpc_error* grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { +grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage) { assert_valid_callouts(batch); - grpc_error* err = maybe_link_callout(batch, storage); + grpc_error_handle err = maybe_link_callout(batch, storage); if (err != GRPC_ERROR_NONE) { assert_valid_callouts(batch); return err; @@ -237,12 +238,12 @@ grpc_error* grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, return GRPC_ERROR_NONE; } -grpc_error* grpc_metadata_batch_link_tail( +grpc_error_handle grpc_metadata_batch_link_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx); assert_valid_callouts(batch); - grpc_error* err = link_callout(batch, storage, idx); + grpc_error_handle err = link_callout(batch, storage, idx); if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) { assert_valid_callouts(batch); return err; @@ -323,11 +324,11 @@ absl::optional grpc_metadata_batch_get_value( return *concatenated_value; } -grpc_error* grpc_metadata_batch_substitute(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem new_mdelem) { +grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage, + grpc_mdelem new_mdelem) { assert_valid_callouts(batch); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_mdelem old_mdelem = storage->md; if (!grpc_slice_eq(GRPC_MDKEY(new_mdelem), GRPC_MDKEY(old_mdelem))) { maybe_unlink_callout(batch, storage); @@ -364,7 +365,7 @@ size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) { return size; } -static void add_error(grpc_error** composite, grpc_error* error, +static void add_error(grpc_error_handle* composite, grpc_error_handle error, const char* composite_error_string) { if (error == GRPC_ERROR_NONE) return; if (*composite == GRPC_ERROR_NONE) { @@ -373,12 +374,11 @@ static void add_error(grpc_error** composite, grpc_error* error, *composite = grpc_error_add_child(*composite, error); } -grpc_error* grpc_metadata_batch_filter(grpc_metadata_batch* batch, - grpc_metadata_batch_filter_func func, - void* user_data, - const char* composite_error_string) { +grpc_error_handle grpc_metadata_batch_filter( + grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func, + void* user_data, const char* composite_error_string) { grpc_linked_mdelem* l = batch->list.head; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; while (l) { grpc_linked_mdelem* next = l->next; grpc_filtered_mdelem new_mdelem = func(user_data, l->md); @@ -402,7 +402,7 @@ void grpc_metadata_batch_copy(grpc_metadata_batch* src, for (grpc_linked_mdelem* elem = src->list.head; elem != nullptr; elem = elem->next) { // Error unused in non-debug builds. - grpc_error* GRPC_UNUSED error = grpc_metadata_batch_add_tail( + grpc_error_handle GRPC_UNUSED error = grpc_metadata_batch_add_tail( dst, &storage[i++], GRPC_MDELEM_REF(elem->md)); // The only way that grpc_metadata_batch_add_tail() can fail is if // there's a duplicate entry for a callout. However, that can't be diff --git a/src/core/lib/transport/metadata_batch.h b/src/core/lib/transport/metadata_batch.h index d80f87936cf..b72859fcf26 100644 --- a/src/core/lib/transport/metadata_batch.h +++ b/src/core/lib/transport/metadata_batch.h @@ -74,9 +74,9 @@ void grpc_metadata_batch_remove(grpc_metadata_batch* batch, grpc_metadata_batch_callouts_index idx); /** Substitute a new mdelem for an old value */ -grpc_error* grpc_metadata_batch_substitute(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage, - grpc_mdelem new_mdelem); +grpc_error_handle grpc_metadata_batch_substitute(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage, + grpc_mdelem new_mdelem); void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, const grpc_slice& value); @@ -97,10 +97,10 @@ absl::optional grpc_metadata_batch_get_value( \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ -grpc_error* grpc_metadata_batch_link_head(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) +grpc_error_handle grpc_metadata_batch_link_head(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; -grpc_error* grpc_metadata_batch_link_head( +grpc_error_handle grpc_metadata_batch_link_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT; @@ -109,10 +109,10 @@ grpc_error* grpc_metadata_batch_link_head( \a storage is owned by the caller and must survive for the lifetime of batch. This usually means it should be around for the lifetime of the call. */ -grpc_error* grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) +grpc_error_handle grpc_metadata_batch_link_tail(grpc_metadata_batch* batch, + grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; -grpc_error* grpc_metadata_batch_link_tail( +grpc_error_handle grpc_metadata_batch_link_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) GRPC_MUST_USE_RESULT; @@ -122,19 +122,19 @@ grpc_error* grpc_metadata_batch_link_tail( lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ -grpc_error* grpc_metadata_batch_add_head( +grpc_error_handle grpc_metadata_batch_add_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; // TODO(arjunroy, roth): Remove redundant methods. // add/link_head/tail are almost identical. -inline grpc_error* GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head( +inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { return grpc_metadata_batch_link_head(batch, storage, idx); } -inline grpc_error* GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head( +inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) { GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); @@ -148,17 +148,17 @@ inline grpc_error* GRPC_MUST_USE_RESULT grpc_metadata_batch_add_head( lifetime of batch. This usually means it should be around for the lifetime of the call. Takes ownership of \a elem_to_add */ -grpc_error* grpc_metadata_batch_add_tail( +grpc_error_handle grpc_metadata_batch_add_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; -inline grpc_error* GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail( +inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { return grpc_metadata_batch_link_tail(batch, storage, idx); } -inline grpc_error* GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail( +inline grpc_error_handle GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail( grpc_metadata_batch* batch, grpc_linked_mdelem* storage, grpc_mdelem elem_to_add, grpc_metadata_batch_callouts_index idx) { GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); @@ -166,10 +166,11 @@ inline grpc_error* GRPC_MUST_USE_RESULT grpc_metadata_batch_add_tail( return grpc_metadata_batch_add_tail(batch, storage, idx); } -grpc_error* grpc_attach_md_to_error(grpc_error* src, grpc_mdelem md); +grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src, + grpc_mdelem md); struct grpc_filtered_mdelem { - grpc_error* error; + grpc_error_handle error; grpc_mdelem md; }; #define GRPC_FILTERED_ERROR(error) \ @@ -181,7 +182,7 @@ struct grpc_filtered_mdelem { typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)( void* user_data, grpc_mdelem elem); -grpc_error* grpc_metadata_batch_filter( +grpc_error_handle grpc_metadata_batch_filter( grpc_metadata_batch* batch, grpc_metadata_batch_filter_func func, void* user_data, const char* composite_error_string) GRPC_MUST_USE_RESULT; diff --git a/src/core/lib/transport/transport.cc b/src/core/lib/transport/transport.cc index dccab66dc04..36060a6bd90 100644 --- a/src/core/lib/transport/transport.cc +++ b/src/core/lib/transport/transport.cc @@ -177,7 +177,7 @@ grpc_endpoint* grpc_transport_get_endpoint(grpc_transport* transport) { // though it lives in lib, it handles transport stream ops sure // it's grpc_transport_stream_op_batch_finish_with_failure void grpc_transport_stream_op_batch_finish_with_failure( - grpc_transport_stream_op_batch* batch, grpc_error* error, + grpc_transport_stream_op_batch* batch, grpc_error_handle error, grpc_core::CallCombiner* call_combiner) { if (batch->send_message) { batch->payload->send_message.send_message.reset(); @@ -219,7 +219,7 @@ struct made_transport_op { } }; -static void destroy_made_transport_op(void* arg, grpc_error* error) { +static void destroy_made_transport_op(void* arg, grpc_error_handle error) { made_transport_op* op = static_cast(arg); grpc_core::ExecCtx::Run(DEBUG_LOCATION, op->inner_on_complete, GRPC_ERROR_REF(error)); @@ -241,7 +241,8 @@ struct made_transport_stream_op { grpc_transport_stream_op_batch op; grpc_transport_stream_op_batch_payload payload; }; -static void destroy_made_transport_stream_op(void* arg, grpc_error* error) { +static void destroy_made_transport_stream_op(void* arg, + grpc_error_handle error) { made_transport_stream_op* op = static_cast(arg); grpc_closure* c = op->inner_on_complete; gpr_free(op); diff --git a/src/core/lib/transport/transport.h b/src/core/lib/transport/transport.h index 407604858d6..7372b3896eb 100644 --- a/src/core/lib/transport/transport.h +++ b/src/core/lib/transport/transport.h @@ -319,7 +319,7 @@ struct grpc_transport_stream_op_batch_payload { struct { // Error contract: the transport that gets this op must cause cancel_error // to be unref'ed after processing it - grpc_error* cancel_error = GRPC_ERROR_NONE; + grpc_error_handle cancel_error = GRPC_ERROR_NONE; } cancel_stream; /* Indexes correspond to grpc_context_index enum values */ @@ -339,11 +339,11 @@ typedef struct grpc_transport_op { /** should the transport be disconnected * Error contract: the transport that gets this op must cause * disconnect_with_error to be unref'ed after processing it */ - grpc_error* disconnect_with_error = nullptr; + grpc_error_handle disconnect_with_error = GRPC_ERROR_NONE; /** what should the goaway contain? * Error contract: the transport that gets this op must cause * goaway_error to be unref'ed after processing it */ - grpc_error* goaway_error = nullptr; + grpc_error_handle goaway_error = GRPC_ERROR_NONE; /** set the callback for accepting new streams; this is a permanent callback, unlike the other one-shot closures. If true, the callback is set to set_accept_stream_fn, with its @@ -411,7 +411,7 @@ void grpc_transport_destroy_stream(grpc_transport* transport, grpc_closure* then_schedule_closure); void grpc_transport_stream_op_batch_finish_with_failure( - grpc_transport_stream_op_batch* batch, grpc_error* error, + grpc_transport_stream_op_batch* batch, grpc_error_handle error, grpc_core::CallCombiner* call_combiner); std::string grpc_transport_stream_op_batch_string( diff --git a/src/core/lib/transport/transport_op_string.cc b/src/core/lib/transport/transport_op_string.cc index 722a64ecb8d..49dec384ee6 100644 --- a/src/core/lib/transport/transport_op_string.cc +++ b/src/core/lib/transport/transport_op_string.cc @@ -109,7 +109,7 @@ std::string grpc_transport_stream_op_batch_string( if (op->cancel_stream) { out.push_back(absl::StrCat( " CANCEL:", - grpc_error_string(op->payload->cancel_stream.cancel_error))); + grpc_error_std_string(op->payload->cancel_stream.cancel_error))); } return absl::StrJoin(out, ""); @@ -131,13 +131,13 @@ std::string grpc_transport_op_string(grpc_transport_op* op) { } if (op->disconnect_with_error != GRPC_ERROR_NONE) { - out.push_back(absl::StrCat(" DISCONNECT:", - grpc_error_string(op->disconnect_with_error))); + out.push_back(absl::StrCat( + " DISCONNECT:", grpc_error_std_string(op->disconnect_with_error))); } if (op->goaway_error) { - out.push_back( - absl::StrCat(" SEND_GOAWAY:%s", grpc_error_string(op->goaway_error))); + out.push_back(absl::StrCat(" SEND_GOAWAY:%s", + grpc_error_std_string(op->goaway_error))); } if (op->set_accept_stream) { diff --git a/src/core/plugin_registry/grpc_plugin_registry.cc b/src/core/plugin_registry/grpc_plugin_registry.cc index 1b2a210513e..d3def27e17a 100644 --- a/src/core/plugin_registry/grpc_plugin_registry.cc +++ b/src/core/plugin_registry/grpc_plugin_registry.cc @@ -60,6 +60,10 @@ void grpc_client_authority_filter_init(void); void grpc_client_authority_filter_shutdown(void); void grpc_workaround_cronet_compression_filter_init(void); void grpc_workaround_cronet_compression_filter_shutdown(void); +namespace grpc_core { +void FaultInjectionFilterInit(void); +void FaultInjectionFilterShutdown(void); +} // namespace grpc_core #ifndef GRPC_NO_XDS namespace grpc_core { @@ -123,6 +127,8 @@ void grpc_register_built_in_plugins(void) { grpc_max_age_filter_shutdown); grpc_register_plugin(grpc_message_size_filter_init, grpc_message_size_filter_shutdown); + grpc_register_plugin(grpc_core::FaultInjectionFilterInit, + grpc_core::FaultInjectionFilterShutdown); grpc_register_plugin(grpc_service_config_channel_arg_filter_init, grpc_service_config_channel_arg_filter_shutdown); grpc_register_plugin(grpc_client_authority_filter_init, diff --git a/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc b/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc index fd9bf9c14d5..5e7452936a1 100644 --- a/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc +++ b/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc @@ -54,6 +54,10 @@ void grpc_max_age_filter_init(void); void grpc_max_age_filter_shutdown(void); void grpc_message_size_filter_init(void); void grpc_message_size_filter_shutdown(void); +namespace grpc_core { +void FaultInjectionFilterInit(void); +void FaultInjectionFilterShutdown(void); +} // namespace grpc_core void grpc_service_config_channel_arg_filter_init(void); void grpc_service_config_channel_arg_filter_shutdown(void); void grpc_client_authority_filter_init(void); @@ -96,6 +100,8 @@ void grpc_register_built_in_plugins(void) { grpc_max_age_filter_shutdown); grpc_register_plugin(grpc_message_size_filter_init, grpc_message_size_filter_shutdown); + grpc_register_plugin(grpc_core::FaultInjectionFilterInit, + grpc_core::FaultInjectionFilterShutdown); grpc_register_plugin(grpc_service_config_channel_arg_filter_init, grpc_service_config_channel_arg_filter_shutdown); grpc_register_plugin(grpc_client_authority_filter_init, diff --git a/src/core/tsi/alts/crypt/gsec.h b/src/core/tsi/alts/crypt/gsec.h index 4d65caa9447..c330ca69eb5 100644 --- a/src/core/tsi/alts/crypt/gsec.h +++ b/src/core/tsi/alts/crypt/gsec.h @@ -21,16 +21,20 @@ #include +#include + #include #include #include #include +#ifndef GRPC_EVENT_ENGINE_POSIX struct iovec { void* iov_base; size_t iov_len; }; +#endif // GRPC_EVENT_ENGINE_POSIX /** * A gsec interface for AEAD encryption schemes. The API is thread-compatible. diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc index 041a46f4cf4..ed70d812512 100644 --- a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +++ b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc @@ -117,10 +117,7 @@ static void handshaker_client_send_buffer_destroy( static bool is_handshake_finished_properly(grpc_gcp_HandshakerResp* resp) { GPR_ASSERT(resp != nullptr); - if (grpc_gcp_HandshakerResp_result(resp)) { - return true; - } - return false; + return grpc_gcp_HandshakerResp_result(resp) != nullptr; } static void alts_grpc_handshaker_client_unref( @@ -442,7 +439,7 @@ static tsi_result make_grpc_call(alts_handshaker_client* c, bool is_start) { } } -static void on_status_received(void* arg, grpc_error* error) { +static void on_status_received(void* arg, grpc_error_handle error) { alts_grpc_handshaker_client* client = static_cast(arg); if (client->handshake_status_code != GRPC_STATUS_OK) { @@ -454,7 +451,7 @@ static void on_status_received(void* arg, grpc_error* error) { "alts_grpc_handshaker_client:%p on_status_received " "status:%d details:|%s| error:|%s|", client, client->handshake_status_code, status_details, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); gpr_free(status_details); } maybe_complete_tsi_next(client, true /* receive_status_finished */, @@ -645,7 +642,7 @@ static void handshaker_client_shutdown(alts_handshaker_client* c) { } } -static void handshaker_call_unref(void* arg, grpc_error* /* error */) { +static void handshaker_call_unref(void* arg, grpc_error_handle /* error */) { grpc_call* call = static_cast(arg); grpc_call_unref(call); } @@ -841,7 +838,8 @@ void alts_handshaker_client_ref_for_testing(alts_handshaker_client* c) { } void alts_handshaker_client_on_status_received_for_testing( - alts_handshaker_client* c, grpc_status_code status, grpc_error* error) { + alts_handshaker_client* c, grpc_status_code status, + grpc_error_handle error) { // We first make sure that the handshake queue has been initialized // here because there are tests that use this API that mock out // other parts of the alts_handshaker_client in such a way that the diff --git a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc index 60df0ce71f4..9cca8ab4726 100644 --- a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +++ b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc @@ -372,7 +372,8 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp, } /* gRPC provided callback used when gRPC thread model is applied. */ -static void on_handshaker_service_resp_recv(void* arg, grpc_error* error) { +static void on_handshaker_service_resp_recv(void* arg, + grpc_error_handle error) { alts_handshaker_client* client = static_cast(arg); if (client == nullptr) { gpr_log(GPR_ERROR, "ALTS handshaker client is nullptr"); @@ -382,7 +383,7 @@ static void on_handshaker_service_resp_recv(void* arg, grpc_error* error) { if (error != GRPC_ERROR_NONE) { gpr_log(GPR_ERROR, "ALTS handshaker on_handshaker_service_resp_recv error: %s", - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); success = false; } alts_handshaker_client_handle_response(client, success); @@ -390,8 +391,8 @@ static void on_handshaker_service_resp_recv(void* arg, grpc_error* error) { /* gRPC provided callback used when dedicatd CQ and thread are used. * It serves to safely bring the control back to application. */ -static void on_handshaker_service_resp_recv_dedicated(void* arg, - grpc_error* /*error*/) { +static void on_handshaker_service_resp_recv_dedicated( + void* arg, grpc_error_handle /*error*/) { alts_shared_resource_dedicated* resource = grpc_alts_get_shared_resource_dedicated(); grpc_cq_end_op( @@ -480,8 +481,8 @@ struct alts_tsi_handshaker_continue_handshaker_next_args { grpc_closure closure; }; -static void alts_tsi_handshaker_create_channel(void* arg, - grpc_error* /* unused_error */) { +static void alts_tsi_handshaker_create_channel( + void* arg, grpc_error_handle /* unused_error */) { alts_tsi_handshaker_continue_handshaker_next_args* next_args = static_cast(arg); alts_tsi_handshaker* handshaker = next_args->handshaker; diff --git a/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h b/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h index cb99fdcce0d..d5ab14dc034 100644 --- a/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h +++ b/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h @@ -78,7 +78,8 @@ grpc_closure* alts_handshaker_client_get_closure_for_testing( alts_handshaker_client* client); void alts_handshaker_client_on_status_received_for_testing( - alts_handshaker_client* client, grpc_status_code status, grpc_error* error); + alts_handshaker_client* client, grpc_status_code status, + grpc_error_handle error); void alts_handshaker_client_ref_for_testing(alts_handshaker_client* c); diff --git a/src/core/tsi/alts/handshaker/transport_security_common_api.cc b/src/core/tsi/alts/handshaker/transport_security_common_api.cc index a0462b2d76c..402bf1313e0 100644 --- a/src/core/tsi/alts/handshaker/transport_security_common_api.cc +++ b/src/core/tsi/alts/handshaker/transport_security_common_api.cc @@ -214,9 +214,7 @@ bool grpc_gcp_rpc_protocol_versions_check( ? &local_versions->min_rpc_version : &peer_versions->min_rpc_version; bool result = grpc_core::internal::grpc_gcp_rpc_protocol_version_compare( - max_common_version, min_common_version) >= 0 - ? true - : false; + max_common_version, min_common_version) >= 0; if (result && highest_common_version != nullptr) { memcpy(highest_common_version, max_common_version, sizeof(grpc_gcp_rpc_protocol_versions_version)); diff --git a/src/core/tsi/fake_transport_security.cc b/src/core/tsi/fake_transport_security.cc index 1ea43590c3f..5e63f11a2a4 100644 --- a/src/core/tsi/fake_transport_security.cc +++ b/src/core/tsi/fake_transport_security.cc @@ -474,12 +474,21 @@ static void fake_zero_copy_grpc_protector_destroy( gpr_free(impl); } +static tsi_result fake_zero_copy_grpc_protector_max_frame_size( + tsi_zero_copy_grpc_protector* self, size_t* max_frame_size) { + if (self == nullptr || max_frame_size == nullptr) return TSI_INVALID_ARGUMENT; + tsi_fake_zero_copy_grpc_protector* impl = + reinterpret_cast(self); + *max_frame_size = impl->max_frame_size; + return TSI_OK; +} + static const tsi_zero_copy_grpc_protector_vtable zero_copy_grpc_protector_vtable = { fake_zero_copy_grpc_protector_protect, fake_zero_copy_grpc_protector_unprotect, fake_zero_copy_grpc_protector_destroy, - nullptr /* fake_zero_copy_grpc_protector_max_frame_size */ + fake_zero_copy_grpc_protector_max_frame_size, }; /* --- tsi_handshaker_result methods implementation. ---*/ diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc index d978441c9e6..4241b6f6f69 100644 --- a/src/core/tsi/ssl_transport_security.cc +++ b/src/core/tsi/ssl_transport_security.cc @@ -357,13 +357,17 @@ static tsi_result add_subject_alt_names_properties_to_peer( subject_alt_name->type == GEN_URI) { unsigned char* name = nullptr; int name_size; + std::string property_name; if (subject_alt_name->type == GEN_DNS) { name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName); + property_name = TSI_X509_DNS_PEER_PROPERTY; } else if (subject_alt_name->type == GEN_EMAIL) { name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.rfc822Name); + property_name = TSI_X509_EMAIL_PEER_PROPERTY; } else { name_size = ASN1_STRING_to_UTF8( &name, subject_alt_name->d.uniformResourceIdentifier); + property_name = TSI_X509_URI_PEER_PROPERTY; } if (name_size < 0) { gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string."); @@ -378,12 +382,10 @@ static tsi_result add_subject_alt_names_properties_to_peer( OPENSSL_free(name); break; } - if (subject_alt_name->type == GEN_URI) { - result = tsi_construct_string_peer_property( - TSI_X509_URI_PEER_PROPERTY, reinterpret_cast(name), - static_cast(name_size), - &peer->properties[(*current_insert_index)++]); - } + result = tsi_construct_string_peer_property( + property_name.c_str(), reinterpret_cast(name), + static_cast(name_size), + &peer->properties[(*current_insert_index)++]); OPENSSL_free(name); } else if (subject_alt_name->type == GEN_IPADD) { char ntop_buf[INET6_ADDRSTRLEN]; @@ -409,6 +411,10 @@ static tsi_result add_subject_alt_names_properties_to_peer( result = tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name, &peer->properties[(*current_insert_index)++]); + if (result != TSI_OK) break; + result = tsi_construct_string_peer_property_from_cstring( + TSI_X509_IP_PEER_PROPERTY, name, + &peer->properties[(*current_insert_index)++]); } else { result = tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, "other types of SAN", @@ -438,7 +444,14 @@ static tsi_result peer_from_x509(X509* cert, int include_certificate_type, for (int i = 0; i < subject_alt_name_count; i++) { GENERAL_NAME* subject_alt_name = sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i)); - if (subject_alt_name->type == GEN_URI) { + // TODO(zhenlian): Clean up tsi_peer to avoid duplicate entries. + // URI, DNS, email and ip address SAN fields are plumbed to tsi_peer, in + // addition to all SAN fields (results in duplicate values). This code + // snippet updates property_count accordingly. + if (subject_alt_name->type == GEN_URI || + subject_alt_name->type == GEN_DNS || + subject_alt_name->type == GEN_EMAIL || + subject_alt_name->type == GEN_IPADD) { property_count += 1; } } @@ -1911,14 +1924,16 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options( #else ssl_context = SSL_CTX_new(TLSv1_2_method()); #endif - result = tsi_set_min_and_max_tls_versions( - ssl_context, options->min_tls_version, options->max_tls_version); - if (result != TSI_OK) return result; if (ssl_context == nullptr) { + log_ssl_error_stack(); gpr_log(GPR_ERROR, "Could not create ssl context."); return TSI_INVALID_ARGUMENT; } + result = tsi_set_min_and_max_tls_versions( + ssl_context, options->min_tls_version, options->max_tls_version); + if (result != TSI_OK) return result; + impl = static_cast( gpr_zalloc(sizeof(*impl))); tsi_ssl_handshaker_factory_init(&impl->base); @@ -2078,15 +2093,18 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options( #else impl->ssl_contexts[i] = SSL_CTX_new(TLSv1_2_method()); #endif - result = tsi_set_min_and_max_tls_versions(impl->ssl_contexts[i], - options->min_tls_version, - options->max_tls_version); - if (result != TSI_OK) return result; if (impl->ssl_contexts[i] == nullptr) { + log_ssl_error_stack(); gpr_log(GPR_ERROR, "Could not create ssl context."); result = TSI_OUT_OF_RESOURCES; break; } + + result = tsi_set_min_and_max_tls_versions(impl->ssl_contexts[i], + options->min_tls_version, + options->max_tls_version); + if (result != TSI_OK) return result; + result = populate_ssl_context(impl->ssl_contexts[i], &options->pem_key_cert_pairs[i], options->cipher_suites); diff --git a/src/core/tsi/ssl_transport_security.h b/src/core/tsi/ssl_transport_security.h index d19738dc8ee..c3d30a888c3 100644 --- a/src/core/tsi/ssl_transport_security.h +++ b/src/core/tsi/ssl_transport_security.h @@ -37,14 +37,13 @@ extern "C" { #define TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY \ "x509_subject_alternative_name" #define TSI_SSL_SESSION_REUSED_PEER_PROPERTY "ssl_session_reused" - #define TSI_X509_PEM_CERT_PROPERTY "x509_pem_cert" - #define TSI_X509_PEM_CERT_CHAIN_PROPERTY "x509_pem_cert_chain" - #define TSI_SSL_ALPN_SELECTED_PROTOCOL "ssl_alpn_selected_protocol" - +#define TSI_X509_DNS_PEER_PROPERTY "x509_dns" #define TSI_X509_URI_PEER_PROPERTY "x509_uri" +#define TSI_X509_EMAIL_PEER_PROPERTY "x509_email" +#define TSI_X509_IP_PEER_PROPERTY "x509_ip" /* --- tsi_ssl_root_certs_store object --- diff --git a/src/core/tsi/test_creds/multi-domain-openssl.cnf b/src/core/tsi/test_creds/multi-domain-openssl.cnf index 265950f56d6..33ecc9d9b84 100644 --- a/src/core/tsi/test_creds/multi-domain-openssl.cnf +++ b/src/core/tsi/test_creds/multi-domain-openssl.cnf @@ -28,3 +28,6 @@ URI.2 = https://bar.test.domain.com/test URI.3 = spiffe://foo.com/bar/baz email.1 = foo@test.domain.com email.2 = bar@test.domain.com +IP.1 = 192.168.7.1 +IP.2 = 13::17 +RID.1 = 1.2.3.4 diff --git a/src/core/tsi/test_creds/multi-domain.key b/src/core/tsi/test_creds/multi-domain.key index b5789e92f94..2b9cce0bdb9 100644 --- a/src/core/tsi/test_creds/multi-domain.key +++ b/src/core/tsi/test_creds/multi-domain.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCuGVBYD3P/D2eT -nhBhZ0izP+nuozNCEO/iQu/kyy6ZCzIEFvykt0aPzJVLcsCHCaWcNJVFPSqVDVRm -9S5ZHUyLlnSl53mKUltZI4tDDVMcEdr7KpfXeBc86lm/93DqFDgAYDkvebekRr/8 -B1OJhVJRGowXjAU9sYABzuUqjkra522BleIik3m+7DborGHS4Io5X/8D8VjlXjeB -Vht6QA8ij5JVfHvO6DsZr99EITPpha6i182O6S6lO2t1V+bdWP+EPjiOQJktrmvM -QYTFjmjYkRKLCZI1xxSfCK8t7ia5sLPFOF6uDH91ck8mXmuHs96nSOyB1i/LdBy9 -XdInSRGXAgMBAAECggEAWoqZqSJoPfah9DhY5n8TZP1RSKUhTDOIvc/3+LHeSwNy -gIP/4h3amYBZCELmc5QFx8Xk93xG//tNsLnD396H53RYt8s4/0GzdhkxHK76UPfM -PaE6FHnFBA4QnPAvjdzz/uYL92/CnLGauJSK0lM+qyU2RCyysRH1s3sI3Wfg8BRd -C9Xik+YzYirhCEGlYKju2D2As/tB2L0b/PRpM9FWeqd/YGCj8pUpceNrbvU8udc7 -4xQS6ssgMI2H1xGc50kJVDjoZix5OLiTaHDO4oRBZT+QdPTtfkam0/y2yZ9oX6UN -Byl+ybtUpxsmsvl+I7bb/fZsILrXE3GHXtcsCMi5iQKBgQDmKi1HfmQo6KeDSnjp -R+yIMc77QpZpLuzjPlKWGxY915KlL77GOUYR2cm0rPP9CPGN2Nj5IyuR32u6uHtI -WKewR7cn69prxZI3VSNFQmsatWKBoR7dwyJ4j93cN54naEuBLA1BJQ0uXgYJtgwT -x5KP97LcudpoDNVsh+FUopon8wKBgQDBpBMeDoc+7YVLnlx4FRJudzVfWWb4bPCL -2cusycOVAlN2E0VsrD2vbVWoinpVPIeOfGgD0RZZLtVQL5Ui8mZcANmuoRXtEqaS -sQ6VxkdC62uDXgrsi+i/0nsxvACmfde4sxALu3DZ7rjNlWUW7amJt34CsDBMlVeL -eDAmD0WczQKBgQCHzSLiKATYzkzn/izRF4rL4PeK8ILmlLVYbxEzV9ALtQHlTQJ2 -2pwpNCL644EiLwC2/NcoSEQQ0Y4yoV68FPL745SBjXtWU0AuPaGN395p59OzQGmB -1vyjvd7dbEN4ZOUH1gIMCdx5Gyjc2fjOQtaK808pRM9EzS2v14xv73CdWQKBgC/8 -qiQrs4Z7tCm+L+ouRqgLcLWVYTg1PxNZQOksAwT9U5OSSQUaVhsQPEcNMi3HV0yP -NfOkMCafvYsmj43ehlFMgKWPE/DxS0hVCmlBfs1tq/IdLxXZwi8vSQpVLdAUpY4H -CfXuWJQZXcDMwgWBlh8j0t11rjJ8W/qbKUt1Q2oNAoGBALdy/RpspFttVvthzFbg -FLHUAwUhEsK1VSi26AYy4L0ZHw/KLnbIGEzKCEFWqn6nfWOlb9Rw5C7QlGx/1UCC -Tnn9KnZoziK4JDQw6SEl/3hNQ5+FYI8y7QGsqAm1W9dobbgl0a1IfmbtBeEOZt+e -7oFnqaxVruVmNr56M9IMCwA1 +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDAg51YU8NkgC7w +Hx7Jf9Zj+wjHcLxedY6czsFjhl9wUlYRkQ+wdt3suH998TrbdVMc38tpI460pGk7 +gGBpMkbZgo1YNnwz/U1jAOR11EVGHN1QDy3H0BI2E5RYtl/vTWQLFo1khIaKK4eS +3ptrPd+1XB6L25E4ISOVgd3yn4b5eTMGRbEei+wrkZIyZAVgCIw8d6BHHwldWz3A +ljKRErMPzKtnyVL+ctp0Kx6ObppiBPPOWhNNTtMkmLgfeZQK3U7cPN5WI13Fso05 +FA3wVo/w6sXTtz4inIT14Y57E34V6sWZezrBbTtAI0yN3DqXSKTBgGjOQUbjqVxS +i/JzRbZpAgMBAAECggEAXJMt59qn3D1T1P5yFJ2X4A5Io3eP7bCEOt2l25EzddTy +NJJYRBh1Ea+LB2ooTn410G3B6DZEGpPxUr6iHhQiQ9hm1eOliG6ndxNnyU2hXlzl +A+m4rxxclYqGzL4ulenWUQqwRYUBGZJjKHpJrKFdYV4CBmk4hRBSh0OjElgqVO5g +nliMl3fC+GgUXtdMDGoPnC6MwD8q0RSJxbzpd8r+yREgX6KveEfPTfgSLAUieJrf +2qqEk0Prdrwzsu0iyDYCaWLOq0cUstnHCo3e5synV4VzAFnaqxMT7lCVuUHgFpHj +62rTwBCG/n3s+IVAp9CGBe37+SiJPRE8t5PDr65F3QKBgQDovkKLWzXxVJauTF/E +tFRA+HqNDzYC3yiN0MIBmcF7IntdwCHznMyqydkaSE6WYn+NKglbH3c4RD5Hmdxc +PUta8wgpmTg264568Svgna5jhwoqStrzh7qeBPXHmJvK4MkWALH4ukr3hIsWzsAh +881ebstQDke8uHzyNZBY/URebwKBgQDTwEP6hgcgDOaf9yzipeMhtsArIm7zXn+r +1RknpKUA8wM6fpEMpdUTgReu9tdJDgrcKac6imSZoNM6DBoOb/Hdj6FourHiTTvE +dXAOjAzkDz/c86HFuDNoz27usoMPu/3iJPwuLQSO0IlflccLuOirhnnY8yVxIuy2 ++9g+2iOkpwKBgE/Kin3EM2YdHdt7i4mgWRI9HaamhFnPr9OOsjRiRha0555odDtU +kkYrFScRiv+7nQcEVljLHNBJdSCO+yEUUnVHxJCeWstZTmuPqv9Cj7rHXRDKwO2k +prHt+WUISMDw9393lYw0MedRpW2YS/5X2xx413MGsklc5lkTS/12Nq45AoGAaVCf +vrL4Sj2AWqEhxtwAmlz9OLbYfdxLHVhQOYJOuqkiuu4GEEdOMXQsJk4IhwIf7p4c +2SXJoQr241DviKyum6Z6/c6U+Fu3VR+fiuym4Kqg9bCKjf7uOruojbllK+cw/0+r +yP+E287l9A9XPwJJXj30zi0oOxvGpb+eLqxpu9MCgYEAxIgVhzyfRvoAdNYk7FE7 +JDig38EGC4m9grh/9G0tMvWT/E+F1Hb5V9NDK/iWA25dD3hOASxza1Hqkt1dP5on +FMZrmP2T9Ov0wgfVuRIf8/c3YyiS1wJXb3wROVaJJDSvE5c2UszR5pfqvNE5C1YV +zpc3ITQSAX66LK6ImkHb9Jw= -----END PRIVATE KEY----- diff --git a/src/core/tsi/test_creds/multi-domain.pem b/src/core/tsi/test_creds/multi-domain.pem index d4ff936fde3..727b8ff4901 100644 --- a/src/core/tsi/test_creds/multi-domain.pem +++ b/src/core/tsi/test_creds/multi-domain.pem @@ -1,24 +1,24 @@ -----BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIUV2eOzlQQj1U+++TDdNyRHjRNamQwDQYJKoZIhvcNAQEL +MIIEGzCCAwOgAwIBAgIUVwCmP2zKfeoWdaMbn32PjFgpdRswDQYJKoZIhvcNAQEL BQAwSjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G -A1UECwwGR29vZ2xlMRAwDgYDVQQDDAd4cGlnb3JzMB4XDTIwMDYwNzIyNTk1MFoX -DTMwMDYwNTIyNTk1MFowSjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYD +A1UECwwGR29vZ2xlMRAwDgYDVQQDDAd4cGlnb3JzMB4XDTIxMDQwOTE5MzgxOVoX +DTMxMDQwNzE5MzgxOVowSjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYD VQQHDAJTRjEPMA0GA1UECwwGR29vZ2xlMRAwDgYDVQQDDAd4cGlnb3JzMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArhlQWA9z/w9nk54QYWdIsz/p7qMz -QhDv4kLv5MsumQsyBBb8pLdGj8yVS3LAhwmlnDSVRT0qlQ1UZvUuWR1Mi5Z0ped5 -ilJbWSOLQw1THBHa+yqX13gXPOpZv/dw6hQ4AGA5L3m3pEa//AdTiYVSURqMF4wF -PbGAAc7lKo5K2udtgZXiIpN5vuw26Kxh0uCKOV//A/FY5V43gVYbekAPIo+SVXx7 -zug7Ga/fRCEz6YWuotfNjukupTtrdVfm3Vj/hD44jkCZLa5rzEGExY5o2JESiwmS -NccUnwivLe4mubCzxThergx/dXJPJl5rh7Pep0jsgdYvy3QcvV3SJ0kRlwIDAQAB -o4HbMIHYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMIG9BgNVHREEgbUwgbKCE2Zv +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwIOdWFPDZIAu8B8eyX/WY/sIx3C8 +XnWOnM7BY4ZfcFJWEZEPsHbd7Lh/ffE623VTHN/LaSOOtKRpO4BgaTJG2YKNWDZ8 +M/1NYwDkddRFRhzdUA8tx9ASNhOUWLZf701kCxaNZISGiiuHkt6baz3ftVwei9uR +OCEjlYHd8p+G+XkzBkWxHovsK5GSMmQFYAiMPHegRx8JXVs9wJYykRKzD8yrZ8lS +/nLadCsejm6aYgTzzloTTU7TJJi4H3mUCt1O3DzeViNdxbKNORQN8FaP8OrF07c+ +IpyE9eGOexN+FerFmXs6wW07QCNMjdw6l0ikwYBozkFG46lcUovyc0W2aQIDAQAB +o4H4MIH1MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMIHaBgNVHREEgdIwgc+CE2Zv by50ZXN0LmRvbWFpbi5jb22CE2Jhci50ZXN0LmRvbWFpbi5jb22GIGh0dHBzOi8v Zm9vLnRlc3QuZG9tYWluLmNvbS90ZXN0hiBodHRwczovL2Jhci50ZXN0LmRvbWFp bi5jb20vdGVzdIYYc3BpZmZlOi8vZm9vLmNvbS9iYXIvYmF6gRNmb29AdGVzdC5k -b21haW4uY29tgRNiYXJAdGVzdC5kb21haW4uY29tMA0GCSqGSIb3DQEBCwUAA4IB -AQBlLNl/uXN01VARQFd5CNFMhwez879uB5N3s/pGBjzE8Z+NA9YjsBFkBSQlebFM -5UP304rsvG2opHwcSkblG9a3TbpQVNaYjcHgudip3FqLTJ3NhYtx1A3uCBp4ABeP -+AVlCcsNVysGwGvMzXlN++Y++U0A9BbfrP85VBslLaKn4rYpfB5pAdzu277ICdEy -nyFZ+jo2OS1lbv7kE7IW6slCXbCFaxPIKvjPbpGFngsLt44sZ9VvSJCeKhDglMfn -HKkhd4/UMnRn+8tZZ6eH/C5tpeKAChMUF+bkuwk3dBwnHq484KbBAKd2cwzZhTB7 -8unku1S1GumvoEYAgbG1P4gC +b21haW4uY29tgRNiYXJAdGVzdC5kb21haW4uY29thwTAqAcBhxAAEwAAAAAAAAAA +AAAAAAAXiAMqAwQwDQYJKoZIhvcNAQELBQADggEBAIHzi/MWANQDYqpNDGVA6HGg +vYPnwxjLXL/8apVf1ZMHzS/R6Eudu8ugppnnEL7Cjsd4oA0r/sJLjBvhaZtf0r4S +GguWdmai2RR1ghwkCLPF/HlCqiBKwUfWrjTxq8GOwwodhW7lk4hLPzhFRzh/I93g +uN5/ugPKcloWQ7X/0okMdkdPmk8uLpMckXNKj13Lupl/0BgDggghVXRTA2t0ujhx +TvRWfYi5H1eJtNcj824PaIDifPiSOpzeXZi+na2XzzVmCz5n/e2H4nlTMVcN6YGG +M3U3uJqjjjpKkCrrdNAJJpqqJpln4P6fVvO2ND1QmyE5YIKV3tZ8p38AJOheUcw= -----END CERTIFICATE----- diff --git a/src/cpp/Protobuf-C++.podspec b/src/cpp/Protobuf-C++.podspec index addc526bea2..7b239a6b2b0 100644 --- a/src/cpp/Protobuf-C++.podspec +++ b/src/cpp/Protobuf-C++.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Protobuf-C++' - s.version = '3.15.2' + s.version = '3.15.8' s.summary = 'Protocol Buffers v3 runtime library for C++.' s.homepage = 'https://github.com/google/protobuf' s.license = '3-Clause BSD License' diff --git a/src/cpp/client/channel_cc.cc b/src/cpp/client/channel_cc.cc index f911ae22f7a..a9f208394ec 100644 --- a/src/cpp/client/channel_cc.cc +++ b/src/cpp/client/channel_cc.cc @@ -57,12 +57,13 @@ Channel::Channel(const std::string& host, grpc_channel* channel, Channel::~Channel() { grpc_channel_destroy(c_channel_); - if (callback_cq_ != nullptr) { + CompletionQueue* callback_cq = callback_cq_.load(std::memory_order_relaxed); + if (callback_cq != nullptr) { if (grpc_iomgr_run_in_background()) { // gRPC-core provides the backing needed for the preferred CQ type - callback_cq_->Shutdown(); + callback_cq->Shutdown(); } else { - CompletionQueue::ReleaseCallbackAlternativeCQ(callback_cq_); + CompletionQueue::ReleaseCallbackAlternativeCQ(callback_cq); } } } @@ -146,9 +147,9 @@ void ChannelResetConnectionBackoff(Channel* channel) { // ClientRpcInfo should be set before call because set_call also checks // whether the call has been cancelled, and if the call was cancelled, we // should notify the interceptors too. - auto* info = - context->set_client_rpc_info(method.name(), method.method_type(), this, - interceptor_creators_, interceptor_pos); + auto* info = context->set_client_rpc_info( + method.name(), method.suffix_for_stats(), method.method_type(), this, + interceptor_creators_, interceptor_pos); context->set_call(c_call, shared_from_this()); return ::grpc::internal::Call(c_call, this, cq, info); @@ -243,25 +244,33 @@ class ShutdownCallback : public grpc_experimental_completion_queue_functor { ::grpc::CompletionQueue* Channel::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-channel CQ registered + CompletionQueue* callback_cq = callback_cq_.load(std::memory_order_acquire); + if (callback_cq != nullptr) { + return callback_cq; + } + // The callback_cq_ wasn't already set, so grab a lock and set it up exactly + // once for this channel. grpc::internal::MutexLock l(&mu_); - if (callback_cq_ == nullptr) { + callback_cq = callback_cq_.load(std::memory_order_relaxed); + if (callback_cq == nullptr) { if (grpc_iomgr_run_in_background()) { // gRPC-core provides the backing needed for the preferred CQ type auto* shutdown_callback = new ShutdownCallback; - callback_cq_ = + callback_cq = new ::grpc::CompletionQueue(grpc_completion_queue_attributes{ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback}); // Transfer ownership of the new cq to its own shutdown callback - shutdown_callback->TakeCQ(callback_cq_); + shutdown_callback->TakeCQ(callback_cq); } else { // Otherwise we need to use the alternative CQ variant - callback_cq_ = CompletionQueue::CallbackAlternativeCQ(); + callback_cq = CompletionQueue::CallbackAlternativeCQ(); } + callback_cq_.store(callback_cq, std::memory_order_release); } - return callback_cq_; + return callback_cq; } } // namespace grpc diff --git a/src/cpp/client/client_callback.cc b/src/cpp/client/client_callback.cc index a05761ad063..a10e1b571cb 100644 --- a/src/cpp/client/client_callback.cc +++ b/src/cpp/client/client_callback.cc @@ -36,7 +36,7 @@ void ClientReactor::InternalScheduleOnDone(grpc::Status s) { : reactor(reactor_arg), status(std::move(s)) { GRPC_CLOSURE_INIT( &closure, - [](void* void_arg, grpc_error*) { + [](void* void_arg, grpc_error_handle) { ClosureWithArg* arg = static_cast(void_arg); arg->reactor->OnDone(arg->status); delete arg; diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc index 1817767ef56..386b731c0f0 100644 --- a/src/cpp/client/client_context.cc +++ b/src/cpp/client/client_context.cc @@ -62,6 +62,7 @@ ClientContext::ClientContext() propagate_from_call_(nullptr), compression_algorithm_(GRPC_COMPRESS_NONE), initial_metadata_corked_(false) { + g_gli_initializer.summon(); g_client_callbacks->DefaultConstructor(this); } diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc index fd9cd4ca8b2..be99d54272f 100644 --- a/src/cpp/client/secure_credentials.cc +++ b/src/cpp/client/secure_credentials.cc @@ -157,7 +157,7 @@ grpc::Status StsCredentialsOptionsFromJson(const std::string& json_string, "options cannot be nullptr."); } ClearStsCredentialsOptions(options); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json json = grpc_core::Json::Parse(json_string.c_str(), &error); if (error != GRPC_ERROR_NONE || json.type() != grpc_core::Json::Type::OBJECT) { @@ -215,7 +215,7 @@ grpc::Status StsCredentialsOptionsFromEnv(StsCredentialsOptions* options) { ClearStsCredentialsOptions(options); grpc_slice json_string = grpc_empty_slice(); char* sts_creds_path = gpr_getenv("STS_CREDENTIALS"); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc::Status status; auto cleanup = [&json_string, &sts_creds_path, &error, &status]() { grpc_slice_unref_internal(json_string); @@ -232,7 +232,7 @@ grpc::Status StsCredentialsOptionsFromEnv(StsCredentialsOptions* options) { error = grpc_load_file(sts_creds_path, 1, &json_string); if (error != GRPC_ERROR_NONE) { status = - grpc::Status(grpc::StatusCode::NOT_FOUND, grpc_error_string(error)); + grpc::Status(grpc::StatusCode::NOT_FOUND, grpc_error_std_string(error)); return cleanup(); } status = StsCredentialsOptionsFromJson( @@ -406,7 +406,7 @@ std::shared_ptr MetadataCredentialsFromPlugin( } namespace { -void DeleteWrapper(void* wrapper, grpc_error* /*ignored*/) { +void DeleteWrapper(void* wrapper, grpc_error_handle /*ignored*/) { MetadataCredentialsPluginWrapper* w = static_cast(wrapper); delete w; diff --git a/src/cpp/common/alarm.cc b/src/cpp/common/alarm.cc index ac1b747b493..10d633c0dd4 100644 --- a/src/cpp/common/alarm.cc +++ b/src/cpp/common/alarm.cc @@ -56,7 +56,7 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { GPR_ASSERT(grpc_cq_begin_op(cq_, this)); GRPC_CLOSURE_INIT( &on_alarm_, - [](void* arg, grpc_error* error) { + [](void* arg, grpc_error_handle error) { // queue the op on the completion queue AlarmImpl* alarm = static_cast(arg); alarm->Ref(); @@ -82,10 +82,10 @@ class AlarmImpl : public ::grpc::internal::CompletionQueueTag { Ref(); GRPC_CLOSURE_INIT( &on_alarm_, - [](void* arg, grpc_error* error) { + [](void* arg, grpc_error_handle error) { grpc_core::Executor::Run( GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error* error) { + [](void* arg, grpc_error_handle error) { AlarmImpl* alarm = static_cast(arg); alarm->callback_(error == GRPC_ERROR_NONE); alarm->Unref(); diff --git a/src/cpp/common/auth_property_iterator.cc b/src/cpp/common/auth_property_iterator.cc index fbb18e9915c..0f380b09507 100644 --- a/src/cpp/common/auth_property_iterator.cc +++ b/src/cpp/common/auth_property_iterator.cc @@ -61,7 +61,7 @@ bool AuthPropertyIterator::operator!=(const AuthPropertyIterator& rhs) const { return !operator==(rhs); } -const AuthProperty AuthPropertyIterator::operator*() { +AuthProperty AuthPropertyIterator::operator*() { return std::pair( property_->name, grpc::string_ref(property_->value, property_->value_length)); diff --git a/src/cpp/common/channel_filter.h b/src/cpp/common/channel_filter.h index 5ce720b3075..d58805632af 100644 --- a/src/cpp/common/channel_filter.h +++ b/src/cpp/common/channel_filter.h @@ -60,7 +60,7 @@ class MetadataBatch { const grpc_mdelem> { public: const grpc_mdelem& operator*() const { return elem_->md; } - const grpc_mdelem operator->() const { return elem_->md; } + grpc_mdelem operator->() const { return elem_->md; } const_iterator& operator++() { elem_ = elem_->next; @@ -113,7 +113,7 @@ class TransportOp { grpc_transport_op* op() const { return op_; } // TODO(roth): Add a C++ wrapper for grpc_error? - grpc_error* disconnect_with_error() const { + grpc_error_handle disconnect_with_error() const { return op_->disconnect_with_error; } bool send_goaway() const { return op_->goaway_error != GRPC_ERROR_NONE; } @@ -236,8 +236,8 @@ class ChannelData { // TODO(roth): Come up with a more C++-like API for the channel element. /// Initializes the channel data. - virtual grpc_error* Init(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { + virtual grpc_error_handle Init(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -259,8 +259,8 @@ class CallData { // TODO(roth): Come up with a more C++-like API for the call element. /// Initializes the call data. - virtual grpc_error* Init(grpc_call_element* /*elem*/, - const grpc_call_element_args* /*args*/) { + virtual grpc_error_handle Init(grpc_call_element* /*elem*/, + const grpc_call_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -288,8 +288,8 @@ class ChannelFilter final { public: static const size_t channel_data_size = sizeof(ChannelDataType); - static grpc_error* InitChannelElement(grpc_channel_element* elem, - grpc_channel_element_args* args) { + static grpc_error_handle InitChannelElement(grpc_channel_element* elem, + grpc_channel_element_args* args) { // Construct the object in the already-allocated memory. ChannelDataType* channel_data = new (elem->channel_data) ChannelDataType(); return channel_data->Init(elem, args); @@ -319,8 +319,8 @@ class ChannelFilter final { static const size_t call_data_size = sizeof(CallDataType); - static grpc_error* InitCallElement(grpc_call_element* elem, - const grpc_call_element_args* args) { + static grpc_error_handle InitCallElement(grpc_call_element* elem, + const grpc_call_element_args* args) { // Construct the object in the already-allocated memory. CallDataType* call_data = new (elem->call_data) CallDataType(); return call_data->Init(elem, args); diff --git a/src/cpp/common/validate_service_config.cc b/src/cpp/common/validate_service_config.cc index 720c0907d85..cac39ad98eb 100644 --- a/src/cpp/common/validate_service_config.cc +++ b/src/cpp/common/validate_service_config.cc @@ -25,12 +25,12 @@ namespace grpc { namespace experimental { std::string ValidateServiceConfigJSON(const std::string& service_config_json) { grpc_init(); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::ServiceConfig::Create(/*args=*/nullptr, service_config_json.c_str(), &error); std::string return_value; if (error != GRPC_ERROR_NONE) { - return_value = grpc_error_string(error); + return_value = grpc_error_std_string(error); GRPC_ERROR_UNREF(error); } grpc_shutdown(); diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc index 6c4e9d47515..4bd31852688 100644 --- a/src/cpp/common/version_cc.cc +++ b/src/cpp/common/version_cc.cc @@ -22,5 +22,5 @@ #include namespace grpc { -std::string Version() { return "1.37.0-dev"; } +std::string Version() { return "1.38.0-dev"; } } // namespace grpc diff --git a/src/cpp/ext/filters/census/channel_filter.cc b/src/cpp/ext/filters/census/channel_filter.cc index 80670bf9e48..ea3bce9f720 100644 --- a/src/cpp/ext/filters/census/channel_filter.cc +++ b/src/cpp/ext/filters/census/channel_filter.cc @@ -22,8 +22,8 @@ namespace grpc { -grpc_error* CensusChannelData::Init(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +grpc_error_handle CensusChannelData::Init(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } diff --git a/src/cpp/ext/filters/census/channel_filter.h b/src/cpp/ext/filters/census/channel_filter.h index 0b7c6826816..d756f23258e 100644 --- a/src/cpp/ext/filters/census/channel_filter.h +++ b/src/cpp/ext/filters/census/channel_filter.h @@ -27,8 +27,8 @@ namespace grpc { class CensusChannelData : public ChannelData { public: - grpc_error* Init(grpc_channel_element* elem, - grpc_channel_element_args* args) override; + grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args) override; }; } // namespace grpc diff --git a/src/cpp/ext/filters/census/client_filter.cc b/src/cpp/ext/filters/census/client_filter.cc index c5af4d7cc11..380ad5b5497 100644 --- a/src/cpp/ext/filters/census/client_filter.cc +++ b/src/cpp/ext/filters/census/client_filter.cc @@ -53,8 +53,8 @@ void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) { } // namespace -void CensusClientCallData::OnDoneRecvTrailingMetadataCb(void* user_data, - grpc_error* error) { +void CensusClientCallData::OnDoneRecvTrailingMetadataCb( + void* user_data, grpc_error_handle error) { grpc_call_element* elem = reinterpret_cast(user_data); CensusClientCallData* calld = reinterpret_cast(elem->call_data); @@ -70,7 +70,7 @@ void CensusClientCallData::OnDoneRecvTrailingMetadataCb(void* user_data, } void CensusClientCallData::OnDoneRecvMessageCb(void* user_data, - grpc_error* error) { + grpc_error_handle error) { grpc_call_element* elem = reinterpret_cast(user_data); CensusClientCallData* calld = reinterpret_cast(elem->call_data); @@ -138,8 +138,8 @@ void CensusClientCallData::StartTransportStreamOpBatch( grpc_call_next_op(elem, op->op()); } -grpc_error* CensusClientCallData::Init(grpc_call_element* elem, - const grpc_call_element_args* args) { +grpc_error_handle CensusClientCallData::Init( + grpc_call_element* elem, const grpc_call_element_args* args) { path_ = grpc_slice_ref_internal(args->path); start_time_ = absl::Now(); method_ = GetMethod(&path_); diff --git a/src/cpp/ext/filters/census/client_filter.h b/src/cpp/ext/filters/census/client_filter.h index 851022873f1..f55a4b5cdc6 100644 --- a/src/cpp/ext/filters/census/client_filter.h +++ b/src/cpp/ext/filters/census/client_filter.h @@ -54,8 +54,8 @@ class CensusClientCallData : public CallData { memset(&on_done_recv_message_, 0, sizeof(grpc_closure)); } - grpc_error* Init(grpc_call_element* elem, - const grpc_call_element_args* args) override; + grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args) override; void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* then_call_closure) override; @@ -63,11 +63,13 @@ class CensusClientCallData : public CallData { void StartTransportStreamOpBatch(grpc_call_element* elem, TransportStreamOpBatch* op) override; - static void OnDoneRecvTrailingMetadataCb(void* user_data, grpc_error* error); + static void OnDoneRecvTrailingMetadataCb(void* user_data, + grpc_error_handle error); - static void OnDoneSendInitialMetadataCb(void* user_data, grpc_error* error); + static void OnDoneSendInitialMetadataCb(void* user_data, + grpc_error_handle error); - static void OnDoneRecvMessageCb(void* user_data, grpc_error* error); + static void OnDoneRecvMessageCb(void* user_data, grpc_error_handle error); private: CensusContext context_; diff --git a/src/cpp/ext/filters/census/context.cc b/src/cpp/ext/filters/census/context.cc index cffa68d6f56..0650bd1b01a 100644 --- a/src/cpp/ext/filters/census/context.cc +++ b/src/cpp/ext/filters/census/context.cc @@ -20,6 +20,7 @@ #include "opencensus/tags/context_util.h" #include "opencensus/trace/context_util.h" +#include "opencensus/trace/propagation/grpc_trace_bin.h" #include "src/cpp/ext/filters/census/context.h" namespace grpc { @@ -33,14 +34,11 @@ void GenerateServerContext(absl::string_view tracing, absl::string_view method, // Destruct the current CensusContext to free the Span memory before // overwriting it below. context->~CensusContext(); - GrpcTraceContext trace_ctxt; - if (TraceContextEncoding::Decode(tracing, &trace_ctxt) != - TraceContextEncoding::kEncodeDecodeFailure) { - SpanContext parent_ctx = trace_ctxt.ToSpanContext(); - if (parent_ctx.IsValid()) { - new (context) CensusContext(method, parent_ctx); - return; - } + SpanContext parent_ctx = + opencensus::trace::propagation::FromGrpcTraceBinHeader(tracing); + if (parent_ctx.IsValid()) { + new (context) CensusContext(method, parent_ctx); + return; } new (context) CensusContext(method, TagMap{}); } @@ -71,9 +69,13 @@ void GenerateClientContext(absl::string_view method, CensusContext* ctxt, size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context, char* tracing_buf, size_t tracing_buf_size) { - GrpcTraceContext trace_ctxt(context); - return TraceContextEncoding::Encode(trace_ctxt, tracing_buf, - tracing_buf_size); + if (tracing_buf_size < + opencensus::trace::propagation::kGrpcTraceBinHeaderLen) { + return 0; + } + opencensus::trace::propagation::ToGrpcTraceBinHeader( + context, reinterpret_cast(tracing_buf)); + return opencensus::trace::propagation::kGrpcTraceBinHeaderLen; } size_t StatsContextSerialize(size_t /*max_tags_len*/, grpc_slice* /*tags*/) { diff --git a/src/cpp/ext/filters/census/context.h b/src/cpp/ext/filters/census/context.h index 55709963522..67f5704a624 100644 --- a/src/cpp/ext/filters/census/context.h +++ b/src/cpp/ext/filters/census/context.h @@ -75,8 +75,8 @@ class CensusContext { ::opencensus::tags::TagMap tags_; }; -// Serializes the outgoing trace context. Field IDs are 1 byte followed by -// field data. A 1 byte version ID is always encoded first. +// Serializes the outgoing trace context. tracing_buf must be +// opencensus::trace::propagation::kGrpcTraceBinHeaderLen bytes long. size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context, char* tracing_buf, size_t tracing_buf_size); diff --git a/src/cpp/ext/filters/census/rpc_encoding.cc b/src/cpp/ext/filters/census/rpc_encoding.cc index 45a66d9dc82..7ce3e940df7 100644 --- a/src/cpp/ext/filters/census/rpc_encoding.cc +++ b/src/cpp/ext/filters/census/rpc_encoding.cc @@ -22,13 +22,6 @@ namespace grpc { -constexpr size_t TraceContextEncoding::kGrpcTraceContextSize; -constexpr size_t TraceContextEncoding::kEncodeDecodeFailure; -constexpr size_t TraceContextEncoding::kVersionIdSize; -constexpr size_t TraceContextEncoding::kFieldIdSize; -constexpr size_t TraceContextEncoding::kVersionIdOffset; -constexpr size_t TraceContextEncoding::kVersionId; - constexpr size_t RpcServerStatsEncoding::kRpcServerStatsSize; constexpr size_t RpcServerStatsEncoding::kEncodeDecodeFailure; constexpr size_t RpcServerStatsEncoding::kVersionIdSize; diff --git a/src/cpp/ext/filters/census/rpc_encoding.h b/src/cpp/ext/filters/census/rpc_encoding.h index b897dfcb638..821c7158dd9 100644 --- a/src/cpp/ext/filters/census/rpc_encoding.h +++ b/src/cpp/ext/filters/census/rpc_encoding.h @@ -31,175 +31,6 @@ namespace grpc { -// TODO(unknown): Rename to GrpcTraceContextV0. -struct GrpcTraceContext { - GrpcTraceContext() {} - - explicit GrpcTraceContext(const ::opencensus::trace::SpanContext& ctx) { - ctx.trace_id().CopyTo(trace_id); - ctx.span_id().CopyTo(span_id); - ctx.trace_options().CopyTo(trace_options); - } - - ::opencensus::trace::SpanContext ToSpanContext() const { - return ::opencensus::trace::SpanContext( - ::opencensus::trace::TraceId(trace_id), - ::opencensus::trace::SpanId(span_id), - ::opencensus::trace::TraceOptions(trace_options)); - } - - // TODO(unknown): For performance: - // uint8_t version; - // uint8_t trace_id_field_id; - uint8_t trace_id[::opencensus::trace::TraceId::kSize]; - // uint8_t span_id_field_id; - uint8_t span_id[::opencensus::trace::SpanId::kSize]; - // uint8_t trace_options_field_id; - uint8_t trace_options[::opencensus::trace::TraceOptions::kSize]; -}; - -// TraceContextEncoding encapsulates the logic for encoding and decoding of -// trace contexts. -class TraceContextEncoding { - public: - // Size of encoded GrpcTraceContext. (16 + 8 + 1 + 4) - static constexpr size_t kGrpcTraceContextSize = 29; - // Error value. - static constexpr size_t kEncodeDecodeFailure = 0; - - // Deserializes a GrpcTraceContext from the incoming buffer. Returns the - // number of bytes deserialized from the buffer. If the incoming buffer is - // empty or the encoding version is not supported it will return 0 bytes, - // currently only version 0 is supported. If an unknown field ID is - // encountered it will return immediately without parsing the rest of the - // buffer. Inlined for performance reasons. - static size_t Decode(absl::string_view buf, GrpcTraceContext* tc) { - if (buf.empty()) { - return kEncodeDecodeFailure; - } - uint8_t version = buf[kVersionIdOffset]; - // TODO(unknown): Support other versions later. Only support version 0 for - // now. - if (version != kVersionId) { - return kEncodeDecodeFailure; - } - - size_t pos = kVersionIdSize; - while (pos < buf.size()) { - size_t bytes_read = - ParseField(absl::string_view(&buf[pos], buf.size() - pos), tc); - if (bytes_read == 0) { - break; - } else { - pos += bytes_read; - } - } - return pos; - } - - // Serializes a GrpcTraceContext into the provided buffer. Returns the number - // of bytes serialized into the buffer. If the buffer is not of sufficient - // size (it must be at least kGrpcTraceContextSize bytes) it will drop - // everything and return 0 bytes serialized. Inlined for performance reasons. - static size_t Encode(const GrpcTraceContext& tc, char* buf, size_t buf_size) { - if (buf_size < kGrpcTraceContextSize) { - return kEncodeDecodeFailure; - } - buf[kVersionIdOffset] = kVersionId; - buf[kTraceIdOffset] = kTraceIdField; - memcpy(&buf[kTraceIdOffset + 1], tc.trace_id, - opencensus::trace::TraceId::kSize); - buf[kSpanIdOffset] = kSpanIdField; - memcpy(&buf[kSpanIdOffset + 1], tc.span_id, - opencensus::trace::SpanId::kSize); - buf[kTraceOptionsOffset] = kTraceOptionsField; - memcpy(&buf[kTraceOptionsOffset + 1], tc.trace_options, - opencensus::trace::TraceOptions::kSize); - return kGrpcTraceContextSize; - } - - private: - // Parses the next field from the incoming buffer and stores the parsed value - // in a GrpcTraceContext struct. If it does not recognize the field ID it - // will return 0, otherwise it returns the number of bytes read. - static size_t ParseField(absl::string_view buf, GrpcTraceContext* tc) { - // TODO(unknown): Add support for multi-byte field IDs. - if (buf.empty()) { - return 0; - } - // Field ID is always the first byte in a field. - uint32_t field_id = buf[0]; - size_t bytes_read = kFieldIdSize; - switch (field_id) { - case kTraceIdField: - bytes_read += kTraceIdSize; - if (bytes_read > buf.size()) { - return 0; - } - memcpy(tc->trace_id, &buf[kFieldIdSize], - opencensus::trace::TraceId::kSize); - break; - case kSpanIdField: - bytes_read += kSpanIdSize; - if (bytes_read > buf.size()) { - return 0; - } - memcpy(tc->span_id, &buf[kFieldIdSize], - opencensus::trace::SpanId::kSize); - break; - case kTraceOptionsField: - bytes_read += kTraceOptionsSize; - if (bytes_read > buf.size()) { - return 0; - } - memcpy(tc->trace_options, &buf[kFieldIdSize], - opencensus::trace::TraceOptions::kSize); - break; - default: // Invalid field ID - return 0; - } - - return bytes_read; - } - - // Size of Version ID. - static constexpr size_t kVersionIdSize = 1; - // Size of Field ID. - static constexpr size_t kFieldIdSize = 1; - - // Offset and value for currently supported version ID. - static constexpr size_t kVersionIdOffset = 0; - static constexpr size_t kVersionId = 0; - - // Fixed Field ID values: - enum FieldIdValue { - kTraceIdField = 0, - kSpanIdField = 1, - kTraceOptionsField = 2, - }; - - // Field data sizes in bytes - enum FieldSize { - kTraceIdSize = 16, - kSpanIdSize = 8, - kTraceOptionsSize = 1, - }; - - // Fixed size offsets for field ID start positions during encoding. Field - // data immediately follows. - enum FieldIdOffset { - kTraceIdOffset = kVersionIdSize, - kSpanIdOffset = kTraceIdOffset + kFieldIdSize + kTraceIdSize, - kTraceOptionsOffset = kSpanIdOffset + kFieldIdSize + kSpanIdSize, - }; - - TraceContextEncoding() = delete; - TraceContextEncoding(const TraceContextEncoding&) = delete; - TraceContextEncoding(TraceContextEncoding&&) = delete; - TraceContextEncoding operator=(const TraceContextEncoding&) = delete; - TraceContextEncoding operator=(TraceContextEncoding&&) = delete; -}; - // TODO(unknown): This may not be needed. Check to see if opencensus requires // a trailing server response. // RpcServerStatsEncoding encapsulates the logic for encoding and decoding of diff --git a/src/cpp/ext/filters/census/server_filter.cc b/src/cpp/ext/filters/census/server_filter.cc index 61e28de635e..72ee8e16a63 100644 --- a/src/cpp/ext/filters/census/server_filter.cc +++ b/src/cpp/ext/filters/census/server_filter.cc @@ -62,7 +62,7 @@ void FilterInitialMetadata(grpc_metadata_batch* b, } // namespace void CensusServerCallData::OnDoneRecvMessageCb(void* user_data, - grpc_error* error) { + grpc_error_handle error) { grpc_call_element* elem = reinterpret_cast(user_data); CensusServerCallData* calld = reinterpret_cast(elem->call_data); @@ -78,8 +78,8 @@ void CensusServerCallData::OnDoneRecvMessageCb(void* user_data, GRPC_ERROR_REF(error)); } -void CensusServerCallData::OnDoneRecvInitialMetadataCb(void* user_data, - grpc_error* error) { +void CensusServerCallData::OnDoneRecvInitialMetadataCb( + void* user_data, grpc_error_handle error) { grpc_call_element* elem = reinterpret_cast(user_data); CensusServerCallData* calld = reinterpret_cast(elem->call_data); @@ -154,8 +154,8 @@ void CensusServerCallData::StartTransportStreamOpBatch( grpc_call_next_op(elem, op->op()); } -grpc_error* CensusServerCallData::Init(grpc_call_element* elem, - const grpc_call_element_args* args) { +grpc_error_handle CensusServerCallData::Init( + grpc_call_element* elem, const grpc_call_element_args* args) { start_time_ = absl::Now(); gc_ = grpc_call_from_top_element(grpc_call_stack_element(args->call_stack, 0)); diff --git a/src/cpp/ext/filters/census/server_filter.h b/src/cpp/ext/filters/census/server_filter.h index e393ed32839..81bec8fae94 100644 --- a/src/cpp/ext/filters/census/server_filter.h +++ b/src/cpp/ext/filters/census/server_filter.h @@ -54,8 +54,8 @@ class CensusServerCallData : public CallData { memset(&on_done_recv_message_, 0, sizeof(grpc_closure)); } - grpc_error* Init(grpc_call_element* elem, - const grpc_call_element_args* args) override; + grpc_error_handle Init(grpc_call_element* elem, + const grpc_call_element_args* args) override; void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info, grpc_closure* then_call_closure) override; @@ -63,9 +63,10 @@ class CensusServerCallData : public CallData { void StartTransportStreamOpBatch(grpc_call_element* elem, TransportStreamOpBatch* op) override; - static void OnDoneRecvInitialMetadataCb(void* user_data, grpc_error* error); + static void OnDoneRecvInitialMetadataCb(void* user_data, + grpc_error_handle error); - static void OnDoneRecvMessageCb(void* user_data, grpc_error* error); + static void OnDoneRecvMessageCb(void* user_data, grpc_error_handle error); private: CensusContext context_; diff --git a/src/cpp/server/admin/admin_services.cc b/src/cpp/server/admin/admin_services.cc new file mode 100644 index 00000000000..5159b3adbe4 --- /dev/null +++ b/src/cpp/server/admin/admin_services.cc @@ -0,0 +1,52 @@ +// +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include + +#include "absl/memory/memory.h" + +#include +#include + +#include + +// TODO(lidiz) build a real registration system that can pull in services +// automatically with minimum amount of code. +#include "src/cpp/server/channelz/channelz_service.h" +#if !defined(GRPC_NO_XDS) && !defined(DISABLED_XDS_PROTO_IN_CC) +#include "src/cpp/server/csds/csds.h" +#endif // GRPC_NO_XDS or DISABLED_XDS_PROTO_IN_CC +namespace grpc { + +namespace { + +static auto* g_channelz_service = new ChannelzService(); +#if !defined(GRPC_NO_XDS) && !defined(DISABLED_XDS_PROTO_IN_CC) +static auto* g_csds = new xds::experimental::ClientStatusDiscoveryService(); +#endif // GRPC_NO_XDS or DISABLED_XDS_PROTO_IN_CC + +} // namespace + +void AddAdminServices(ServerBuilder* builder) { + builder->RegisterService(g_channelz_service); +#if !defined(GRPC_NO_XDS) && !defined(DISABLED_XDS_PROTO_IN_CC) + builder->RegisterService(g_csds); +#endif // GRPC_NO_XDS or DISABLED_XDS_PROTO_IN_CC +} + +} // namespace grpc diff --git a/src/cpp/server/csds/csds.cc b/src/cpp/server/csds/csds.cc new file mode 100644 index 00000000000..fc8e7e0e3c2 --- /dev/null +++ b/src/cpp/server/csds/csds.cc @@ -0,0 +1,94 @@ +// +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include + +#include "src/cpp/server/csds/csds.h" + +#include "absl/status/statusor.h" + +#include +#include +#include + +#include + +#include "src/proto/grpc/testing/xds/v3/csds.grpc.pb.h" + +namespace grpc { +namespace xds { +namespace experimental { + +using envoy::service::status::v3::ClientConfig; +using envoy::service::status::v3::ClientStatusRequest; +using envoy::service::status::v3::ClientStatusResponse; + +namespace { + +absl::StatusOr DumpClientConfig() { + ClientConfig client_config; + grpc_slice serialized_client_config = grpc_dump_xds_configs(); + std::string bytes = StringFromCopiedSlice(serialized_client_config); + grpc_slice_unref(serialized_client_config); + if (!client_config.ParseFromString(bytes)) { + return absl::InternalError("Failed to parse ClientConfig."); + } + return client_config; +} + +} // namespace + +Status ClientStatusDiscoveryService::StreamClientStatus( + ServerContext* /*context*/, + ServerReaderWriter* stream) { + ClientStatusRequest request; + while (stream->Read(&request)) { + ClientStatusResponse response; + absl::StatusOr s = DumpClientConfig(); + if (!s.ok()) { + if (s.status().code() == absl::StatusCode::kUnavailable) { + // If the xDS client is not initialized, return empty response + stream->Write(response); + continue; + } + return Status(StatusCode(s.status().raw_code()), s.status().ToString()); + } + *response.add_config() = std::move(s.value()); + stream->Write(response); + } + return Status::OK; +} + +Status ClientStatusDiscoveryService::FetchClientStatus( + ServerContext* /*context*/, const ClientStatusRequest* /*request*/, + ClientStatusResponse* response) { + absl::StatusOr s = DumpClientConfig(); + if (!s.ok()) { + if (s.status().code() == absl::StatusCode::kUnavailable) { + // If the xDS client is not initialized, return empty response + return Status::OK; + } + return Status(StatusCode(s.status().raw_code()), s.status().ToString()); + } + *response->add_config() = std::move(s.value()); + return Status::OK; +} + +} // namespace experimental +} // namespace xds +} // namespace grpc diff --git a/src/cpp/server/csds/csds.h b/src/cpp/server/csds/csds.h new file mode 100644 index 00000000000..be2a4aa1ee8 --- /dev/null +++ b/src/cpp/server/csds/csds.h @@ -0,0 +1,55 @@ +// +// +// Copyright 2021 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_INTERNAL_CPP_SERVER_CSDS_H +#define GRPC_INTERNAL_CPP_SERVER_CSDS_H + +#include +#include +#include "absl/status/status.h" + +#include "src/proto/grpc/testing/xds/v3/csds.grpc.pb.h" + +namespace grpc { +namespace xds { +namespace experimental { + +// The implementation of +// envoy::service::status::v3::ClientStatusDiscoveryService +class ClientStatusDiscoveryService final + : public envoy::service::status::v3::ClientStatusDiscoveryService::Service { + public: + // A streaming call that responds client status for each request. + Status StreamClientStatus( + ServerContext* /*context*/, + ServerReaderWriter* + stream) override; + + // An unary call to fetch client status. + Status FetchClientStatus( + ServerContext* /*unused*/, + const envoy::service::status::v3::ClientStatusRequest* /*request*/, + envoy::service::status::v3::ClientStatusResponse* response) override; +}; + +} // namespace experimental +} // namespace xds +} // namespace grpc + +#endif // GRPC_INTERNAL_CPP_SERVER_CSDS_H diff --git a/src/cpp/server/health/default_health_check_service.cc b/src/cpp/server/health/default_health_check_service.cc index 2ba2e8cadac..42c55c526ef 100644 --- a/src/cpp/server/health/default_health_check_service.cc +++ b/src/cpp/server/health/default_health_check_service.cc @@ -243,10 +243,9 @@ bool DefaultHealthCheckService::HealthCheckServiceImpl::EncodeResponse( grpc_health_v1_HealthCheckResponse_new(arena.ptr()); grpc_health_v1_HealthCheckResponse_set_status( response_struct, - status == NOT_FOUND - ? grpc_health_v1_HealthCheckResponse_SERVICE_UNKNOWN - : status == SERVING ? grpc_health_v1_HealthCheckResponse_SERVING - : grpc_health_v1_HealthCheckResponse_NOT_SERVING); + status == NOT_FOUND ? grpc_health_v1_HealthCheckResponse_SERVICE_UNKNOWN + : status == SERVING ? grpc_health_v1_HealthCheckResponse_SERVING + : grpc_health_v1_HealthCheckResponse_NOT_SERVING); size_t buf_length; char* buf = grpc_health_v1_HealthCheckResponse_serialize( response_struct, arena.ptr(), &buf_length); diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc index 7e7da865ee2..695aa541ddb 100644 --- a/src/cpp/server/server_builder.cc +++ b/src/cpp/server/server_builder.cc @@ -223,8 +223,8 @@ ServerBuilder& ServerBuilder::AddListeningPort( return *this; } -std::unique_ptr ServerBuilder::BuildAndStart() { - grpc::ChannelArguments args; +ChannelArguments ServerBuilder::BuildChannelArgs() { + ChannelArguments args; if (max_receive_message_size_ >= -1) { args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, max_receive_message_size_); } @@ -245,16 +245,19 @@ std::unique_ptr ServerBuilder::BuildAndStart() { args.SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, maybe_default_compression_algorithm_.algorithm); } - if (resource_quota_ != nullptr) { args.SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota_, grpc_resource_quota_arg_vtable()); } - for (const auto& plugin : plugins_) { plugin->UpdateServerBuilder(this); plugin->UpdateChannelArguments(&args); } + return args; +} + +std::unique_ptr ServerBuilder::BuildAndStart() { + ChannelArguments args = BuildChannelArgs(); // == Determine if the server has any syncrhonous methods == bool has_sync_methods = false; @@ -304,6 +307,10 @@ std::unique_ptr ServerBuilder::BuildAndStart() { } } + if (callback_generic_service_ != nullptr) { + has_frequently_polled_cqs = true; + } + const bool is_hybrid_server = has_sync_methods && has_frequently_polled_cqs; if (has_sync_methods) { diff --git a/src/cpp/server/server_callback.cc b/src/cpp/server/server_callback.cc index f6b72c0fcce..5b2d328b81b 100644 --- a/src/cpp/server/server_callback.cc +++ b/src/cpp/server/server_callback.cc @@ -37,7 +37,7 @@ void ServerCallbackCall::ScheduleOnDone(bool inline_ondone) { explicit ClosureWithArg(ServerCallbackCall* call_arg) : call(call_arg) { GRPC_CLOSURE_INIT( &closure, - [](void* void_arg, grpc_error*) { + [](void* void_arg, grpc_error_handle) { ClosureWithArg* arg = static_cast(void_arg); arg->call->CallOnDone(); delete arg; @@ -66,7 +66,7 @@ void ServerCallbackCall::CallOnCancel(ServerReactor* reactor) { : call(call_arg), reactor(reactor_arg) { GRPC_CLOSURE_INIT( &closure, - [](void* void_arg, grpc_error*) { + [](void* void_arg, grpc_error_handle) { ClosureWithArg* arg = static_cast(void_arg); arg->reactor->OnCancel(); arg->call->MaybeDone(); diff --git a/src/cpp/server/server_cc.cc b/src/cpp/server/server_cc.cc index e7859c7a953..a334cdd867c 100644 --- a/src/cpp/server/server_cc.cc +++ b/src/cpp/server/server_cc.cc @@ -67,6 +67,15 @@ namespace { // max-threads set) to the server builder. #define DEFAULT_MAX_SYNC_SERVER_THREADS INT_MAX +// Give a useful status error message if the resource is exhausted specifically +// because the server threadpool is full. +const char* kServerThreadpoolExhausted = "Server Threadpool Exhausted"; + +// Although we might like to give a useful status error message on unimplemented +// RPCs, it's not always possible since that also would need to be added across +// languages and isn't actually required by the spec. +const char* kUnknownRpcMethod = ""; + class DefaultGlobalCallbacks final : public Server::GlobalCallbacks { public: ~DefaultGlobalCallbacks() override {} @@ -802,7 +811,7 @@ class Server::SyncRequestThreadManager : public grpc::ThreadManager { if (has_sync_method_) { unknown_method_ = absl::make_unique( "unknown", grpc::internal::RpcMethod::BIDI_STREAMING, - new grpc::internal::UnknownMethodHandler); + new grpc::internal::UnknownMethodHandler(kUnknownRpcMethod)); server_->server()->core_server->SetBatchMethodAllocator( server_cq_->cq(), [this] { grpc_core::Server::BatchCallAllocation result; @@ -930,14 +939,16 @@ Server::~Server() { for (const auto& value : sync_req_mgrs_) { value->Shutdown(); } - if (callback_cq_ != nullptr) { + CompletionQueue* callback_cq = + callback_cq_.load(std::memory_order_relaxed); + if (callback_cq != nullptr) { if (grpc_iomgr_run_in_background()) { // gRPC-core provides the backing needed for the preferred CQ type - callback_cq_->Shutdown(); + callback_cq->Shutdown(); } else { - CompletionQueue::ReleaseCallbackAlternativeCQ(callback_cq_); + CompletionQueue::ReleaseCallbackAlternativeCQ(callback_cq); } - callback_cq_ = nullptr; + callback_cq_.store(nullptr, std::memory_order_release); } } } @@ -1104,8 +1115,9 @@ void Server::UnrefAndWaitLocked() { shutdown_done_ = true; return; // no need to wait on CV since done condition already set } - grpc::internal::WaitUntil(&shutdown_done_cv_, &mu_, - [this] { return shutdown_done_; }); + grpc::internal::WaitUntil( + &shutdown_done_cv_, &mu_, + [this]() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { return shutdown_done_; }); } void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) { @@ -1191,7 +1203,8 @@ void Server::Start(grpc::ServerCompletionQueue** cqs, size_t num_cqs) { // to deal with the case of thread exhaustion if (sync_server_cqs_ != nullptr && !sync_server_cqs_->empty()) { resource_exhausted_handler_ = - absl::make_unique(); + absl::make_unique( + kServerThreadpoolExhausted); } for (const auto& value : sync_req_mgrs_) { @@ -1255,14 +1268,15 @@ void Server::ShutdownInternal(gpr_timespec deadline) { // Shutdown the callback CQ. The CQ is owned by its own shutdown tag, so it // will delete itself at true shutdown. - if (callback_cq_ != nullptr) { + CompletionQueue* callback_cq = callback_cq_.load(std::memory_order_relaxed); + if (callback_cq != nullptr) { if (grpc_iomgr_run_in_background()) { // gRPC-core provides the backing needed for the preferred CQ type - callback_cq_->Shutdown(); + callback_cq->Shutdown(); } else { - CompletionQueue::ReleaseCallbackAlternativeCQ(callback_cq_); + CompletionQueue::ReleaseCallbackAlternativeCQ(callback_cq); } - callback_cq_ = nullptr; + callback_cq_.store(nullptr, std::memory_order_release); } // Drain the shutdown queue (if the previous call to AsyncNext() timed out @@ -1317,8 +1331,9 @@ bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag, Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse( UnimplementedAsyncRequest* request) : request_(request) { - grpc::Status status(grpc::StatusCode::UNIMPLEMENTED, ""); - grpc::internal::UnknownMethodHandler::FillOps(request_->context(), this); + grpc::Status status(grpc::StatusCode::UNIMPLEMENTED, kUnknownRpcMethod); + grpc::internal::UnknownMethodHandler::FillOps(request_->context(), + kUnknownRpcMethod, this); request_->stream()->call_.PerformOps(this); } @@ -1329,25 +1344,33 @@ grpc::ServerInitializer* Server::initializer() { grpc::CompletionQueue* Server::CallbackCQ() { // TODO(vjpai): Consider using a single global CQ for the default CQ // if there is no explicit per-server CQ registered + CompletionQueue* callback_cq = callback_cq_.load(std::memory_order_acquire); + if (callback_cq != nullptr) { + return callback_cq; + } + // The callback_cq_ wasn't already set, so grab a lock and set it up exactly + // once for this server. grpc::internal::MutexLock l(&mu_); - if (callback_cq_ != nullptr) { - return callback_cq_; + callback_cq = callback_cq_.load(std::memory_order_relaxed); + if (callback_cq != nullptr) { + return callback_cq; } if (grpc_iomgr_run_in_background()) { // gRPC-core provides the backing needed for the preferred CQ type auto* shutdown_callback = new grpc::ShutdownCallback; - callback_cq_ = new grpc::CompletionQueue(grpc_completion_queue_attributes{ + callback_cq = new grpc::CompletionQueue(grpc_completion_queue_attributes{ GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING, shutdown_callback}); // Transfer ownership of the new cq to its own shutdown callback - shutdown_callback->TakeCQ(callback_cq_); + shutdown_callback->TakeCQ(callback_cq); } else { // Otherwise we need to use the alternative CQ variant - callback_cq_ = CompletionQueue::CallbackAlternativeCQ(); + callback_cq = CompletionQueue::CallbackAlternativeCQ(); } - return callback_cq_; + callback_cq_.store(callback_cq, std::memory_order_release); + return callback_cq; } } // namespace grpc diff --git a/src/cpp/server/server_context.cc b/src/cpp/server/server_context.cc index 33d58f721c8..2cb014ba138 100644 --- a/src/cpp/server/server_context.cc +++ b/src/cpp/server/server_context.cc @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,8 @@ namespace grpc { +static internal::GrpcLibraryInitializer g_gli_initializer; + // CompletionOp class ServerContextBase::CompletionOp final @@ -233,7 +236,9 @@ bool ServerContextBase::CompletionOp::FinalizeResult(void** tag, bool* status) { // ServerContextBase body ServerContextBase::ServerContextBase() - : deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)) {} + : deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)) { + g_gli_initializer.summon(); +} ServerContextBase::ServerContextBase(gpr_timespec deadline, grpc_metadata_array* arr) diff --git a/src/csharp/BUILD-INTEGRATION.md b/src/csharp/BUILD-INTEGRATION.md index 5854a6d8ff4..b8c30fd22fe 100644 --- a/src/csharp/BUILD-INTEGRATION.md +++ b/src/csharp/BUILD-INTEGRATION.md @@ -1,26 +1,13 @@ -Protocol Buffers/gRPC Integration Into .NET Build +Protocol Buffers/gRPC Codegen Integration Into .NET Build ================================================= With Grpc.Tools package version 1.17 we made it easier to compile .proto files in your project using the `dotnet build` command, Visual Studio, or command-line MSBuild. You need to configure the .csproj project according to the way you want -to integrate Protocol Buffer files into your build. If you are upgrading an -existing project, read through this list of common scenarios and decide if any -one of them matches your approach. The protoc command line migration is -explained near the end of this document; this migration may be the quickest but -not the long-term solution. +to integrate Protocol Buffer files into your build. There is also a Reference section at the end of the file. -Reporting issues ----------------- - -First thing first, if you found a bug in this new build system, or have a -scenario that is not easily covered, please open an [issue in the gRPC -repository](https://github.com/grpc/grpc/issues), and **tag the user @kkm000** -somewhere in the text (for example, include `/cc @kkm000` at end of the issue -text) to seize his immediate attention. - Common scenarios ---------------- @@ -48,35 +35,27 @@ is a meta-package, in turn referencing Grpc.Core and Google.Protobuf packages). It is **very important** to mark Grpc.Tools as a development-only dependency, so that the *users* of your library do not fetch the tools package: -* "Classic" .csproj with `packages.config` (Visual Studio, Mono): This is - handled automatically by NuGet. See the attribute added by Visual Studio to the - [packages.config](../../examples/csharp/HelloworldLegacyCsproj/Greeter/packages.config#L6) - file in the HelloworldLegacyCsproj/Greeter example. - -* "SDK" .csproj (Visual Studio, `dotnet new`): Add an attribute +* "dotnet SDK" .csproj (Visual Studio, `dotnet new`): Add an attribute `PrivateAssets="All"` to the Grpc.Tools package reference. See an example in the [Greeter.csproj](../../examples/csharp/Helloworld/Greeter/Greeter.csproj#L10) example project in this repository. If adding a package reference in Visual Studio, edit the project file and add this attribute. [This is a bug in NuGet client](https://github.com/NuGet/Home/issues/4125). + * "Classic" .csproj with `packages.config` (Visual Studio, Mono): This is + handled automatically by NuGet. See the attribute added by Visual Studio to the + [packages.config](../../examples/csharp/HelloworldLegacyCsproj/Greeter/packages.config#L6) + file in the HelloworldLegacyCsproj/Greeter example. + If building a NuGet package from your library with the nuget command line tool from a .nuspec file, then the spec file may (and probably should) reference the -Grpc metapackage, but **do not add a reference to Grpc.Tools** to it. .NET "SDK" +Grpc metapackage, but **do not add a reference to Grpc.Tools** to it. "dotnet SDK" projects handle this automatically when called from `dotnet pack` by excluding any packages with private assets, such as thus marked Grpc.Tools. #### Per-file options that can be set in Visual Studio -For a "classic" project, you can only add .proto files with all options set to -default (if you find it necessary to modify these options, then hand-edit the -.csproj file). Click on the "show all files" button, add files to project, then -change file type of the .proto files to "Protobuf" in the Properties window -drop-down. This menu item will appear after you import the Grpc.Tools package: - -![Properties in a classic project](doc/integration.md-fig.1-classic.png) - -For an "SDK" project, you have more control of some frequently used options. +For a "dotnet SDK" project, you have more control of some frequently used options. **You may need to open and close Visual Studio** for this form to appear in the properties window after adding a reference to Grpc.Tools package (we do not know whether this is a bug or by design, but it looks like a bug): @@ -86,6 +65,14 @@ whether this is a bug or by design, but it looks like a bug): You can also change options of multiple files at once by selecting them in the Project Explorer together. +For a "classic" project, you can only add .proto files with all options set to +default (if you find it necessary to modify these options, then hand-edit the +.csproj file). Click on the "show all files" button, add files to project, then +change file type of the .proto files to "Protobuf" in the Properties window +drop-down. This menu item will appear after you import the Grpc.Tools package: + +![Properties in a classic project](doc/integration.md-fig.1-classic.png) + See the Reference section at end of this file for options that can be set per-file by modifying the source .csproj directly. @@ -356,14 +343,16 @@ The following metadata are recognized on the `` items. | Name | Default | Value | Synopsis | |----------------|-----------|----------------------|----------------------------------| -| Access | `public` | `public`, `internal` | Generated class access | -| ProtoCompile | `true` | `true`, `false` | Pass files to protoc? | -| ProtoRoot | See notes | A directory | Common root for set of files | -| CompileOutputs | `true` | `true`, `false` | C#-compile generated files? | -| OutputDir | See notes | A directory | Directory for generated C# files | -| GrpcOutputDir | See notes | A directory | Directory for generated stubs | -| GrpcServices | `both` | `none`, `client`, | Generated gRPC stubs | -| | | `server`, `both` | | +| Access | `public` | `public`, `internal` | Generated class access | +| AdditionalProtocArguments | | arbitrary cmdline arguments | Extra command line flags passed to `protoc` command | +| ProtoCompile | `true` | `true`, `false` | Pass files to protoc? | +| ProtoRoot | See notes | A directory | Common root for set of files | +| CompileOutputs | `true` | `true`, `false` | C#-compile generated files? | +| OutputDir | See notes | A directory | Directory for generated C# files with protobuf messages | +| OutputOptions | | arbitrary options | Extra options passed to C# codegen as `--csharp_opt=opt1,opt2` | +| GrpcOutputDir | See notes | A directory | Directory for generated gRPC stubs | +| GrpcOutputOptions | | arbitrary options | Extra options passed to gRPC codegen as `--grpc_opt=opt1,opt2` | +| GrpcServices | `both` | `none`, `client`, `server`, `both` | Generated gRPC stubs | __Notes__ @@ -389,6 +378,18 @@ Unless explicitly set, will follow `OutputDir` for any given file. * __Access__ Sets generated class access on _both_ generated message and gRPC stub classes. +* __AdditionalProtocArguments__ +Pass additional commandline arguments to the `protoc` command being invoked. +Normally this option should not be used, but it exists for scenarios when you need to pass +otherwise unsupported (e.g. experimental) flags to protocol buffer compiler. + +* __GrpcOutputOptions__ +Pass additional options to the `grpc_csharp_plugin` in form of the `--grpc_opt` flag. +Normally this option should not be used as it's values are already controlled by "Access" +and "GrpcServices" metadata, but it might be useful in situations where you want +to explicitly pass some otherwise unsupported (e.g. experimental) options to the +`grpc_csharp_plugin`. + `grpc_csharp_plugin` command line options --------- @@ -400,7 +401,6 @@ to perform code generation. Here is an overview of the available `grpc_csharp_pl | no_client | off | Don't generate the client stub | | no_server | off | Don't generate the server-side stub | | internal_access | off | Generate classes with "internal" visibility | -| lite_client | off | Generate client stubs that inherit from "LiteClientBase" | Note that the protocol buffer compiler has a special commandline syntax for plugin options. Example: @@ -408,4 +408,4 @@ Example: protoc --plugin=protoc-gen-grpc=grpc_csharp_plugin --csharp_out=OUT_DIR \ --grpc_out=OUT_DIR --grpc_opt=lite_client,no_server \ -I INCLUDE_DIR foo.proto -``` \ No newline at end of file +``` diff --git a/src/csharp/Grpc.Core.Api/VersionInfo.cs b/src/csharp/Grpc.Core.Api/VersionInfo.cs index 60a0948847e..a0775bec674 100644 --- a/src/csharp/Grpc.Core.Api/VersionInfo.cs +++ b/src/csharp/Grpc.Core.Api/VersionInfo.cs @@ -33,11 +33,11 @@ namespace Grpc.Core /// /// Current AssemblyFileVersion of gRPC C# assemblies /// - public const string CurrentAssemblyFileVersion = "2.37.0.0"; + public const string CurrentAssemblyFileVersion = "2.38.0.0"; /// /// Current version of gRPC C# /// - public const string CurrentVersion = "2.37.0-dev"; + public const string CurrentVersion = "2.38.0-dev"; } } diff --git a/src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj b/src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj index f2b773816a7..497282dcecf 100644 --- a/src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj +++ b/src/csharp/Grpc.Core.NativeDebug/Grpc.Core.NativeDebug.csproj @@ -2,7 +2,10 @@ The gRPC Authors Copyright 2015 The gRPC Authors - Debug symbols for the native library contained in Grpc.Core + Debug symbols for the grpc_csharp_ext native library contained in Grpc.Core + +Note that the Grpc.Core implementation of gRPC for C# is in maintenance mode and will be replaced by grpc-dotnet in the future. +See https://grpc.io/blog/grpc-csharp-future/ for details. https://github.com/grpc/grpc.github.io/raw/master/img/grpc_square_reverse_4x.png Apache-2.0 https://github.com/grpc/grpc @@ -18,6 +21,14 @@ + + runtimes/linux-x64/native/libgrpc_csharp_ext.x64.dbginfo.so + true + + + runtimes/linux-arm64/native/libgrpc_csharp_ext.arm64.dbginfo.so + true + runtimes/win-x86/native/grpc_csharp_ext.x86.dll true diff --git a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj index e9809d7fa66..45618f08059 100755 --- a/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj +++ b/src/csharp/Grpc.Core.Testing/Grpc.Core.Testing.csproj @@ -1,7 +1,10 @@  The gRPC Authors - Miscellaneous code for testing Grpc.Core + Miscellaneous code for testing Grpc.Core + +Note that the Grpc.Core implementation of gRPC for C# is in maintenance mode and will be replaced by grpc-dotnet in the future. +See https://grpc.io/blog/grpc-csharp-future/ for details. Copyright 2017 The gRPC Authors https://github.com/grpc/grpc.github.io/raw/master/img/grpc_square_reverse_4x.png Apache-2.0 diff --git a/src/csharp/Grpc.Core.Tests/Internal/UserAgentStringProviderTest.cs b/src/csharp/Grpc.Core.Tests/Internal/UserAgentStringProviderTest.cs new file mode 100644 index 00000000000..24e788f6ecd --- /dev/null +++ b/src/csharp/Grpc.Core.Tests/Internal/UserAgentStringProviderTest.cs @@ -0,0 +1,63 @@ +#region Copyright notice and license + +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using Grpc.Core; +using Grpc.Core.Internal; +using Grpc.Core.Utils; +using NUnit.Framework; + +namespace Grpc.Core.Internal.Tests +{ + public class UserAgentStringProviderTest + { + [Test] + public void BasicTest() + { + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; net45; x64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + Assert.AreEqual("grpc-csharp/1.0 (CLR 1.2.3.4; net45; x64)", + new UserAgentStringProvider("1.0", null, "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; net45; x64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", null, "net45", CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; x64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", null, CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + } + + [Test] + public void ArchitectureTest() + { + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; net45; arm64)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.Arm64).GrpcCsharpUserAgentString); + + // unknown architecture + Assert.AreEqual("grpc-csharp/1.0 (.NET Framework 4.6.1; CLR 1.2.3.4; net45)", + new UserAgentStringProvider("1.0", ".NET Framework 4.6.1", "1.2.3.4", "net45", CommonPlatformDetection.CpuArchitecture.Unknown).GrpcCsharpUserAgentString); + } + + [Test] + public void FrameworkDescriptionTest() + { + Assert.AreEqual("grpc-csharp/1.0 (Mono 6.12.0.93; x64)", + new UserAgentStringProvider("1.0", "Mono 6.12.0.93 (2020-02/620cf538206 Tue Aug 25 14:04:52 EDT 2020)", null, null, CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + + Assert.AreEqual("grpc-csharp/1.0 (x64)", + new UserAgentStringProvider("1.0", "(some invalid framework description)", null, null, CommonPlatformDetection.CpuArchitecture.X64).GrpcCsharpUserAgentString); + } + } +} diff --git a/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs b/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs index 1b4676f9e87..baf7ca5c2cb 100644 --- a/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs +++ b/src/csharp/Grpc.Core.Tests/UserAgentStringTest.cs @@ -50,10 +50,10 @@ namespace Grpc.Core.Tests helper = new MockServiceHelper(Host); helper.UnaryHandler = new UnaryServerMethod((request, context) => { - var userAgentString = context.RequestHeaders.First(m => (m.Key == "user-agent")).Value; + var userAgentString = context.RequestHeaders.GetValue("user-agent"); var parts = userAgentString.Split(new [] {' '}, 2); - Assert.AreEqual(string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion), parts[0]); - Assert.IsTrue(parts[1].StartsWith("grpc-c/")); + Assert.AreEqual($"grpc-csharp/{VersionInfo.CurrentVersion}", parts[0]); + Assert.That(parts[1], Does.Match(@"\(.*\) grpc-c/.*")); return Task.FromResult("PASS"); }); @@ -71,9 +71,10 @@ namespace Grpc.Core.Tests channelOptions: new[] { new ChannelOption(ChannelOptions.PrimaryUserAgentString, "XYZ") }); helper.UnaryHandler = new UnaryServerMethod((request, context) => { - var userAgentString = context.RequestHeaders.First(m => (m.Key == "user-agent")).Value; + var userAgentString = context.RequestHeaders.GetValue("user-agent"); var parts = userAgentString.Split(new[] { ' ' }, 3); Assert.AreEqual("XYZ", parts[0]); + Assert.AreEqual($"grpc-csharp/{VersionInfo.CurrentVersion}", parts[1]); return Task.FromResult("PASS"); }); diff --git a/src/csharp/Grpc.Core.Xamarin/Grpc.Core.Xamarin.csproj b/src/csharp/Grpc.Core.Xamarin/Grpc.Core.Xamarin.csproj index 277a1a48a03..d8225365d7a 100644 --- a/src/csharp/Grpc.Core.Xamarin/Grpc.Core.Xamarin.csproj +++ b/src/csharp/Grpc.Core.Xamarin/Grpc.Core.Xamarin.csproj @@ -3,9 +3,12 @@ The gRPC Authors Copyright 2015 The gRPC Authors Xamarin support for gRPC C#. Note that the gRPC C# support for the Xamarin platform is considered experimental. - This package contains the native grpc_csharp_ext libraries that are needed to run gRPC C# on mobile platforms (Android, iOS). - WARNING: Versions of Grpc.Core.Xamarin and Grpc.Core dependencies being used in your project must always match exactly, otherwise - things will be badly broken. + +This package contains the native grpc_csharp_ext libraries that are needed to run gRPC C# on mobile platforms (Android, iOS). +WARNING: Versions of Grpc.Core.Xamarin and Grpc.Core dependencies being used in your project must always match exactly, otherwise things will be badly broken. + +Note that the Grpc.Core implementation of gRPC for C# is in maintenance mode and will be replaced by grpc-dotnet in the future. +See https://grpc.io/blog/grpc-csharp-future/ for details. https://github.com/grpc/grpc.github.io/raw/master/img/grpc_square_reverse_4x.png Apache-2.0 https://github.com/grpc/grpc diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs index 81b7f1f1037..e2d69e408d8 100644 --- a/src/csharp/Grpc.Core/Channel.cs +++ b/src/csharp/Grpc.Core/Channel.cs @@ -318,8 +318,7 @@ namespace Grpc.Core userAgentString = option.StringValue + " "; }; - // TODO(jtattermusch): it would be useful to also provide .NET/mono version. - userAgentString += string.Format("grpc-csharp/{0}", VersionInfo.CurrentVersion); + userAgentString += UserAgentStringProvider.DefaultInstance.GrpcCsharpUserAgentString; options[ChannelOptions.PrimaryUserAgentString] = new ChannelOption(key, userAgentString); } diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 4c7255d2be8..4d376aef5e0 100755 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -2,7 +2,10 @@ The gRPC Authors Copyright 2015 The gRPC Authors - C# implementation of gRPC based on native gRPC C-core library. + C# implementation of gRPC based on native gRPC C-core library. + +Note that the Grpc.Core implementation of gRPC for C# is in maintenance mode and will be replaced by grpc-dotnet in the future. +See https://grpc.io/blog/grpc-csharp-future/ for details. https://github.com/grpc/grpc.github.io/raw/master/img/grpc_square_reverse_4x.png Apache-2.0 https://github.com/grpc/grpc @@ -36,6 +39,10 @@ runtimes/linux-x64/native/libgrpc_csharp_ext.x64.so true + + runtimes/linux-arm64/native/libgrpc_csharp_ext.arm64.so + true + runtimes/win-x64/native/grpc_csharp_ext.x64.dll true diff --git a/src/csharp/Grpc.Core/Internal/CommonPlatformDetection.cs b/src/csharp/Grpc.Core/Internal/CommonPlatformDetection.cs new file mode 100644 index 00000000000..56e24b877b3 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/CommonPlatformDetection.cs @@ -0,0 +1,129 @@ +#region Copyright notice and license + +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Grpc.Core.Internal +{ + /// + /// This source file is shared by both Grpc.Core and Grpc.Tools to avoid duplication + /// of platform detection code. + /// + internal static class CommonPlatformDetection + { + public enum OSKind { Unknown, Windows, Linux, MacOSX }; + public enum CpuArchitecture { Unknown, X86, X64, Arm64 }; + + public static OSKind GetOSKind() + { +#if NETSTANDARD || NETCORE + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return OSKind.Windows; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return OSKind.Linux; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return OSKind.MacOSX; + } + else + { + return OSKind.Unknown; + } +#else + var platform = Environment.OSVersion.Platform; + if (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows) + { + return OSKind.Windows; + } + else if (platform == PlatformID.Unix && GetUname() == "Darwin") + { + // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname. + return OSKind.MacOSX; + } + else if (platform == PlatformID.Unix) + { + // on legacy .NET Framework, our detection options are limited, so we treat + // all other unix systems as Linux. + return OSKind.Linux; + } + else + { + return OSKind.Unknown; + } +#endif + } + + public static CpuArchitecture GetProcessArchitecture() + { +#if NETSTANDARD || NETCORE + switch (RuntimeInformation.ProcessArchitecture) + { + case Architecture.X86: + return CpuArchitecture.X86; + case Architecture.X64: + return CpuArchitecture.X64; + case Architecture.Arm64: + return CpuArchitecture.Arm64; + // We do not support other architectures, + // so we simply return "unrecognized". + default: + return CpuArchitecture.Unknown; + } +#else + // on legacy .NET Framework, RuntimeInformation is not available + // but our choice of supported architectures there + // is also very limited, so we simply take our best guess. + return Environment.Is64BitProcess ? CpuArchitecture.X64 : CpuArchitecture.X86; +#endif + } + + [DllImport("libc")] + static extern int uname(IntPtr buf); + + // This code is copied from Grpc.Core/PlatformApis.cs + static string GetUname() + { + var buffer = Marshal.AllocHGlobal(8192); + try + { + if (uname(buffer) == 0) + { + return Marshal.PtrToStringAnsi(buffer); + } + return string.Empty; + } + catch + { + return string.Empty; + } + finally + { + if (buffer != IntPtr.Zero) + { + Marshal.FreeHGlobal(buffer); + } + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs index 0aa5bb025d1..3073b8147f0 100644 --- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -136,7 +136,7 @@ namespace Grpc.Core.Internal // but DllImport("grpc_csharp_ext.x64.dll") does, so we need a special case for that. // See https://github.com/dotnet/coreclr/pull/17505 (fixed in .NET Core 3.1+) bool useDllSuffix = PlatformApis.IsWindows; - if (PlatformApis.Is64Bit) + if (PlatformApis.ProcessArchitecture == CommonPlatformDetection.CpuArchitecture.X64) { if (useDllSuffix) { @@ -144,7 +144,7 @@ namespace Grpc.Core.Internal } return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_x64()); } - else + else if (PlatformApis.ProcessArchitecture == CommonPlatformDetection.CpuArchitecture.X86) { if (useDllSuffix) { @@ -152,6 +152,14 @@ namespace Grpc.Core.Internal } return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_x86()); } + else if (PlatformApis.ProcessArchitecture == CommonPlatformDetection.CpuArchitecture.Arm64) + { + return new NativeMethods(new NativeMethods.DllImportsFromSharedLib_arm64()); + } + else + { + throw new InvalidOperationException($"Unsupported architecture \"{PlatformApis.ProcessArchitecture}\"."); + } } /// @@ -285,16 +293,18 @@ namespace Grpc.Core.Internal throw new InvalidOperationException("Unsupported platform."); } - // Currently, only Intel platform is supported. private static string GetArchitectureString() { - if (PlatformApis.Is64Bit) - { - return "x64"; - } - else + switch (PlatformApis.ProcessArchitecture) { - return "x86"; + case CommonPlatformDetection.CpuArchitecture.X86: + return "x86"; + case CommonPlatformDetection.CpuArchitecture.X64: + return "x64"; + case CommonPlatformDetection.CpuArchitecture.Arm64: + return "arm64"; + default: + throw new InvalidOperationException($"Unsupported architecture \"{PlatformApis.ProcessArchitecture}\"."); } } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs index 9bc6a481344..83d9ffaa332 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs @@ -681,6 +681,114 @@ namespace Grpc.Core.Internal this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib_x64.grpcsharp_test_call_start_unary_echo; } + public NativeMethods(DllImportsFromSharedLib_arm64 unusedInstance) + { + this.grpcsharp_init = DllImportsFromSharedLib_arm64.grpcsharp_init; + this.grpcsharp_shutdown = DllImportsFromSharedLib_arm64.grpcsharp_shutdown; + this.grpcsharp_version_string = DllImportsFromSharedLib_arm64.grpcsharp_version_string; + this.grpcsharp_batch_context_create = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_create; + this.grpcsharp_batch_context_recv_initial_metadata = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_initial_metadata; + this.grpcsharp_batch_context_recv_message_length = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_message_length; + this.grpcsharp_batch_context_recv_message_next_slice_peek = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_message_next_slice_peek; + this.grpcsharp_batch_context_recv_status_on_client_status = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_status; + this.grpcsharp_batch_context_recv_status_on_client_details = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_details; + this.grpcsharp_batch_context_recv_status_on_client_error_string = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_error_string; + this.grpcsharp_batch_context_recv_status_on_client_trailing_metadata = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_status_on_client_trailing_metadata; + this.grpcsharp_batch_context_recv_close_on_server_cancelled = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_recv_close_on_server_cancelled; + this.grpcsharp_batch_context_reset = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_reset; + this.grpcsharp_batch_context_destroy = DllImportsFromSharedLib_arm64.grpcsharp_batch_context_destroy; + this.grpcsharp_request_call_context_create = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_create; + this.grpcsharp_request_call_context_call = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_call; + this.grpcsharp_request_call_context_method = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_method; + this.grpcsharp_request_call_context_host = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_host; + this.grpcsharp_request_call_context_deadline = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_deadline; + this.grpcsharp_request_call_context_request_metadata = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_request_metadata; + this.grpcsharp_request_call_context_reset = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_reset; + this.grpcsharp_request_call_context_destroy = DllImportsFromSharedLib_arm64.grpcsharp_request_call_context_destroy; + this.grpcsharp_composite_call_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_composite_call_credentials_create; + this.grpcsharp_call_credentials_release = DllImportsFromSharedLib_arm64.grpcsharp_call_credentials_release; + this.grpcsharp_call_cancel = DllImportsFromSharedLib_arm64.grpcsharp_call_cancel; + this.grpcsharp_call_cancel_with_status = DllImportsFromSharedLib_arm64.grpcsharp_call_cancel_with_status; + this.grpcsharp_call_start_unary = DllImportsFromSharedLib_arm64.grpcsharp_call_start_unary; + this.grpcsharp_call_start_client_streaming = DllImportsFromSharedLib_arm64.grpcsharp_call_start_client_streaming; + this.grpcsharp_call_start_server_streaming = DllImportsFromSharedLib_arm64.grpcsharp_call_start_server_streaming; + this.grpcsharp_call_start_duplex_streaming = DllImportsFromSharedLib_arm64.grpcsharp_call_start_duplex_streaming; + this.grpcsharp_call_send_message = DllImportsFromSharedLib_arm64.grpcsharp_call_send_message; + this.grpcsharp_call_send_close_from_client = DllImportsFromSharedLib_arm64.grpcsharp_call_send_close_from_client; + this.grpcsharp_call_send_status_from_server = DllImportsFromSharedLib_arm64.grpcsharp_call_send_status_from_server; + this.grpcsharp_call_recv_message = DllImportsFromSharedLib_arm64.grpcsharp_call_recv_message; + this.grpcsharp_call_recv_initial_metadata = DllImportsFromSharedLib_arm64.grpcsharp_call_recv_initial_metadata; + this.grpcsharp_call_start_serverside = DllImportsFromSharedLib_arm64.grpcsharp_call_start_serverside; + this.grpcsharp_call_send_initial_metadata = DllImportsFromSharedLib_arm64.grpcsharp_call_send_initial_metadata; + this.grpcsharp_call_set_credentials = DllImportsFromSharedLib_arm64.grpcsharp_call_set_credentials; + this.grpcsharp_call_get_peer = DllImportsFromSharedLib_arm64.grpcsharp_call_get_peer; + this.grpcsharp_call_destroy = DllImportsFromSharedLib_arm64.grpcsharp_call_destroy; + this.grpcsharp_channel_args_create = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_create; + this.grpcsharp_channel_args_set_string = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_set_string; + this.grpcsharp_channel_args_set_integer = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_set_integer; + this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib_arm64.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib_arm64.grpcsharp_override_default_ssl_roots; + this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_ssl_credentials_create; + this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_composite_channel_credentials_create; + this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib_arm64.grpcsharp_channel_credentials_release; + this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib_arm64.grpcsharp_insecure_channel_create; + this.grpcsharp_secure_channel_create = DllImportsFromSharedLib_arm64.grpcsharp_secure_channel_create; + this.grpcsharp_channel_create_call = DllImportsFromSharedLib_arm64.grpcsharp_channel_create_call; + this.grpcsharp_channel_check_connectivity_state = DllImportsFromSharedLib_arm64.grpcsharp_channel_check_connectivity_state; + this.grpcsharp_channel_watch_connectivity_state = DllImportsFromSharedLib_arm64.grpcsharp_channel_watch_connectivity_state; + this.grpcsharp_channel_get_target = DllImportsFromSharedLib_arm64.grpcsharp_channel_get_target; + this.grpcsharp_channel_destroy = DllImportsFromSharedLib_arm64.grpcsharp_channel_destroy; + this.grpcsharp_sizeof_grpc_event = DllImportsFromSharedLib_arm64.grpcsharp_sizeof_grpc_event; + this.grpcsharp_completion_queue_create_async = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_create_async; + this.grpcsharp_completion_queue_create_sync = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_create_sync; + this.grpcsharp_completion_queue_shutdown = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_shutdown; + this.grpcsharp_completion_queue_next = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_next; + this.grpcsharp_completion_queue_pluck = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_pluck; + this.grpcsharp_completion_queue_destroy = DllImportsFromSharedLib_arm64.grpcsharp_completion_queue_destroy; + this.gprsharp_free = DllImportsFromSharedLib_arm64.gprsharp_free; + this.grpcsharp_metadata_array_create = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_create; + this.grpcsharp_metadata_array_add = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_add; + this.grpcsharp_metadata_array_count = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_count; + this.grpcsharp_metadata_array_get_key = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_get_key; + this.grpcsharp_metadata_array_get_value = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_get_value; + this.grpcsharp_metadata_array_destroy_full = DllImportsFromSharedLib_arm64.grpcsharp_metadata_array_destroy_full; + this.grpcsharp_redirect_log = DllImportsFromSharedLib_arm64.grpcsharp_redirect_log; + this.grpcsharp_native_callback_dispatcher_init = DllImportsFromSharedLib_arm64.grpcsharp_native_callback_dispatcher_init; + this.grpcsharp_metadata_credentials_create_from_plugin = DllImportsFromSharedLib_arm64.grpcsharp_metadata_credentials_create_from_plugin; + this.grpcsharp_metadata_credentials_notify_from_plugin = DllImportsFromSharedLib_arm64.grpcsharp_metadata_credentials_notify_from_plugin; + this.grpcsharp_ssl_server_credentials_create = DllImportsFromSharedLib_arm64.grpcsharp_ssl_server_credentials_create; + this.grpcsharp_server_credentials_release = DllImportsFromSharedLib_arm64.grpcsharp_server_credentials_release; + this.grpcsharp_server_create = DllImportsFromSharedLib_arm64.grpcsharp_server_create; + this.grpcsharp_server_register_completion_queue = DllImportsFromSharedLib_arm64.grpcsharp_server_register_completion_queue; + this.grpcsharp_server_add_insecure_http2_port = DllImportsFromSharedLib_arm64.grpcsharp_server_add_insecure_http2_port; + this.grpcsharp_server_add_secure_http2_port = DllImportsFromSharedLib_arm64.grpcsharp_server_add_secure_http2_port; + this.grpcsharp_server_start = DllImportsFromSharedLib_arm64.grpcsharp_server_start; + this.grpcsharp_server_request_call = DllImportsFromSharedLib_arm64.grpcsharp_server_request_call; + this.grpcsharp_server_cancel_all_calls = DllImportsFromSharedLib_arm64.grpcsharp_server_cancel_all_calls; + this.grpcsharp_server_shutdown_and_notify_callback = DllImportsFromSharedLib_arm64.grpcsharp_server_shutdown_and_notify_callback; + this.grpcsharp_server_destroy = DllImportsFromSharedLib_arm64.grpcsharp_server_destroy; + this.grpcsharp_call_auth_context = DllImportsFromSharedLib_arm64.grpcsharp_call_auth_context; + this.grpcsharp_auth_context_peer_identity_property_name = DllImportsFromSharedLib_arm64.grpcsharp_auth_context_peer_identity_property_name; + this.grpcsharp_auth_context_property_iterator = DllImportsFromSharedLib_arm64.grpcsharp_auth_context_property_iterator; + this.grpcsharp_auth_property_iterator_next = DllImportsFromSharedLib_arm64.grpcsharp_auth_property_iterator_next; + this.grpcsharp_auth_context_release = DllImportsFromSharedLib_arm64.grpcsharp_auth_context_release; + this.grpcsharp_slice_buffer_create = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_create; + this.grpcsharp_slice_buffer_adjust_tail_space = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_adjust_tail_space; + this.grpcsharp_slice_buffer_slice_count = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_slice_count; + this.grpcsharp_slice_buffer_slice_peek = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_slice_peek; + this.grpcsharp_slice_buffer_reset_and_unref = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_reset_and_unref; + this.grpcsharp_slice_buffer_destroy = DllImportsFromSharedLib_arm64.grpcsharp_slice_buffer_destroy; + this.gprsharp_now = DllImportsFromSharedLib_arm64.gprsharp_now; + this.gprsharp_inf_future = DllImportsFromSharedLib_arm64.gprsharp_inf_future; + this.gprsharp_inf_past = DllImportsFromSharedLib_arm64.gprsharp_inf_past; + this.gprsharp_convert_clock_type = DllImportsFromSharedLib_arm64.gprsharp_convert_clock_type; + this.gprsharp_sizeof_timespec = DllImportsFromSharedLib_arm64.gprsharp_sizeof_timespec; + this.grpcsharp_test_callback = DllImportsFromSharedLib_arm64.grpcsharp_test_callback; + this.grpcsharp_test_nop = DllImportsFromSharedLib_arm64.grpcsharp_test_nop; + this.grpcsharp_test_override_method = DllImportsFromSharedLib_arm64.grpcsharp_test_override_method; + this.grpcsharp_test_call_start_unary_echo = DllImportsFromSharedLib_arm64.grpcsharp_test_call_start_unary_echo; + } + public NativeMethods(DllImportsFromSharedLib_x86_dll unusedInstance) { this.grpcsharp_init = DllImportsFromSharedLib_x86_dll.grpcsharp_init; @@ -2288,6 +2396,326 @@ namespace Grpc.Core.Internal public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); } + /// + /// grpc_csharp_ext used as a shared library (with arm64 suffix) + /// + internal class DllImportsFromSharedLib_arm64 + { + private const string ImportName = "grpc_csharp_ext.arm64"; + + [DllImport(ImportName)] + public static extern void grpcsharp_init(); + + [DllImport(ImportName)] + public static extern void grpcsharp_shutdown(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_version_string(); + + [DllImport(ImportName)] + public static extern BatchContextSafeHandle grpcsharp_batch_context_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_initial_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_message_length(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_message_next_slice_peek(BatchContextSafeHandle ctx, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern StatusCode grpcsharp_batch_context_recv_status_on_client_status(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_details(BatchContextSafeHandle ctx, out UIntPtr detailsLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_error_string(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_batch_context_recv_status_on_client_trailing_metadata(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern int grpcsharp_batch_context_recv_close_on_server_cancelled(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_reset(BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_batch_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern RequestCallContextSafeHandle grpcsharp_request_call_context_create(); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_request_call_context_call(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_method(RequestCallContextSafeHandle ctx, out UIntPtr methodLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_host(RequestCallContextSafeHandle ctx, out UIntPtr hostLength); + + [DllImport(ImportName)] + public static extern Timespec grpcsharp_request_call_context_deadline(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_request_call_context_request_metadata(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_reset(RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_request_call_context_destroy(IntPtr ctx); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_composite_call_credentials_create(CallCredentialsSafeHandle creds1, CallCredentialsSafeHandle creds2); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_cancel_with_status(CallSafeHandle call, StatusCode status, string description); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_unary(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_client_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_server_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, int sendEmptyInitialMetadata); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, SliceBufferSafeHandle optionalSendBuffer, WriteFlags writeFlags); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_send_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_call_set_credentials(CallSafeHandle call, CallCredentialsSafeHandle credentials); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_call_get_peer(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_call_destroy(IntPtr call); + + [DllImport(ImportName)] + public static extern ChannelArgsSafeHandle grpcsharp_channel_args_create(UIntPtr numArgs); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_string(ChannelArgsSafeHandle args, UIntPtr index, string key, string value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_set_integer(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_args_destroy(IntPtr args); + + [DllImport(ImportName)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag); + + [DllImport(ImportName)] + public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_insecure_channel_create(string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern ChannelSafeHandle grpcsharp_secure_channel_create(ChannelCredentialsSafeHandle credentials, string target, ChannelArgsSafeHandle channelArgs); + + [DllImport(ImportName)] + public static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CallSafeHandle parentCall, ContextPropagationFlags propagationMask, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline); + + [DllImport(ImportName)] + public static extern ChannelState grpcsharp_channel_check_connectivity_state(ChannelSafeHandle channel, int tryToConnect); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_watch_connectivity_state(ChannelSafeHandle channel, ChannelState lastObservedState, Timespec deadline, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern CStringSafeHandle grpcsharp_channel_get_target(ChannelSafeHandle call); + + [DllImport(ImportName)] + public static extern void grpcsharp_channel_destroy(IntPtr channel); + + [DllImport(ImportName)] + public static extern int grpcsharp_sizeof_grpc_event(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_async(); + + [DllImport(ImportName)] + public static extern CompletionQueueSafeHandle grpcsharp_completion_queue_create_sync(); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_shutdown(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_next(CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern CompletionQueueEvent grpcsharp_completion_queue_pluck(CompletionQueueSafeHandle cq, IntPtr tag); + + [DllImport(ImportName)] + public static extern void grpcsharp_completion_queue_destroy(IntPtr cq); + + [DllImport(ImportName)] + public static extern void gprsharp_free(IntPtr ptr); + + [DllImport(ImportName)] + public static extern MetadataArraySafeHandle grpcsharp_metadata_array_create(UIntPtr capacity); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_add(MetadataArraySafeHandle array, string key, byte[] value, UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_metadata_array_count(IntPtr metadataArray); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_key(IntPtr metadataArray, UIntPtr index, out UIntPtr keyLength); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_metadata_array_get_value(IntPtr metadataArray, UIntPtr index, out UIntPtr valueLength); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_array_destroy_full(IntPtr array); + + [DllImport(ImportName)] + public static extern void grpcsharp_redirect_log(GprLogDelegate callback); + + [DllImport(ImportName)] + public static extern void grpcsharp_native_callback_dispatcher_init(NativeCallbackDispatcherCallback dispatcher); + + [DllImport(ImportName)] + public static extern CallCredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(IntPtr nativeCallbackTag); + + [DllImport(ImportName)] + public static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails); + + [DllImport(ImportName)] + public static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs, SslClientCertificateRequestType clientCertificateRequest); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_credentials_release(IntPtr credentials); + + [DllImport(ImportName)] + public static extern ServerSafeHandle grpcsharp_server_create(ChannelArgsSafeHandle args); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_register_completion_queue(ServerSafeHandle server, CompletionQueueSafeHandle cq); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_insecure_http2_port(ServerSafeHandle server, string addr); + + [DllImport(ImportName)] + public static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_start(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_server_request_call(ServerSafeHandle server, CompletionQueueSafeHandle cq, RequestCallContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_cancel_all_calls(ServerSafeHandle server); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_shutdown_and_notify_callback(ServerSafeHandle server, CompletionQueueSafeHandle cq, BatchContextSafeHandle ctx); + + [DllImport(ImportName)] + public static extern void grpcsharp_server_destroy(IntPtr server); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle grpcsharp_call_auth_context(CallSafeHandle call); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_context_peer_identity_property_name(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern AuthContextSafeHandle.NativeAuthPropertyIterator grpcsharp_auth_context_property_iterator(AuthContextSafeHandle authContext); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_auth_property_iterator_next(ref AuthContextSafeHandle.NativeAuthPropertyIterator iterator); + + [DllImport(ImportName)] + public static extern void grpcsharp_auth_context_release(IntPtr authContext); + + [DllImport(ImportName)] + public static extern SliceBufferSafeHandle grpcsharp_slice_buffer_create(); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_slice_buffer_adjust_tail_space(SliceBufferSafeHandle sliceBuffer, UIntPtr availableTailSpace, UIntPtr requestedTailSpace); + + [DllImport(ImportName)] + public static extern UIntPtr grpcsharp_slice_buffer_slice_count(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_slice_peek(SliceBufferSafeHandle sliceBuffer, UIntPtr index, out UIntPtr sliceLen, out IntPtr sliceDataPtr); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_reset_and_unref(SliceBufferSafeHandle sliceBuffer); + + [DllImport(ImportName)] + public static extern void grpcsharp_slice_buffer_destroy(IntPtr sliceBuffer); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_now(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_future(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_inf_past(ClockType clockType); + + [DllImport(ImportName)] + public static extern Timespec gprsharp_convert_clock_type(Timespec t, ClockType targetClock); + + [DllImport(ImportName)] + public static extern int gprsharp_sizeof_timespec(); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_callback([MarshalAs(UnmanagedType.FunctionPtr)] NativeCallbackTestDelegate callback); + + [DllImport(ImportName)] + public static extern IntPtr grpcsharp_test_nop(IntPtr ptr); + + [DllImport(ImportName)] + public static extern void grpcsharp_test_override_method(string methodName, string variant); + + [DllImport(ImportName)] + public static extern CallError grpcsharp_test_call_start_unary_echo(CallSafeHandle call, BatchContextSafeHandle ctx, SliceBufferSafeHandle sendBuffer, WriteFlags writeFlags, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags); + } + /// /// grpc_csharp_ext used as a shared library (with x86.dll suffix) /// diff --git a/src/csharp/Grpc.Core/Internal/PlatformApis.cs b/src/csharp/Grpc.Core/Internal/PlatformApis.cs index ee08c3ca214..5ad443b51b4 100644 --- a/src/csharp/Grpc.Core/Internal/PlatformApis.cs +++ b/src/csharp/Grpc.Core/Internal/PlatformApis.cs @@ -47,6 +47,8 @@ namespace Grpc.Core.Internal static readonly bool isMono; static readonly bool isNet5OrHigher; static readonly bool isNetCore; + static readonly string frameworkDescription; + static readonly string clrVersion; static readonly string unityApplicationPlatform; static readonly bool isXamarin; static readonly bool isXamarinIOS; @@ -54,27 +56,28 @@ namespace Grpc.Core.Internal static PlatformApis() { -#if NETSTANDARD - isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); - isMacOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); - isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); -#if NETSTANDARD2_0 - isNet5OrHigher = Environment.Version.Major >= 5; -#else - // assume that on .NET 5+, the netstandard2.0 TFM is going to be selected. + // Detect OS + var osKind = CommonPlatformDetection.GetOSKind(); + isLinux = osKind == CommonPlatformDetection.OSKind.Linux; + isMacOSX = osKind == CommonPlatformDetection.OSKind.MacOSX; + isWindows = osKind == CommonPlatformDetection.OSKind.Windows; + +#if NETSTANDARD1_5 + // assume that on .NET 5+, the netstandard2.0 or newer TFM is always going to be selected + // so for netstandard1.5 we assume we are never on .NET5+ isNet5OrHigher = false; -#endif + isNetCore = isNet5OrHigher || RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"); +#elif NETSTANDARD + isNet5OrHigher = Environment.Version.Major >= 5; isNetCore = isNet5OrHigher || RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"); #else - var platform = Environment.OSVersion.Platform; - - // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname. - isMacOSX = (platform == PlatformID.Unix && GetUname() == "Darwin"); - isLinux = (platform == PlatformID.Unix && !isMacOSX); - isWindows = (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows); isNet5OrHigher = false; isNetCore = false; #endif + frameworkDescription = TryGetFrameworkDescription(); + clrVersion = TryGetClrVersion(); + + // Detect mono runtime isMono = Type.GetType("Mono.Runtime") != null; // Unity @@ -125,6 +128,18 @@ namespace Grpc.Core.Internal /// public static bool IsNet5OrHigher => isNet5OrHigher; + /// + /// Contains RuntimeInformation.FrameworkDescription if the property is available on current TFM. + /// null otherwise. + /// + public static string FrameworkDescription => frameworkDescription; + + /// + /// Contains the version of common language runtime obtained from Environment.Version + /// if the property is available on current TFM. null otherwise. + /// + public static string ClrVersion => clrVersion; + /// /// true if running on .NET Core (CoreCLR) or NET 5+, false otherwise. /// @@ -132,6 +147,8 @@ namespace Grpc.Core.Internal public static bool Is64Bit => IntPtr.Size == 8; + public static CommonPlatformDetection.CpuArchitecture ProcessArchitecture => CommonPlatformDetection.GetProcessArchitecture(); + /// /// Returns UnityEngine.Application.platform as a string. /// See https://docs.unity3d.com/ScriptReference/Application-platform.html for possible values. @@ -183,31 +200,54 @@ namespace Grpc.Core.Internal } } - [DllImport("libc")] - static extern int uname(IntPtr buf); + /// + /// Returns description of the framework this process is running on. + /// Value is based on RuntimeInformation.FrameworkDescription. + /// + static string TryGetFrameworkDescription() + { +#if NETSTANDARD + return RuntimeInformation.FrameworkDescription; +#else + // on full .NET framework we are targeting net45, and the property is only available starting from .NET Framework 4.7.1+ + // try obtaining the value by reflection since we might be running on a newer framework even though we're targeting + // an older one. + var runtimeInformationClass = Type.GetType("System.Runtime.InteropServices.RuntimeInformation"); + var frameworkDescriptionProperty = runtimeInformationClass?.GetTypeInfo().GetProperty("FrameworkDescription", BindingFlags.Static | BindingFlags.Public); + return frameworkDescriptionProperty?.GetValue(null)?.ToString(); +#endif + } + + /// + /// Returns version of the common language runtime this process is running on. + /// Value is based on Environment.Version. + /// + static string TryGetClrVersion() + { +#if NETSTANDARD1_5 + return null; +#else + return Environment.Version.ToString(); +#endif + } - static string GetUname() + /// + /// Returns the TFM of the Grpc.Core assembly. + /// + public static string GetGrpcCoreTargetFrameworkMoniker() { - var buffer = Marshal.AllocHGlobal(8192); - try - { - if (uname(buffer) == 0) - { - return Marshal.PtrToStringAnsi(buffer); - } - return string.Empty; - } - catch - { - return string.Empty; - } - finally - { - if (buffer != IntPtr.Zero) - { - Marshal.FreeHGlobal(buffer); - } - } +#if NETSTANDARD1_5 + return "netstandard1.5"; +#elif NETSTANDARD2_0 + return "netstandard2.0"; +#elif NET45 + return "net45"; +#else + // The TFM is determined at compile time. + // The is intentionally no "default" return clause here so that + // if the set of TFMs we build for changes and this method is not updated accordingly, + // it will result in compilation error. +#endif } } } diff --git a/src/csharp/Grpc.Core/Internal/UserAgentStringProvider.cs b/src/csharp/Grpc.Core/Internal/UserAgentStringProvider.cs new file mode 100644 index 00000000000..01f158509ff --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/UserAgentStringProvider.cs @@ -0,0 +1,108 @@ +#region Copyright notice and license + +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#endregion + +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace Grpc.Core.Internal +{ + /// + /// Helps constructing the grpc-csharp component of the user agent string. + /// + internal class UserAgentStringProvider + { + static readonly UserAgentStringProvider defaultInstance; + readonly string userAgentString; + + static UserAgentStringProvider() + { + defaultInstance = new UserAgentStringProvider(VersionInfo.CurrentVersion, PlatformApis.FrameworkDescription, PlatformApis.ClrVersion, PlatformApis.GetGrpcCoreTargetFrameworkMoniker(), PlatformApis.ProcessArchitecture); + } + + public static UserAgentStringProvider DefaultInstance => defaultInstance; + + public string GrpcCsharpUserAgentString => userAgentString; + + public UserAgentStringProvider(string grpcCsharpVersion, string frameworkDescription, string clrVersion, string tfm, CommonPlatformDetection.CpuArchitecture arch) + { + var detailComponents = new List(); + + string sanitizedFrameworkDescription = SanitizeFrameworkDescription(frameworkDescription); + if (sanitizedFrameworkDescription != null) + { + detailComponents.Add(sanitizedFrameworkDescription); + } + + if (clrVersion != null) + { + detailComponents.Add($"CLR {clrVersion}"); + } + + if (tfm != null) + { + detailComponents.Add(tfm); + } + + string architectureString = TryGetArchitectureString(arch); + if (architectureString != null) + { + detailComponents.Add(architectureString); + } + + // TODO(jtattermusch): consider adding details about running under unity / xamarin etc. + var details = string.Join("; ", detailComponents); + userAgentString = $"grpc-csharp/{grpcCsharpVersion} ({details})"; + } + + static string TryGetArchitectureString(CommonPlatformDetection.CpuArchitecture arch) + { + if (arch == CommonPlatformDetection.CpuArchitecture.Unknown) + { + return null; + } + return arch.ToString().ToLowerInvariant(); + } + + static string SanitizeFrameworkDescription(string frameworkDescription) + { + if (frameworkDescription == null) + { + return null; + } + + // Some platforms return more details in the FrameworkDescription string than we want. + // e.g. on mono, we will get something like "Mono 6.12.0.93 (2020-02/620cf538206 Tue Aug 25 14:04:52 EDT 2020)" + // For user agent string, we only want basic info on framework name and its version. + var parts = new List(frameworkDescription.Split(' ')); + + int i = 0; + for (; i < parts.Count; i++) + { + var part = parts[i]; + if (!Regex.IsMatch(part, @"^[-.,+@A-Za-z0-9]*$")) + { + // stop once we find first part that's not framework name or version + break; + } + } + + var result = string.Join(" ", parts.GetRange(0, i)); + return !string.IsNullOrEmpty(result) ? result : null; + } + } +} diff --git a/src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs b/src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs index 54723b74fcb..e98f6e93fa3 100644 --- a/src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs +++ b/src/csharp/Grpc.Tools.Tests/ProtoToolsPlatformTaskTest.cs @@ -67,6 +67,25 @@ namespace Grpc.Tools.Tests } } + [Test] + public void CpuIsArm64() + { + if (RuntimeInformation.OSArchitecture == Architecture.Arm64) + { + _cpuMatched++; + + // On macosx arm64, x64 is used until a native protoc is shipped + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Assert.AreEqual("x64", _task.Cpu); + } + else + { + Assert.AreEqual("arm64", _task.Cpu); + } + } + } + [Test] public void OsIsWindows() { diff --git a/src/csharp/Grpc.Tools/Common.cs b/src/csharp/Grpc.Tools/Common.cs index f7ea13c9df9..90624d6c186 100644 --- a/src/csharp/Grpc.Tools/Common.cs +++ b/src/csharp/Grpc.Tools/Common.cs @@ -21,6 +21,7 @@ using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; +using Grpc.Core.Internal; namespace Grpc.Tools { @@ -39,80 +40,14 @@ namespace Grpc.Tools // A few flags used to control the behavior under various platforms. internal static class Platform { - public enum OsKind { Unknown, Windows, Linux, MacOsX }; - public static readonly OsKind Os; + public static readonly CommonPlatformDetection.OSKind Os = CommonPlatformDetection.GetOSKind(); - public enum CpuKind { Unknown, X86, X64 }; - public static readonly CpuKind Cpu; + public static readonly CommonPlatformDetection.CpuArchitecture Cpu = CommonPlatformDetection.GetProcessArchitecture(); // This is not necessarily true, but good enough. BCL lacks a per-FS // API to determine file case sensitivity. - public static bool IsFsCaseInsensitive => Os == OsKind.Windows; - public static bool IsWindows => Os == OsKind.Windows; - - static Platform() - { -#if NETCORE - Os = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? OsKind.Windows - : RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? OsKind.Linux - : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? OsKind.MacOsX - : OsKind.Unknown; - - switch (RuntimeInformation.ProcessArchitecture) - { - case Architecture.X86: Cpu = CpuKind.X86; break; - case Architecture.X64: Cpu = CpuKind.X64; break; - // We do not have build tools for other architectures. - default: Cpu = CpuKind.Unknown; break; - } -#else - // Using the same best-effort detection logic as Grpc.Core/PlatformApis.cs - var platform = Environment.OSVersion.Platform; - if (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows) - { - Os = OsKind.Windows; - } - else if (platform == PlatformID.Unix && GetUname() == "Darwin") - { - Os = OsKind.MacOsX; - } - else - { - Os = OsKind.Linux; - } - - // Hope we are not building on ARM under Xamarin! - Cpu = Environment.Is64BitProcess ? CpuKind.X64 : CpuKind.X86; -#endif - } - - [DllImport("libc")] - static extern int uname(IntPtr buf); - - // This code is copied from Grpc.Core/PlatformApis.cs - static string GetUname() - { - var buffer = Marshal.AllocHGlobal(8192); - try - { - if (uname(buffer) == 0) - { - return Marshal.PtrToStringAnsi(buffer); - } - return string.Empty; - } - catch - { - return string.Empty; - } - finally - { - if (buffer != IntPtr.Zero) - { - Marshal.FreeHGlobal(buffer); - } - } - } + public static bool IsFsCaseInsensitive => Os == CommonPlatformDetection.OSKind.Windows; + public static bool IsWindows => Os == CommonPlatformDetection.OSKind.Windows; }; // Exception handling helpers. diff --git a/src/csharp/Grpc.Tools/Grpc.Tools.csproj b/src/csharp/Grpc.Tools/Grpc.Tools.csproj index 752d8651bbb..13e0014dbe0 100644 --- a/src/csharp/Grpc.Tools/Grpc.Tools.csproj +++ b/src/csharp/Grpc.Tools/Grpc.Tools.csproj @@ -47,6 +47,11 @@ Linux and MacOS. Managed runtime is supplied separately in the Grpc.Core package gRPC RPC HTTP/2 + + + + + @@ -62,6 +67,7 @@ Linux and MacOS. Managed runtime is supplied separately in the Grpc.Core package <_Asset PackagePath="tools/windows_x64/" Include="$(Assets_ProtoCompiler)windows_x64/protoc.exe" /> <_Asset PackagePath="tools/linux_x86/" Include="$(Assets_ProtoCompiler)linux_x86/protoc" /> <_Asset PackagePath="tools/linux_x64/" Include="$(Assets_ProtoCompiler)linux_x64/protoc" /> + <_Asset PackagePath="tools/linux_arm64/" Include="$(Assets_ProtoCompiler)linux_aarch64/protoc" /> <_Asset PackagePath="tools/macosx_x64/" Include="$(Assets_ProtoCompiler)macos_x64/protoc" /> @@ -69,6 +75,7 @@ Linux and MacOS. Managed runtime is supplied separately in the Grpc.Core package <_Asset PackagePath="tools/windows_x64/" Include="$(Assets_GrpcPlugins)protoc_windows_x64/grpc_csharp_plugin.exe" /> <_Asset PackagePath="tools/linux_x86/" Include="$(Assets_GrpcPlugins)protoc_linux_x86/grpc_csharp_plugin" /> <_Asset PackagePath="tools/linux_x64/" Include="$(Assets_GrpcPlugins)protoc_linux_x64/grpc_csharp_plugin" /> + <_Asset PackagePath="tools/linux_arm64/" Include="$(Assets_GrpcPlugins)protoc_linux_aarch64/grpc_csharp_plugin" /> <_Asset PackagePath="tools/macosx_x64/" Include="$(Assets_GrpcPlugins)protoc_macos_x64/grpc_csharp_plugin" /> diff --git a/src/csharp/Grpc.Tools/ProtoToolsPlatform.cs b/src/csharp/Grpc.Tools/ProtoToolsPlatform.cs index aed8a66339b..2bccb0c3ba9 100644 --- a/src/csharp/Grpc.Tools/ProtoToolsPlatform.cs +++ b/src/csharp/Grpc.Tools/ProtoToolsPlatform.cs @@ -18,6 +18,7 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; +using Grpc.Core.Internal; namespace Grpc.Tools { @@ -34,7 +35,7 @@ namespace Grpc.Tools public string Os { get; set; } /// - /// Return one of 'x64' or 'x86'. + /// Return one of 'x64', 'x86', 'arm64'. /// If the CPU is unknown, the property is not set. /// [Output] @@ -45,18 +46,26 @@ namespace Grpc.Tools { switch (Platform.Os) { - case Platform.OsKind.Linux: Os = "linux"; break; - case Platform.OsKind.MacOsX: Os = "macosx"; break; - case Platform.OsKind.Windows: Os = "windows"; break; + case CommonPlatformDetection.OSKind.Linux: Os = "linux"; break; + case CommonPlatformDetection.OSKind.MacOSX: Os = "macosx"; break; + case CommonPlatformDetection.OSKind.Windows: Os = "windows"; break; default: Os = ""; break; } switch (Platform.Cpu) { - case Platform.CpuKind.X86: Cpu = "x86"; break; - case Platform.CpuKind.X64: Cpu = "x64"; break; + case CommonPlatformDetection.CpuArchitecture.X86: Cpu = "x86"; break; + case CommonPlatformDetection.CpuArchitecture.X64: Cpu = "x64"; break; + case CommonPlatformDetection.CpuArchitecture.Arm64: Cpu = "arm64"; break; default: Cpu = ""; break; } + + // Use x64 on macosx arm64 until a native protoc is shipped + if (Os == "macosx" && Cpu == "arm64") + { + Cpu = "x64"; + } + return true; } }; diff --git a/src/csharp/Grpc.Tools/build/_protobuf/Google.Protobuf.Tools.targets b/src/csharp/Grpc.Tools/build/_protobuf/Google.Protobuf.Tools.targets index f06186896e1..c3970cde93d 100644 --- a/src/csharp/Grpc.Tools/build/_protobuf/Google.Protobuf.Tools.targets +++ b/src/csharp/Grpc.Tools/build/_protobuf/Google.Protobuf.Tools.targets @@ -83,7 +83,7 @@ + Text="Google.Protobuf.Tools cannot determine host OS and CPU. Use environment variables PROTOBUF_TOOLS_OS={linux|macosx|windows} and PROTOBUF_TOOLS_CPU={x86|x64|arm64} to try the closest match to your system. You may also set PROTOBUF_PROTOC to specify full path to the host-provided compiler (v3.5+ is required)." /> - 2.37.0-dev - 3.15.2 + 2.38.0-dev + 3.15.8 diff --git a/src/csharp/tests.json b/src/csharp/tests.json index 108911b74bb..4b0018e2489 100644 --- a/src/csharp/tests.json +++ b/src/csharp/tests.json @@ -17,6 +17,7 @@ "Grpc.Core.Internal.Tests.SliceBufferSafeHandleTest", "Grpc.Core.Internal.Tests.SliceTest", "Grpc.Core.Internal.Tests.TimespecTest", + "Grpc.Core.Internal.Tests.UserAgentStringProviderTest", "Grpc.Core.Internal.Tests.WellKnownStringsTest", "Grpc.Core.Tests.AppDomainUnloadTest", "Grpc.Core.Tests.AuthContextTest", diff --git a/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec index 28c9d9e1a58..b172cf8543d 100644 --- a/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCCppPlugin' - v = '1.37.0-dev' + v = '1.38.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates C++ files from .proto services.' s.description = <<-DESC @@ -100,7 +100,7 @@ Pod::Spec.new do |s| s.preserve_paths = plugin # Restrict the protoc version to the one supported by this plugin. - s.dependency '!ProtoCompiler', '3.15.2' + s.dependency '!ProtoCompiler', '3.15.8' # For the Protobuf dependency not to complain: s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' diff --git a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec index 65f201961c0..a810b01b1c2 100644 --- a/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +++ b/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec @@ -42,7 +42,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler-gRPCPlugin' - v = '1.37.0-dev' + v = '1.38.0-dev' s.version = v s.summary = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.' s.description = <<-DESC @@ -102,7 +102,7 @@ Pod::Spec.new do |s| s.preserve_paths = plugin # Restrict the protoc version to the one supported by this plugin. - s.dependency '!ProtoCompiler', '3.15.2' + s.dependency '!ProtoCompiler', '3.15.8' # For the Protobuf dependency not to complain: s.ios.deployment_target = '9.0' s.osx.deployment_target = '10.10' diff --git a/src/objective-c/!ProtoCompiler.podspec b/src/objective-c/!ProtoCompiler.podspec index e6db8f7ac24..0a86fe7421e 100644 --- a/src/objective-c/!ProtoCompiler.podspec +++ b/src/objective-c/!ProtoCompiler.podspec @@ -36,7 +36,7 @@ Pod::Spec.new do |s| # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed # before them. s.name = '!ProtoCompiler' - v = '3.15.2' + v = '3.15.8' s.version = v s.summary = 'The Protobuf Compiler (protoc) generates Objective-C files from .proto files' s.description = <<-DESC diff --git a/src/objective-c/BoringSSL-GRPC.podspec b/src/objective-c/BoringSSL-GRPC.podspec index 2ceadbc729f..f2ef17d0f7a 100644 --- a/src/objective-c/BoringSSL-GRPC.podspec +++ b/src/objective-c/BoringSSL-GRPC.podspec @@ -39,7 +39,7 @@ Pod::Spec.new do |s| s.name = 'BoringSSL-GRPC' - version = '0.0.17' + version = '0.0.18' s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' # Adapted from the homepage: @@ -76,7 +76,7 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/google/boringssl.git', - :commit => "1a7359455220f7010def8c63f7c7e041ce6707c6", + :commit => "688fc5cf5428868679d2ae1072cad81055752068", } s.ios.deployment_target = '9.0' @@ -213,494 +213,496 @@ Pod::Spec.new do |s| # /src/boringssl/boringssl_prefix_symbols.h. Here we decode the content and inject the header to # the correct location in BoringSSL. base64 -D < src/include/openssl/boringssl_prefix_symbols.h - H4sICAAAAAAC/2JvcmluZ3NzbF9wcmVmaXhfc3ltYm9scy5oAKy9XXPbuJaofT+/wnXm5pyqXTOx0+72 - fu8UW+lo2rE9ktzTmRsWJVE2dyhSISg77l//AiAl4mMtkGvBVbtmOpaeZ1EgvgkC//mfZ09ZmdVpk23O - Vm+nfySrqs7LJyGKZF9n2/xn8pylm6z+D/F8VpVnn/Sni8Xt2bra7fLm/zs7T3/7ePnPXy4vLy4+bH/7 - cP5hk22v1r9+3P62/i378Mv5Ovv1tw+/rX/9t3/7z/88u672b3X+9Nyc/d/1/zu7+HB+9Y+z36vqqcjO - ZuX6P+RX1LcesnqXC5HLeE11dhDZP2S0/ds/znbVJt/K/5+Wm/+s6rNNLpo6Xx2a7Kx5zsWZqLbNa1pn - Z1v5YVq+Kdf+UO8rkZ295o38AbX+/9WhOdtm2ZlEnrM6U7++TkuZEP8429fVS76RSdI8p438P9lZuqpe - MmVan669rJp8namraOPu++s9frTfZ2l9lpdnaVEoMs/E8dctv0zPFvefl/8zmU/PZouzh/n9n7Ob6c3Z - /5ks5L//z9nk7kZ/afK4/HI/P7uZLa5vJ7Ovi7PJ7e2ZpOaTu+VsulCu/5ktv5zNp79P5hK5l5T09e67 - 69vHm9nd7xqcfX24nckoveDs/rNyfJ3Or7/Iv0w+zW5ny286/OfZ8m66WPyHdJzd3Z9N/5zeLc8WX5TH - uLJP07Pb2eTT7fTss/zX5O6b0i0eptezye0/5HXPp9fLf0jF8b/kl67v7xbT/36UOvmds5vJ18nv6kI0 - ffyn/mFfJsvFvYw7lz9v8Xi7VD/j8/z+69nt/UJd+dnjYipjTJYTRcs0lJe8+IfkpvIC5+q6J/J/18vZ - /Z3ySUCGXs4n6jrupr/fzn6f3l1PFXuvgeX9XH73cdEx/zibzGcLFfT+canoe+XUWfj+7m6qv9OmvkoP - eS36KqZzmRBfJ1r82b4b/6Hz/6f7uXTK4pNMbm6Sh/n08+yvs30qmkycNa/Vmcx6ZZNv86wWMvPIzF+V - mbwJjcpiMlPvhPqDEuWNKq0qx1Xbs126rquz7Oc+LXUmlP/LG3GW1k+HnfSJs1Um4UwHkqX3P/7t32UZ - zcsMvJz/m/7jbPX/wI+Smfzp8/YLQYf5xbP07N///SxR/2f1bz01u0+2iaxl4Gvo/9j+4R898P8sh8ga - qqVDes/N8naRrItcJlWyy2T1sBmr80nHytCBHpHVL1nN0VmkY1V1YbI6bLcyu3HcAG9HeDlPLvgp69OA - nalFfeyU9mnPHpMS4XR4knm6yXeZatloXoP0rM+yhSsyptiGPTcrEZBfH3PPwndM1RV5mTd5Whx/SbI5 - dDUvNRCu6uNO5/OkqNJNogyqdyO7YmMDQWxvvn+Y3qkP1DVQqkyX640P069JnXXxFrK7oNrEkVaIBcyr - vIqyO7wd4bWWrShX78GQO+LyQUEfQ/3xevYgey7JJhPrOt9TsiRMg3ZVP6QHWc+X+YahN3HUv1K9FZ5b - oah3ne9l/z7iynsBGmOTP2WiiYjRC9AYbHfA+f1nUqa7jCnu6KCdfdUtjLp36c9EVtmCl98dAx4lL2Oj - 9AY0SsQtCKb/vt5G3ICODtirplpXRRIR4WRAo9TbdUz6HHHU/5IWB65cs7g5Kt+E8kwuklS2awxzR2LW - VVGtv3f1Hc9uGsAoopE9wrTecG+qxTsR7r8+JOlmk6yr3b7O9FQMsTs4oAHibessA74pyBExERBT5o8P - 9PSzSNj6Lj8E8SAR8w0rQL5BfNxkgVJl+ZfKBx+S9XMqa/F1Vjcks4+D/vM4//mQX39i3ZG0eGIEAj1I - xHaYej1hhTnCsDv72dRpXJJ5DjiSaH8mJ0CH+t71cybrx32dv6hZ9u/ZG9XuCYAYbX9V/ranujrsyRFs - HPAXWVobqSfIEVwBFsO9T8xIngaLt6s2GS+EIjFrpcdVzGvvYN+dlemqyJJqLfaqUdwXcqBPDQE50Egi - fyqzrhZQUxcS2O0FMyQsQ2M3hVD3rywzcncTk/ixtsVBPB+LLvmH2TRgl+072SkZ36QbcZVy+TZfy1qA - anV5LIIqLzy3IkNWXmF2eSTCPq3THcutScza1riMGtvBQX9bEESjns/Q9QaN2E+5PlmvWAFMARJDNxuC - ZW9RxHvsDiRFLhqW3jLAUeSf0kMhh6SpEK/cVPIkI2MlB5HVm7RJ3yXoyQZHz34m3FAdinrL7FV2GzbZ - T6b8xGMRInsDoASOlZfbKlmnRbFK1985cSwBHENWBkX1FBXFUcBx1ESXriG4BcgS4DH0dA5r2gOTILHk - rYuP5UqQWIwe4ZGDjczeoIHC3h+HXD3Sfj40m+qVlSS2AY6in6ekz9TZJ4+G7V3vSeZnOcxhp71vgaMR - n2gCKOIthKxl5HfW39siyrrZvgWOJrNvvn2LqkUcRTDOJts3zxFBNB+MwL3tBu779RPR7htFtU5ZZRCU - +LHKTI5smt0+mS/IEyAmC5lf6cJX31Nnu+ol405w2LRvVx8k6Xot7zRVbaBBb/JUVZsIuebDEeqszJ6q - JmcMsBANEq+tpraHomDF6XHMv0qec3pnyWQxcyUHBWveTe7YsJl/m03BQIzYGw14kIh6MKJvl8j/5gWz - FYE4+osrdowWD/hVXz3C3+IBf1fJRIQ4GZAo7EIRKBFqAXDGs7Yo4i0PuxXxkZyNIl4RnyPFmBwp4nKk - GMqRIi5HiqEcKaJzpBiRI7teJS//HGHI3XzoFmgm+6piNDM2j0RgzReKwHxh+9lx8kbw1Ccc8R/7vuz5 - N9gCRjtnp9F5II3kZ4f6hVPrnNCglzVt4PJIBNZcbU8iVpE/pcUTL0E6NmzmJ4kpQGLEPesAFEic98j5 - 5yNzfiKHltVrcii/l9WrenC872ZfODcJl2GxI6ON8YusUJ1ATuvgGuAo7dN3lr5DA17u/R+87/rzyCkK - zINE1FO7abnhPF33BGgM/vMUMfw8RfSrTpk1jYkj/qjnKmLEcxXjOzGZ1zIgUQ51rb6k+kDcMLYCiyOz - +q7Lh7wohgCOEf0kSox7EiXe9UmUID6JMr/fFet92jyLmLimB4lYCV2Ty3pWTxDz0taVwLGytC7e9POy - bv0BpykHLEg03lM9EXqqpz7cpoXI1NqQumt2s03SvTyrWy1OwCEnfCVPdZZKLCItbQMcJX8qZVumOlDn - HxP1GOSpTjeslhE2IVFjnjaK4aeNIv5poxjztFHEPm0Uw08bxXs8bRTjnjYevyYy2RvY1umTepGWG8uS - ILFin2yKcU82BfPJpkCfbOpPRFz2MvnhCElaP8VGUQ44UqmevbWpGNWzhzxDEUWSbl7U8iyRbaLDOjI4 - tl4AWGdiX5WClSksARKD99xbhJ57C/0SyWkpLGexP2pBoonvpx5pRFYHNHi87uXU2HiOBonXbZTBidGi - sPfHIV9H3B4DR/0Rqx/EiNUPImr1gxhY/dB+3qiRZ1XKHp94Ti8uf02qrTn+EbyoQ1bsarr+tOzjypJ9 - 2GW86K4FjnasHPtVqcyaDxRhMWNXm4iRq03M76khf1U2soKOidZbwtFUwd88Z9y1LgEVEhda183uCuI2 - PHpePqkXU6pajih2evciwQ0NqJC4dbNXze02LzJeNFOAxGjqfB09LeRb4GjdsiP1smBEte1bsGjs3BnM - jfY8eMzYETahUVX3q21v1Wtl3K4qKBobM6a7gNvC0Zu0OYjYX3uSjInFayRcRzBSvwIvLprlGRlRvEs8 - EYx2UJMxsv6JCHVUIHFknb15Zuk1GbLGZXNbgcfJ1vzrVyxurkXKFUs06I1OGtOBRKoPvGZIg7CTP7ke - mlXveqHv0DGATcGorDWzYnDN7EENubdUb0sBNlmGH9pR8B/0B2c2PWRPJou787gQWjEYR/WnIuMoBRxn - vpjEJZglGBGDnWy+ZUw0buL5FjhaxCuMDj7oZ6ec6xiO1D4+5qYdbBqO+h7x8Ehq6NduStm8Jc85fQ4c - lNixus2tErXB6ulxUP/4ixJxQAXHNZ60rdO96t5zQvoWOBr1bWCTw4zVLlm9NbQBqE/D9vbdW/LGMAAe - 8POmRhBFIA57uhu3BKLts4g0U/CA2yzDIiqQZRqK2s4lxsVrHYFI7zOdNFIZuI52LMWO2eKon/P0HsCD - fta7uZgDj0RbsGiTuHWn9kauqQu6YAMe5bQdGePha8iDR+yG6EW+zfS6I2rTOuQKRd5l/Ei7LGwmzuUB - OO6PvDnBe/KcitjKzVHgcfhVSk/D9ly0j1q4fRiThyMQ30M0MNinVxLzqo4ODXpjehWOAo0TU4eLoTpc - vFPtJEbXTv3sPTdOKIeKiBpIBGsgEVcDiaEaSMixRLFJVuptp/KpyNTIhhUI8MARm4rfqz+yYXOyreqI - mw1o4Hj0+SqbtK30F4yh94oj9vcL7u0Xsa9fcE8/tblcut8Xefv2ucqwDWV38JDDj8Taxy+wh5/6SM0y - dK8NHFb/ytaNUDlI9sJpE9UDKiduob6kNrnudkQnRXLhAXdSVJEBtAGKokfp3aSwaqKLhh7Hd0CRmrd9 - xk4rAx5wM9PKNdhR2pUYzzkpcU6Q41ILZNqt+Ei2HnN8Mfs/Duz9SL9K4Ppi9nYc2NeRt8citr8ie2/F - wL6KjA0NwH0M1oemea6rw9Oz3i+1yGgz3ABu+zdZkT2pM7uSdZ3pKdW0UD0IUg8alTixKn2IhxzOfCf9 - CJNzjLI5Z7x2ZGC2r51zPa3pXTc/1S5fmT4FSY35KEGGXFBkPdvbdi5odwDAUb96d0G11eQqGXM4kSJ3 - Ex3eSfTddhEl7CAavXvoiJ1Ds7qW/V7m8Rse7Lh/7qtaL+FQLd1OFtZaFlJSANBgR6E+i/CfQZyODVSL - W/QW8BSfT7v25oP5iiytkPk0YDcfg6nOhSBH8AxQFF6zGt73tN3SvX/N4LQJDT2VQAsQjf38ZOi5CW// - Vmzv1v45Q+yIKWzConKfy4x5HtN/p2vGu/3Y2zUpzHCgCovrroNhxvQ0QLzuzYU6+3GQ1bys9Im7gaAS - MFbMMm1EAcV5lydbpCdaT3oDCvqebybnGZPuET9ReMR8H3NViIMC3nbJ8+qNfuQLgKN+xh3EV2Mz91VG - 91SO2095aC9l4/Na9vyrHVPewoC7e0WfvgzBpwP2/oALdohegcfpD2plRjkJwBgvGbGra3KYkXq4ik36 - 1uOb+4wZewD3/d7YhxrBEwAxVBee7FUQ4KI/Q0Kf/xsfJH9dfvhnsljez6d6NVa++ckMAZjAqKzVBuFV - Bt3m3TuRiMNeDWroagP23VtyadkC5UT+IxfPGd3Vcb6RvTfAwC7k+uMXcrsiEd9zGrglRUYuYxbsu9n7 - CQzsXB69a/mIHcujdysfsVM5Z5dyeIfydl/O47gvaarvWZmsZFFUUwecUdmAzY/OmM1F90XXK3GOgyj6 - xnsAHvAzO6wuj0TgVioWjLkPRRGbRI4DiaTf4W5k507oKSmdBQQrHmhCoqrBUdoc6qwfYrJiAh4oYpu9 - eT1UmwbsrCNobBKwGsuyyV6DDZvJS9tAgR+D/97/0IkHegvhVV5RnYoBTKydA0JnJpw+E2pGo1xnLPER - Btz0DlEN9YhEtlalpt8dW0+d8bpwIRcUuZ3vtd6upocEJFCsdnaJNe61YNStXsljlH2bxuyckV1Phqx6 - Npyv1jjkZ43Q0Vks8ZzWag6NN9li06idsS+tT0N2Xu2H13tAY9edUE6OgZrGRVWDA1YGCrjGRWaVCMQD - ROTuGPEU3i3CWAmePmWJ+E5bqQvggJ/9ONWnYfuhzH/Qp2h7ErQab/yfHkExQkCaoXicHOwb/CgRG+sO - nvsTc+ZP+LyfiLN+guf8GB/SF8d5MOjmtDnoqP2V0bt8BXuXr/S+2ivUV3uVVVbG7lDatG1X7yzEPoXF - HHakvGS+NWqBntPYtJQoNUjPKsfmVJ1CHI9INrK2IHlaxPMoOWu6wWU9c9ujIypbyHcBzazarGIvqIkQ - MHlRI/aE9Wnfbs2P8RZxBDR2PNUTOuw3xBmrnrJtRb6q0/qNnJlNzjGqg9b6R43UcRuAA/527VW7GE6Q - 9RZt23fpU74+zeactk9rSLkflbix1MayaZFUsqBQpxc82HZzz7HDz7AjvjfmvS9WHnb24J9033zatu+z - jNSFUt93Dfp20SQacTx1tVZn+uiJzn0lGt4S3IAGjtdWUuoB3DHD0V8LGnJ5kV/yTdZeIrXF9mDb3W4a - KvP46Vcn2yJ/em6oT6mCIiCmnlkrspesIEfpUcDbdrB4YoO1zTWx0qi9eoJ5gB56Xp7xAadEAbjrF+6j - /X8RV/0jCjtOtxVpv6qSEsGDXbfaTFxGLtpXYmhqm3XNbWmtM+oLBTbpWjknhGGng0WcDBY8FUx/SJ30 - P0GAK+qMpTEni+nvvHKu+BW64nPWPTpH7hHnZDL0VLKYE8nCp5HpT6G3YcghIAkQi/wsHTvxjHvaGX7S - WdQpZwMnnEWebjZ4sln8qWZjTjQTvDWvAlvzqs//as8KVnN91Ou1WMDMO/sseO6Z+pBe4yRQfcM5GAo9 - 0Szq9K+Bk78iTuQKnsYVdxLX0Clc+vPueGJW5rJgwM09D2vgLKz485PGnJ2kv9O+4JWtn7vjgchBXAEU - Y1vV60xPLOk5FJE+MeIAEiAWfQUpuvuIIK+KFMCqyPc5VWnsiUpRpykNnKSkPv7X5vv5efJa1d/TujqU - 5NRxeT8Ce73jwNlJ0ecmjTgzKfq8pBFnJUWfkzTijCTO+Ujw2Ugx5yKFz0SKPQ9p+Cwk/Y3mQJY2B9/D - fmVw4HQh5slC6KlC8ScKjTlN6B1OEhp1itA7nCA06vQg5slB6KlBpyN/zO1U6W/jBTRIPN7tRk8nOn0Y - s+wVlSCx1F67ahi6lmMYWR/tq7zkpRokAmMy1yANnbrEP3EpdNpS+1k/Rcip510eivCeZzlxznES9DWc - AlrDKXir7QS22i7+LKQx5yDp7zxnG2PKXn5vm5ObSFACxeLlfzznv88LwpRTlN7pBKXRpydFnZw0cGpS - e9YRY8SLjHTjTl8ac/LS+5xXNPasIuPwlmf1YJC62hHi0Qgxq+7E2FV3InrVnRix6i7y3JzBM3N45+Vg - Z+VEnpMzeEYO93wc/Gwc5rk46Jk4sefhDJ+Fo7/hv9xGrswgBxCJeuIOctoO76Qd7JSd9zlhZ+zpOjEn - 64RP1RExK0hFeAWpoK/TFNA6TVZPA+5lkNtHoG1Uf2LsSmZyuJG8PaQH2+6mUg+9+SuIIN6OwD9FKXSC - UuTpSYMnJ0WemjR4YlLUaUkDJyXFn5I05oSk+NORxpyMFHEqUvBEpNjTkIZPQoo9j2j4LKLoc4hGnEGk - 1q0kz1lRVGq4Xb8dd4sihgEddiTGvDU4U/2a0hJBfd8xqIVhJIUCLMfLxcfjRAR5As1jPTNLibi6WUyW - 0mJ78/J2wfvxHmg76TLIwvrBHmg71Ylayeqw3coMyTADuOV/OU/O2Snqw76bJ8Vs3BT2Ydd9EZMKF+FU - uGBKMVtEKlyEUyEiDYIpwBHCpojfjvzyzUWeGOcfjHU6GOqjrN4B0N6bX2w41+lgqI9ynQDae2Wrfz3/ - 9rC8Tz49fv48neuhfHs84PZQrsfGGNAMxVP75r5DvJMmEG+TZXt9YexQJ0MgilrcXx6Kgh3kKAjFOOz4 - +sMuYN4fxDNbreCAW4x/ZwJiA2bS5pUwbdkX8+WD/P79cnq9VOVG/ufn2e2Uc2+HVOPiku53wDIqGjEP - hDR2PLXSc/bw5VRH7PbUko8psDhq7XGT8QK0LGo+7Jnawx5zyj9teFJFYlZOpvVp1E7LmhaIOakZ0CYx - K7WScFHLq7d8vJt8nbKzMmIIRmG0zZgiFIfTJmMKJA6nLQZoxE4sSDaIOQkHAngg4iS8+ulyuJFa2H0Y - ce+rPT8VjjDmphV5G0Scej11TME0BVgMwoZdHug744rfUMnjZg48X9Bq/yPie7hZC89V4jnfku+MhnwX - teXood41ub6Wg7DkZrq4ns8eltTjzhE86B+/8QAIB92EmgumDft0kVx/nVyP9nXftw3r1TrJynX9Nv74 - QwdzfNvV+cUVS2mRjrWpuVaLtK2bjKzrENuTrVecSzMwx8dwQZ6KfS+qwL0QerN0/QHlvSgA9b1dQI7X - QG3voXyt0z1V2VOYLdmnm834BVUgbLs51wlfZcQ14le4uDtPJnffKPVjjzieT7Nlsliq77cHEZKMLoy7 - SU0FwOLmJ/0SYsOVdzju56tDVkrz46O4lzBFBaBBb0wqCziVvz6ws4eFol7qFRsg6iTfOpN0rff3t9PJ - Hfk6T5jjm949fp3OJ8vpDT1JHRY3PxHzmI3i3pytDaUD9XbZKO4V/FQQoVRoquTTHdesYcf9mZnJPqO5 - 7PfpnYx3O/vf6c1yJoeC6eZfJDPAD0SgN02gYSAKuchAgoEYxJvg4wN+anYH+IEI+5qwRAc3DEShFi+A - H45AXOI4oIHjcVs4Hw/6efkKa+3sj5l5Cm31ZpNLbqrYKOolpoYJok5qKlika71bTn9Xz4B2e5qz5xAj - 4bGOyyFG+j0yQMRJ7UIYHGLMecIc85Hvds8hRsH8zQL9zarqOciq9NdfuOIOR/z0rohFOta7x9tbemY6 - UZCNeNM7BjJRb/cRclz3n/5rer1U+0QRFvr6JGwlp53BwUZi+p0o2EZNwx5zfdfLaT+xQKwiXTjkplaW - Lhxy0++WS4fs1DtnsyEz+S46cMhNrQJd2HE/yL8vJ59up9wkhwQDMYgJ7+MDfmryAzwWISJ9ginDTpNA - avDTIZgClJdHAdTxLqb//Ti9u55yJmMdFjNzrYBxybvMJXKFbXZr0ybdbGhWBw6510WWlsR6GhKEYlC7 - oy4Mu6ktF9pmHT8grDZxOdhI2VTM5RAj705tsPtDrrLwmryf8P/A/uEnGHWfji/epeI7M4TlgCMVWfk0 - /h1Zn4St1EoXbXO6D+hTRSYYcCbjzyCG2LA52e5j5BKH/YJXywisflEb/jKFH1BjsnpL7mY3TG9H4/bY - 0iFGlQ73W0kq1u8RTXngiHLA+7j8fMUJ0qGIl9phMTjcyC3oR9YxL38951bXNop6ib0WE0Sd1DSwSNfK - fMayRJ+xsB6sIE9TmI9Q0Ocm+oNNvt3SdYqCbPSMgzxv4TxkgZ+ssB6nIM9QmA9O0KclrEckyHORmIch - 4Scg+lNZvT1lZVanRf53tlE7VdEj+A430reHKbm/fYQgFz0/HinIRh1fHCHIRc6RHQS5BOe6BHxdapd1 - luzcsT3ezf6czhf8J2eQYCAGscLw8QE/9aYBvBthec1qIgwOMdIbCovErLu93qYuaXjqE4746bnEABFn - zrvWHLtGci7oOcRIb1IsErFSqwWDw42c5sXHPf/nK3Y1YbO4mZwNDBK30jODiTreP2eLWcQ8uI8H/cQE - ceGgm5osHu3YaQdcG4jjafsfjRz+qM1CST4bxbwvH3nSl4+esUmqFeXsKwdzfHmT7ZLNRU6yHSHERdkD - wAMxJ3HaxuBAIz3jGBxoPHAu8ABenTragXNLWg4xkusNE0Sc+cWGpZQcYqTWEAYHGXk/GvvFrJ+L/Fa1 - +QWrnHQg5uSUk5aDjKzbgdyLfUrseZ4oyKa2K6bbFIXZknXzk2dUJGQ9lLzf3HKQkbb/p8s5xt2q23WR - /OzJIjFrydeWgLdtvmR6/00r0QbnGGUveZc3+UtGryZs1PUemiSraHPSHQOYGK19jzm+Jn26oL7o0TGA - SYw/HtlkXFO22xd6/0DqTbBIw/q4/CKB5bdkdvf5Pule8CTZUcNQFELaIvxQBEqNjAmgGH9Mv81umKnU - s7iZkzJHEreyUuOE9t5Pk8XsOrm+v5NDjcnsbknLLzAdso9PDYgNmQkpAsKGe3afpPu9PtYpLzLKdvMA - antPJxitm7qgWC3QcRZZWifbIh1/sKaDQb52Q1Cm1YAdt9roRB8UrL9CMtuo46Ump5+K8i96uKgPYyFu - pooKkBjtCddPh7ROyybLWGEcBxCJeCC1y9nGTXU8YZHi6ynbllVbikZ+3ebVjjCkx8gW5LgKwi4nJ8Bx - 1LS76NST3V+StCioFsXYJr3WhrAUyGR80/ht4HsCsOzJlr1vycu8oXoU45t2ahKCkUZHDjbux3cMHcz3 - qd1dZH4dvyTIA30ns053UMyrjhQdv000xPpm6gkCLucZqT/c+bXP2c/NYUfKzB1ie9QNKkl5uSVcS0Nu - +Y6MbVLZUB9OVdJSyORcY/NMrhZPEOCidPAMBjDpDaRIL7MAKOYl3g4LRJwb2ZGoqzeWtmMRM7VAWCDi - lINwnlOBiLMmHKrngYiTtJm8T/rWit4jMTDbR8zsXj5XjcAqr5J9mtdE0YnzjYwOoIH5PlrfoiUAC+H8 - BpMBTHuyZ+9bVJ24Omypqg7zfaJaf8/Iid5Sru0n0fPTNRx2q6wml0cDA32qRMk2hKHsSNvKGPiAY559 - RcoQ8usOr5YjkDJCSziWpiY3K0fGMREHOntvnEOt3P06nZp1/DzTnpYqynOqRkOAizPLY4GuU9CKqwYc - xyvvql6RaxKculvANbcg1tvCq7UFuc4WQI2tTuTY0SQScB302lWAdavuwxWEU6UtCHDJpNfnVVLzgAcj - bjUQ2BP2SQVhxM32wk7qSF2AsxmCPJshgNkM/TfqCPoEAa49WbT3LdSZEQHOjIhuQoLYezEw2JdVWzXO - P9QlR9vTvr0kLCUwGd90mocg55CeDFiJMyMiODPSfyr22TpPC566gzE3eYDkoL6XM5sj0Nmc01CsO6GJ - 9IgcFTgxnqtDsUnkiIiT0i4MuslZrscQH/HBismBRnpGMDjX2N5J+RlNeMIcX0nvYx8Z29RkglGx95Rt - O6hjn0lX1RK25YU6f/biz529cJLoBU6jV8bA6hUcWZGzFJCX2qJLfGRygiAXp8ttk4b1dvLH9OLTxeWv - o20nArIkn/OSUP04HGicUToNNgb6HvcbypyqCxrOu+TT7ezupn3Pv3zJCL1JH4W9pKLlcLAxL1/SIicl - AUijdmYy5IFUoMwz2pjlu17+lWTjD/foCc9CvC1HxPMQXk7rCc9CS56O8CyiSWvq1WjGMv0+vbv+pNeB - EFQ9BLgEKY1OjGX6en+31BdMWfTocrCRmBUsDjbSbqeJoT5VyYiG8gIoKsBjbKs62VWbQ3EQ3CiGAo5D - ywwmhvqSQs2TbJjajrbs6UokuUheq5piNSjbtiFZNh5NvpAOsT1ifbEqKRYNWI5VXtIcLWA75F9ykkMD - gIN4LIDLAcZ9SrftU8+0Xq1Y19ZzrnGTrWkqCbiOZ8IajyPgOoqM9cNOmOvb7XOaSQKWQ68DJCj0930D - ZXt+kwFMxOakh2wXYfHHnf0efvtvap1xRGwPrbH12th1dShVBfua/J3VlUowQdJ5tGWXeZxWG7WA7chf - KIL8xaWp6XxEbM+Bcrett9rkv7PyOS3X2SbZ5UWhHn+mupKr853s6TdvevKAoB+js+P/OKQFq4PikLb1 - JyVN5LctmlgKvfK3raud7MiUzVO1y+o3ksoiLevTmpJV5Ldt+vjWqroXWUKqzj3WMTdJvV1/vLz4tfvC - +eXHX0l6SODFOIzfbLknPAuxxB0RyyPbNlrd0QKWg/Qw5M59DnKn+oqyTiP2iHvIdZXZU6pemaLJjpRr - q0id1hbwHCXxYiTgOvbV6wVNogjPQi8xBgXbtqmstdS8LE9r4K6fmMGhMYf8m2o0aRZFWJYioxUS/X3b - QDqJ8QQAjnOy5Nyy7NJaPMvWhrSiw8Ycn/hO7dGcGNtUbYhjxI6ALMmPQz7+nViX84y0VrgjIMuFbhPp - rpaDjExh2MfqxsACPAaxfHusZ9ZTr4J6yR2F2ZJVoRaDb3jWI43aqw3XXAE5n1zP9BDiOmfJzjEbq1xa - LGKOECPe3aEg6iQBWXgdaB/23MROwRHxPOJHTdRIArI0dI2f78RhRdUcVpCFlSVOnGdkVFd+LbXPaV2J - FrAdtHzp5kmZpai/pEMsD21y353TL0uZPBRefd83UEtAD9muw47ahTkioIeawBbnG99k/5hqU4xlog1C - 3BHIPlUtjur8JYdS7UVCag8B2rZz52gCszGkXe2O3/cNlAWDPWJ7RHbYVEmdkp7YGhRmU//nKeM5W9Yy - Ey/QuzLWJQWupf0zbVhpcbaR2jOq/V5RTe4R1UBviHgMbk94FsZUh4l5Ptq8lADmpQR9XkpA81K0Honb - GyH2RLxeCK0H4vY+VA+CmgYdYnmaKnGOZiUYfRh0d2etMcQd6VpZXV2Ls4wH2oTAwZ0NONAeIB3cJ0gH - WlY4uHnhJS0OGbHtPTGWiTiN5cxhnb6yPZTrJq/K5JlQA4E0ZBdZsaW14T5qeB8/J1+nX7stXkYrLcq3 - kR6JGIxveqqrV6pJMbCpPWOI42tJ30rpoveI71EvTNUv5ETrMNu3y3aUp3wnwraIpiZaWsKzFOu0IWoU - AngIT4h7xPOU9J9VQr+rLLKS6inM9zqvP33S06GUaWKTgU3JqqoKjk6DiJN0eKlPItZq3ZD3m0YFWIx8 - 0z4nbQhvCuMGJMqBn0AHJIVIQ1IL8l1in64zqktDvutw/ivVJBHQ051xJYd08qOf44e7AQUYp8gY5gL6 - 7RfkeywR0BP9230FEOfjBdn78QL0MNJQQYCLXk4OUPmQf2Rck4IA1xVZdAVZom/qVfieEs9YNBDbQ3n7 - 9Ph9x5ATX6KyINcl1mm9SdbPebGh+QzQdsr/yMfvDNATkIWyWbRNOTbKrmwnAHC0DYca1I/fcw6EbTdl - kcnx+74hIef8nrJthP5V93WbJ/apDcT2UIaFx++bhkXXvcpqNQrfZPV4mYdC3rzp9lp+TgVl1gs3AFFU - L0heAq0X5bO2We2zleal6FZdvlGqE4h27fs3ajfKpGwbrc5ceHXmQq8OS8s3Yn/f5nBjkhXZjrADG8bD - EVQOjI3iOoBInJSBU4U+EnJAxMn9/YO/O8l3+yJf5/QBEe7AItEGKy6JWA987QHxkgvvCfJdRSoaUkfP - wnxftVezdMRVXiA84GZlY98wFIU3GB8yDUXlZRrI4UcijVRPCOjhd+xRBRinyBjmIgNcF+REdUaqpz9G - //bwSLX7EmWkekJADyMN3ZHqgrqE3EBAD+Oa3JFq92dyBQbVXTEjVcxgR6GNJRbeWGKhFgkfFzKc2p7s - idZ5xhxeJP2iutMZJgaCFKE4vJ/jC+wYpDHTwh0zLdrdidSrMhTLCbJd+yz73l5qk5JS0wJtp/ie7ykq - 9X3H0Ix/onT8vmugPBnpCcMynS9nn2fXk+X04f52dj2b0k6pwPhwBEKJBOmwnfAkDMEN/9fJNfkVfAsC - XKQENiHARfmxBuOYSPuf9IRjoex5cgIcx5yywWNPOBbabikGYnju7z4nf05uH0mnsNqUY9N7BGSCdv9d - EHEWVbdnJkt8oh17u5avyMc/43cwwze/TW5mi2XycE8+CwdicTMhE3okbqVkAh81vd8elvfJp8fPn6dz - +Y37W2JSgHjQT7p0iMbsaVGMP5IMQDEvaYbLIzErP5lDKaznjGXTyjMfacxO6UW5IOZkZ4dATtDboKhH - 0+yUMA1YFNrObxDrmb8+Lqd/kR9nASxiJg0/XBBxqs1bSFsbwnTITnuiBuOI/1DGXb/BhyPwf4Mp8GLI - juI32cJTH+xBMOpm5BoTRb0H3clJVurnCWYAy+FFWiwny9l1ZEaFJSNicW45YglH42diTDMqXvTvC+bs - 5Zf5dHIzu0nWh7qmPFqAcdyvt6TuDt3jBjEd4UjlYZfV+TomUKcIx9lXaiKkjonTKbw469X6/OJK7eVS - v+2p98WGMXdWRrg72HdvV+rjc67dwTH/VZx/8Pqj7Kj7OZX/Sy4+ULVHzje2PRHVt9bHttN70YDBj9LU - EWliwQNu9U/CbDyu8OJsq/q7LBCNOsQ5fyqrOkt26eYlec33WVXqT9WmfmqFOmX+lSP3r00dPMi7fSbq - eZ/WO5UwKbnF6kHMyauXbHjAzcoLkAKLw8vPNjzgjvkN4fzcfYnVJbVYzKzHqd+zN577SGN22fSN35IM - QDEvZbbfBX2nOvjire0/tcfUcfswAVMwanfe3HuEdVXBuO2Fxge1PGBEXrVnkJiVfOIngoN+XaV3m43l - VckI4RjAKDr1KDuoQyxqVmvuIm6xqwDjNM/6ZCf5XcLDBhj3/c+pWulKHzf3oOdUaxBTsSMKO8q3tR03 - cn/vxHlGXa2KN0F5lxtAfa8+nGqbq0NR87RIVgfKcuiAw4tU5Ks6rd84981EPe9OTy9ztAbpW7Md4Q1T - C/Jcqkbh1XYG6VsPu4Qzt3PiPGMVMwKqwiOgqlxTKzOFeJ59Vbydf/xwyev/ODRuZ+Qmi8XNB9rjSpD2 - 7XLcIWTxXlU/WZfu4J6/3jDqnRZCXGrvmSbfF9kV5ZSsgMKPk23bDXblkCBRX9ebEZKW1Q+J8Jh5ueZG - kajnVfNF6lWdmN4Z6AAjvU/PVxB6vuL9er6C0vMV79TzFaN7voLd8xWBnq8+hm4Tc/UGDdoj+41iTL9R - xPUbxVC/kdd9wnpO3d+TfJukL2lepKsi46kthRenKcS5rKGpdeQRM3zLeXIz//Q7bU95mwJsx52XycIj - CDhJbZgJAS71dhVhqamNGb7n9Fr1zIkTOxbV226mi+NU1cexLpOxTdl69ZHabXM5z8gUIr5NdqEeILCk - DuuZP0aYPwbMJf3+HBnbVDKvr0SvTdV1hCk6AwE9yaFcP2eUQ2ZA2HdXssOxT+u8IV9qTxrWL4mONNrV - fd83JPvDipSADmcbq93+ILs3RF9PYTY1v/BMuCcQjLpp55yAsOWmLLnqvm7xpx38acloYrBP5qJ0lzVZ - LQhbzqECJ0bzIXkiORXgO6i/uUV8z55q2QOOH+RfJBHAU+cvnB925AAjudCamO/7QTX9cB3qUIjf/nn+ - z+Tiwy9XNJuFWt7jlux9viOYfdhyExYEtt+2aeJ+qgZiedpFw6zf56KWV9DLkoDKkqCXAwGVAz3s0W8s - 0UwdZLsIpzJ3X7d42oLKE2A6dKoLymk+JmOYZvPp9fJ+/m2xnFPPEIVY3Dx+GOGTuJVSiHzU9C4ebiff - ltO/lsQ0sDnYSPntJgXbSL/Zwixft1A+uZt8nVJ/s8fiZtJvd0jcSksDFwW9zCRAfz3rhyO/mfdzsV+q - 58j2lIeaIGy4F5NkMSPWHgbjm7q2kyrrMN9HScAe8T26zaOaNGS72iGMejU1bQ41yeigtndTxah92rOr - T4hKhXiel6zOt29EUws5Ltk43nwhiTRhW6g518+1rEGTwyFG3rAJNbhRSAOnEwFYyL/c6+8d/7one/aQ - 5Qf9d9n9xtNfqQMoF4ScxCGUwwHGH2TXD89CfSTiYKCPvAwIYm1zxMAMpBG7vHuMIg3giP+wKvI1W3+i - bTuxrfPaOfaQEGBBMy9VPRh0s1LUZW2zYNRtAqzbBKNWEmCtJHglVWAlldqs+206aVDcfd82EIfFJ8K2 - 0DsWQK+CMbw2od41vebNSrscbky2+V5wtRq23IyevE3Btop4xg7EQmbVitGdisJsSc3zJTVqFEwj+IuJ - IyMPhJ0/Ke88eyDkJLRCFgS5SKMuB4N8gpVrBJJrmoqbt4+kayWOsywIcNGqRAdzffQLg66K0lr0hGvh - /DD/VyW/f+5OvJR9lufxZ6b5pGctc9HsLy5+4ZkdGrFf/hpjP9Gg/e8o+9+YfX7/+JAQFvWaDGAiNNMm - A5hozZ4BAa52mNyOwKuabLVxzF/VhP2EART2yi7CNl0zr/oEY+5D/ZKpPMKTH+mgnTK3ieCIf5M9cfJI - jyJe9o1E72Nb8AhbhPskYFXj8dVbTDJ7BiQKP59YNGDXKUZ6egqggFcc97PdFuNfgYNpxM6vTiwasev3 - 4NULJOrwY3UE1baqd6xIoMmK+sf0WzfXTBu/OCDiJI20bM4zyhuey6ykxyEiW9fjN0pDBX4MUgvWEZ6F - 2HodEc/DmcoG0KCXc9s9HoigGs26IidnD8JOxpwVgiN+8rwVTEN2XQ6pZdljQXNWrnV1JRjmEwubaZNb - PolZyZPRCO75c5FU+/THgVoET5xnlPfzgvBKjk15tuO0MavphgVoDH5xCc6dd98hTS0cCcjC7smAPBiB - PHiyQc/ZTlWzL9rFET998h/BMT87fwSeAnTf4PbCPBY0c+tSEaxLRURdKoJ1qWDXpSJQl+reJKOZPXGg - kZ8rHBq2c5tYGx5wJ+lWfSjvtRwq5GVKmhcc5/OugPbgxIIs19fp8sv9Tbs1Qp4Vm6R521MqGJC3IrRL - iAgHDpsMYNJvQlH7vS4KeUlzUycGMhF2sLYgwLVZFWSVZCDTgf773BEHfdWcBQEufR5MTPEJaUbHI045 - DKmAuLkaFjfkGC0G+USSqreV1av0DT232Tjsl0N43WngyI8sYN4d6DlaMoCJ1icE1kee/lqtmws9f0H2 - nUjAqv9+sV6tyNYTiVplXKZVkoBVvE85FGPLoXi/cigo5bDtk+32dSZEtnmX2LgOid9U/ILr8FaErouf - by5Kwj7yHgg6RSM/2zCcLWg59Yldh7xo8q6WoOQzHzbcNxeXl+f/VH2ofZqPnzC1MdR3nM4b/94eKvBj - kJ6xGoxvIj4htSjTNnuYzJffyK8KeCDiHL9W3sEQH6U1cDjDePf77I74e3vE86jM2j6CJs4JwDjon8fY - 57hbn1RxLGlZ+SQ/EsQIkMKLQ7lvJ8Kz1NmTrGrUaZNFoWvkImuotxB0eJFE3D0VQ/dUxNxTgd3T+TxZ - TP6c6j2qifnbR22v2tYmq+uqps04eGTIuuVrt7a3HQPqjylOA4N84k1mnB1Xa9K2vf0ZtMPJXA43JiXX - mZS2Ve+H234kKE6Tc4yHcs3++R5su/W8PvVWnSDElRTqTxyhJkNWcsECcN9fZj/7b+kt/qghfIMdRf6R - fQtd1jGrluXT7J6T51wWMKv/4JoNFjDPJ3c3bLUJA269U0nFttu47dfH85GLTE9hNnKhcdCgl1xsIB6I - oM8H5iVGjwa9vGRx+OEIvASCJE6saq8Gqbu0/k6y95jjq9XSEh2SlK1NDjcm6xVXKtGAd7tne7d7x3vg - 5LgDmNfqLBVVya6YAdz176oX1aoTtiVzOdDYbS/HFZu46xeNOjyAYTZA2ylSThr0lGOTrS21OB0Zw/Tn - QzKZTm702ZQp4UQdD0ScxNO9IBYxk0YsLog4VRdm/G74AIp4KfvneWDAmbzmzXOyyetsTdn9fMiDRKSM - yx0OMVb7jHfRCgw4k6e0eSaspEV4JILICG/euGDAmYh12jTMyzYFSIwmfSK94AOwiJmyi68HAk71yJu2 - Tw+AAl71ppKs+OtnTk1nwoibm8IGC5hLtfM2Nz1M2HZ/Ui8dLas/CEshLMq2Xc8evkzn+qbq4+loL/dg - AjTGOt8TC7gH4256m+XTuJ2yFsBHcW9TF1yvRFFvt98lpU+ICdAYtBVPAIubib0EB0W9+lH/fk8bL+EK - NA615+CguPeFUaFAPBqBV4eDAjTGrtpw765CUS+xp2OTuDXfcK35BrXWlFPbIRY1i/g8LsbkcfWlmBrg - xAcjROdHWxKMpbZj5VeYhgGMEtW+DrSt3PuAp39MTROuZaLu6MCdZNYsaK3CK/t+uad3e6C+jv7b57xM - C8JeUj4JWWfUButEYTbWJXYg5HwknfjicrbxJlvLO/4pFdmvv1CMJgcaVSllCBUG+fQdo/s0Bvmod7mn - IBv9jpgcZNzckusFC/ScqgfLKTAOCnoZiXnEUB/vMsFS033Gukk96Djzp0zQfrQmIAs9b/cY6vvr/jNT - KUnUSr0rFglZyVnnRGE21iXC+UZ/tKCsYrMozMa83ycU8/LS8khiVkaxcVjIzLXixj9pawQdDjcy75YB - 427eHetZ3MxNX5O27dOS1a4bGOQjp66BQT5qivYUZKOnoslBRka7boGek9uuOyjoZSQm3K4bH/AuE6yf - u89YNwlr1788/DHlzqG6LGLOfu6rumGJWxTxUmfaLBBxcp83gAIkBvUZmgUiTuoTLgtEnc1hn6zkkCep - k596iTkzhOcZjijeKaIgR1Sv+uoTKt8r9EkYvIa9+P4eyWxqBuOJ94knqPHeI4lBH3AFetKeU5qPIOJ8 - /r7ZJjuetmNt89ebiGdxHgy6GXX818DKjuNnxOdjBob6iK2mTcJWfYIqR6pB0Nkdj8qQdiRopT4B+4qt - kvnKW8vyFVvJ0n1Ay/QnCHQRn9t8RdandH8nP1kxOdDIetLhsrCZV8LRsk166d/GPB+7DgrUP5xUhFNP - vRjT7lbAUNqw52b8ZvDXMu6GfycePk0TQTrz0qYc2x/Xi6sL2QR9I9lOlGubfrvQH9JsR8q3sdZEWCDi - 3NBaPJNDjNQa2gIRZ7sj2Hfa2h6fDtlrkSZVmu2TIl1lBT+O7cEj6i/unrbnxCYDcwxE0pcUGalzDERi - PC3GHEORhEhEWjTENWohTyDi6fygmGQ0JUgsYqtvcrgxyTdcaZJjVyreqdyI0eVG79+0bvfiUiuxuOEs - yYhYT1nZbyIQHdSyBaKrJJG1lvo6aWPXAc+4iPvDKvu5f4+YrWkgakxNKEbVhOIdakIxqiYU71ATilE1 - oTBqsC61I3+ZZSJEfYfb5+vGx49pBnDdiPjvFXg4YnT7I4bbn1QI4gNOA0N9yc1iwnQqFPe2275x1S2N - 2+f8q56DV60nPhntR8dBRk6zgLQBlP3hDAY2cXbbhHHIr2ayYgLYPBBhk9FHlgaHG8nzTR4MutVm3Ayr - wlAf91JPLG7WS0Iz2so/iAcidMvzyeaOw4285DBhwM0aKyPjZD36HH9qqMuhRkYteAQxJ7PeNljMPOde - 7Ry72nNmmp6jaXrOTdNzPE3PI9L0PJim59w0PQ+laVMIVTbUUgbavoRBCxwtqdNX1j68AUcoEn1PXlwB - xGF0IMC+A31vd48ErG0HmqxsMdTHq3wNFjDvctlXK59iOhK+AojDmc+B53LUZExsXgYcoUj8vOwrgDjH - 6RCy/QgGnLw8Y9GQXe9i0R6LSZcbMO5u7wxX3tK4Xd8OrlzDgFtwWzWBt2oiolUTwVZNcFs1gbdq4l1a - NTGyVdO7pBKfolkg5OSM/JFxvx4Es8rfiQStfzN+sfcEUv+ZlXpIyhH3qrcxwPdCXrxsYKiPdz8MFjfX - 2Vot6+PKO3zQH/ULTIcdibUKH1l/z1l5D6+5P/6VuNjHwHwffXEstm6fuRoeXQfPWwGPrX3v/05MPQuE - nPQUxNfQq208270bkrTIU1J3wmV984b8TlJPOTa1q1SaieT84ipZr9aJeE51K0WSY5KRsZJ8t5d9j5y6 - o9Eo4fA1qFNf3+EXd5pQvPUuWRWHrKkq2osBuGVstOTqfeIlV6GITZ0879JjavAj2p5AxKf1jh1FsmGz - HOKUG70pTUyM3jIQTURk/o4fiCBz5/lFVAxtGBHlY3SUj1iUf17w73rLImZVfqNrQFcyMlZ0DRgSDl9D - TA3oa4bjfbz65T3idZpQvHeokQBPICI3b3Zs2BxZI3mWgWgiIjOGa6TjN/g1kmUYEeVjdBSoRlo/p/J/ - Fx+SfVW8nX/8cEmO4hmAKBt5Jdkm+xhXPYGWsdGiKqhBI3AV5aEo+L/VogH7z/gb93Pwzp16hzT3CUN8 - Tc3yNTXsywg7CNsY7CNXgGhvrP2g2rKuT2KAT3YAOPejxRAf4360GOzj3I8Wg32c+wH3k9oPOPejxXxf - 15ZTfR2G+Oj3o8NgH+N+dBjsY9wPpG/QfsC4Hx1m+1ZF+j27WBF7ST1l2xgv3IFv2qmmg5hDOsT3EO9k - hwAe2n5bHQJ6PjJEH2ETJ5mOHGLkJFjHgUbmJfpXqI4PVk08RXZkbJM+Ml7Pta3eSMdTA2zATHuu76C+ - t53J412xyQbM9Cs2UNxbrf7F9UrU9j6nQldnz2m9eU1rUkq4rG0+Hurehk7S4qmq8+aZVHFjDjgS87F/ - +PR58wush/0+7dg3pK3k5Ndd/pLGX3q87uUTJZqxTe0x7TH3GzZAUZj3OnSSfP8x6z67rG2u1xfJLx+o - lXdP+TaGCvD8QnM4eY+ab/w8o+aCLn4hOiThW2h9LmgOqp0NI1ok4VkuafMxLQFZEvqv6ijbpqYK1LyB - Xti9S0kZx2Vhc1dm1UPkesPRWwI4RvvZ8ZvisFfb+2SsaIgKi6uPj2G8rQQbjCh/Lad3N9MbtQ4neVxM - fieezAjjQT/hATIEB92UlXwg3ds/zx4WpF15TwDgSAgbO1hQ7/p9ejedT24TdWLsgnSTfBKzjr81LocZ - CTfEA2En5S0Yl0OMhDfsXQ4xcm9P4O60i+ArdUzMHWHAEFCE4rykxSEihsYRPy+ToXmMm8UCOUwvpWQ5 - NYlYxSnxS+79sxWhOPz7JwL3b/H4aTmf8rK3yeJmeuboSdzKyCIG2nu//HEzepde9V2bVNsBpuWGIugQ - z9PU6bohijRjmL5Orkcb5HdtkrMfl8tBRsJeXBaEuAiLy1wOMFKyvQUBLspCSQsCXITsbTKAibQDlU05 - NtLCw55wLDNqKs38FCIuMjQZx0RbWmggjoeySvoEGI75YqFeOE3Hl7wT4ViykmrRhGN5ysqsJs6FeKDj - 5E95Ibjj5060gLDrroq3j7KwvmTj9431QNC5OxQMoaR622yxeJRfTW5mi2XycD+7W5LqNQQP+seXYRAO - ugl1H0z39q83o6de5FctjlbdnQDbQansjt+3Dcs6LcW2qncUzQmyXbTKridMy+V4/NLiqOl56afnJTE9 - L730vOSk5yWcnpfk9Lz003O6/HJ/Q3mRpSc8y6GkezTTm/Rw4fr+brGcT2RhWiTr52z8ZvMwHbBTaikQ - DrjHZxQADXgJtRPEGmb5yWdaEpwI16J3OaMd4OuBoJN0kLfLucaiGr/pcU9AlmSVV3STolwb5XYeAcMx - XS6uJw/TZPHwh+zUkW6mj6JeQl52QdRJ+eEeCVtnyerXX1SnlDDFivGhCO17mvwILY9F4N7EWeAeznSp - kL1LQrcU47EIvEwyQ/PIjJtFZqEcIiLTQQymA+WVWp/ErLTXQyHWMN8vZ9dT+VVaXrMoyEbIAQYDmSh3 - 3oR61/2n/0rWK3FBWK9iII6HNillII5nR3PsXJ60YXtP2JYN7Zds3F8h/2Ojsmq+UasZBMXloKh39Raj - 7mjbrp8hUE6BtSDbRTuwsyccS0nNnC1hW+QfLtarFUXTIb6nKKmaovQthJVcBuJ7BPlqhHM1UktN4g7x - Pc3PhuqRiO0R5DsugDsutVRNh/ge4r3qEMPzML1TX1JvEadF0S9vEsm6KkcPBgc0frzVIS/U/mrtjrqC - GsfBfb+uvkVG9XYY4iPUuzYG+2pS6+2TgFWmdf5ENmoKsO0PsjLWR9OQlT3qezm/Gv69T7sm35FdLYXZ - ZB7+F8+oSNS6ybdbplahvvc5Fc8fL6jKlvJtefrxYp3ukweq8AQCTvXARG+kWJGtPep725G4qgFkBbCr - NoeCXoFADj/STtZl1ZrqbinMRnrKB6CAN9tt6EW0pXxbWTGrkRPoO2UnlpOQHeb7RFOvU5FRuuMeCVoZ - 6dhSoK1Ypw1DpzDEN/5JuIOBvpKfiGUoFUteMpZYOpaErbodzPc1VVG9jt/1yMEM3/LLdE5dfGZBkIvU - NloUZCNUNAYDmQjjeQsyXPushLuIo8WoAY/SvmzDDtHhuL9dq8v2d7jvf5FRCXPxDob6kvKwYzoV2nsf - pl+TyeLuXNXRo0cyFoS4KBPzHgg4X2UOychCTWE21iWeSNv61+WHfyazu8/35IS0yZCVer0+jdlZyQHg - tn/11mSCdeU2aVvlfyZrWeZW6fjnkS7nGr/LHtm2otlaxjFViTpcd3yrZEG2S83zq1X+17MHWQ/rhKZY - Adz272vZEaXsw2hBtoua5/2cru/1zRfazq4eCDkXk4f2haw/xj9pgGnYnjw8fiJskgqgsJebFEcSsE6v - I5LChEE3NyFOJGBV5/H9RjZqCrFdsWxXmE1+ffanfs2EWkAxBxSJl7B4qvJzQTAPzKPK2nygrKnP9ao8 - rvwIw25uKs9D5Vi1kWSjghBXMnn8i+VTIOa8nt/ynBLEnPPpf/OcEgScxP4D3HM4/pXfzpgw5o4qA54B - j8LNrzaO+2OSKNAGqc+j2iFXgMaISaBQm6Q+57VLJzJgvWJbr0LWyHYK8WAR+QkfTvW4XDOYZ+bRZXc+ - ouxGtWOuAI8RcxfmQ/UDq107ggEnq30z4ZCb086ZcMjNae9M2HaTJzuAeY52UM5p6mwStHILCoAjfkb2 - dVnEzE4QuFVrP+Q2aT4N29nJgbRk7YfkZszAMN8Vz3eF+mIS1hGMiEE5YjgoQWPxm2JUAsZiZphAbom5 - EcF7MI+rT+ZD9Qm3yfVpxM5O7XmwtqI2sz2F2agNrE2iVmLTapOoldio2mTImtxN/4dvVjRkJw5SkVnz - 058j2m58nGp8HlfmBkaq1pfYpSM0VrW+EZVQoXY9ZrgKG/AoUckUbOdZQ1YHDXmv+N6roDc24Ue0/8DX - eH0ARBSMGdsXGDUuN74akcEGclfsjRq8R/P4+mo+pr6K6yuEx+fWd6LuxnywVuT1HeAxuv0Zrw+Bj9Kd - z1l9CXyc7nzO6lMMjNStz3l9C9dgRJHF+/wiefg0VatNRpstyrPRXmCxIM9FWepkIJ5HPbH+LuvMtNwk - 66wevxgH470IemsHolUznqk71Y6w2aEH2s5Leav+uPl8kVC27vHAgDNZfJmcs8Wadu37VXahXtIkn8+O - 4KCfc/47gtv+35LVodwUmaoxSFnNAhGnyn/5Nl/L8sJzmwI3BrXA/QaUt990caH/9CMF2VRtxjMeSczK - T07IAEWJizBkVycxx0VwDW4UyruuPeFa1Moedb445fU8n0StpDMRIRYzd6U82/DkJxz3v2RFtef7Oxzz - q3vBlbds2DwpN9O4n+B77IjOAIRcR0F8OAKtOfDpsJ2wThrBXX/X0tGsHeS6ugxLc3WQ6zrupnUqBJzd - z0eo3LjtPlvvEDUg8mKq/qF6l5gY4YiBPsHzCdt3fzu7/kYvOjYG+ggFxYRAF6VYWJRr++/HyS3z11oo - 6qX+agNEneRfb5Kulb3/EYIH/dTUQHdBAj4mpwq+E1L3+dfJw4Mi6ZdtkJiVk9Yminq5Fxu6VnraGqRh - nd//JZN9Ol+2zZPeH30xu7+jJUbQMiYaIYkCjjGRKAkXkrixulSmJ5sBIk5q4pwwxEdOgp7rjfPJ3U3S - vUE01mYyjkn+JUvfSKIWcTyEmbDj9x2DfsWE5NAEZEle8+ZZhcjV7mnqQCHC8GlA48Qjbl9gMo4pe6Kl - oPy+ayjTVZEl26r+nhxKkW6zZHXYbjPKRnGDIifmNpdfpGyxblOOrR1Yl5tklzXPFS09HNYx69fSVViS - 80Q5tn01/iC1E+A6RHbYVIxsb4KOU2QZLdEU4Dn490AE74Fo0uZA+60tYniuR+8aK79qcfriCGMZAzE8 - 5gMryn5RHmg7j0+nqEqTs4z/m5x/uPhFbcCgdrVP0pefFwQvQFv25GGxSB4m88lXWk8ZQFHv+NbXA1En - oQX2SduqXjTef1+Lczm8lX/9SfG6rG1e5eOftBy/7xiKvFQnDyXj33N2MNunN4uV9eCedF09BdkoJdGE - bBdxDsdAXM82PRQNtc7zSNtKnBUyENuzLdInUtJrwHEQi6lfNs394wlb/ANowEvNZB7supsPybpuEtp6 - JAAFvBuybgNZdvtzukhCoOsHx/UDcmVkUQZYtum6qWp6wnccYMx/7PZknYIAF7ESOjKAqSR7SsBC/2HQ - r/pBtvzwLLKU0kZNNgb6ZBuayBaGWnXYrG3ORVLt0x8HUmY9QbYr4lxZBEf85GMwYNq2E7s2Xn9GJTC9 - 9esp29Ydfah7OnqhRXI/mT4ku6ctqX4KaIbiqb5bfLijZSiafioXGat1jIp08Q6RLvBIZVVm3AiKhc1t - F+4dcgMoGo7Jv0e+ZWS0i3eJ5t0p5onIIAy6WTUUfk6P/pRyzN8J8Bz6shm9fgeFvYz+uoPCXt03rasd - cbIHNeBRmiouRlOFIjTUE1pA2HG3+YVzSy0StHJuqEWC1ojbCQnQGKyb6eO2X/BHRCI0IhLM3r5Ae/uC - 0UMXYA9d8PqzAuvPUtZ2Hb/vG5K9EOQ20AIBZ52+knWScU1/ZzTL306bf9hTTk7qCdtCO9mhJyBLRLcQ - FIAxOHfUQUEv8a72VG+jrDa21xarf9GOCOsJx0I5JOwEOA7yMWE25dhoB4UZiOW5uPiFoJDfdmly+p4Y - z0RM4yPiecgp00O26/JXiuTyV5emp82R8UzUtOkQz8PJgxaHGz8V1fq74Hpb2rPT7+UJslwfryj5XH7b - pcn38sR4JuK9PCKeh5w2PWS5Ls8vCBL5bZdOaCWlIyALOZUtDjQSU9vEQB851W3Qc3J+MfxrGb8U/JWc - OsLiPCMrzbz0mj18mSy+JIQW60QYlofJH9ML8jndDgb6CBOZNuXZTs+GduKJqDRRz6v2XM1Ud42sNUjD - SlqC5a6+av9N3dbapnrbcv64WCbL+z+md8n17Wx6t9STeoRRGG4IRlllT3mZ5EIc0nKdRQSzRSNi1tkm - 2+0p53OOUAXjyr/n4vk9fqxjGhP1XX6u5wpHJtQQCB70E2oMmA7a1SyAqOvIMmBY4GjqvOzpPKa02YZg - FO4dMfCgX2XImACaD0Zg3vOeDtpVxs52EQFawYgYlKF9UBKMpXLfLmtSNZUVmb1c1WDciLLjW+Bokm3/ - g5uvLQEcoz379jSbfUwCTjREBcfNfu6zOt9lZZO8nHOiWYLhGLKTslvFxtGSMbFeqn29jY+mNXA8bpbA - c4K55IhjNnk4ArNys2q1x8V03h4AS0oCBwN948dHFgS6CD/Vpgzb8vOVWiYyeueHE+A49geiQwG946+L - y8vz0Tu8tN92aZUn9mle0yxHyrN1T4P0s6auuiGaAYMR5fLDP//8qN7PUZsFtI//KYdbYjwYQe3DEhPB - 4sEIhHdYbAqzJWmRp4LnbFnUXOTjX9wHUNTLTd3BlG0/TcT3GLnEQT/xLRyfBK2bi5xhlBRoo9TCDgb6 - ZAXG0EkKs1E2WfNJ0JpfcIySAm3cvInnyzZT8X73iQXNpOUuLocbk+2eK5Uo6H3RaxZLhrYjPWt3cp5s - MUS2psw0YLwXQVYI54zMdcQgn3rVqNyktXrjpclKNS0m6HrIAkaTaXfIGH7N4cZkVVUFV6vhAXdCLoEe - H4hALzMWGzAf1s9pzXZr2rPrCoBRrZ84z9hnGlYF4uKeX9XV9Fato0Abr4QbJGxtKO+seiDoZJcPGw64 - 6TfMYj1zu6CS0dPrQc/ZpTon25oo4G2SdfOTrNQUaOO09ifON+qMwfrZPWlbk8nt7/dzyouKNgXZKEfe - 2hRo2xw4ts0BtlETz8BAH2XfHwcDfZwbgd0HwryETYE2wfulAvulehJ2wzNK0HUul/PZp8flNFlMl+RU - dGDUva4OJVetWdxM2jsVhAfcyeotuZvdRIXoHCMi3X/6r+hI0jEiUvOziY4kHWgkcv1jkqiVXg9ZKOpt - 34YkTOpjfDhCtfqXbEljYrSGcBTKQbIYj0Zg1xGB+oFc45okapUV3nnMPT3x4QhR99QwOFH0HkiTx7/o - Wd4iMSvxNhocZqTeRBPEnOSRkIO63tndZ0Z6HinIpkce+VOZNoeaobVwyE+9Ty0Dmcj3p4Mgl+5LVJt8 - m2cbutSkXfv8lr5nqU9iVmpq9hxmJKeqAQLOr9Pll/sb3q83WNzMud4eBbzpZvMhqbOX6js1Kzgw7D5X - MxvU+T4Pht3qU45WcYCxfXlTHPImW5G1Jgy5iWPDjgFMm6zI1EuLjJ/eo5A3327pRgmBLsrm1A4G+Q70 - 1PN7oeqvrIKJlEjd15K9aLWVONlpwgG3yOo8Ldj2Fsf8vNlyiMciFKloaEufMR6LUMqLiInQ81gEZu/A - w2F/Mp/+ef/H9IYjP7KImVNFdBxu5AynfTzspw6ifTzsX9d5k695xcp1BCLRZ008OmAnPgtwWcSsV2/W - LHGLIt64imCwHtAbmdDHih6N2OMqmcE6pq8jqM+zYQMShfieAcQCZkaXHOyN79Jm/UxWaQqwcbrJcP+Y - MYQ9UpiNuBLAAgGnnoOIKGAOj0WIKAQOD0dgbuQXUCBx2oqKtPMtxiMR+LWRGKiNREQ5FsFyTNkYwYIQ - F/WRogVCzorRy1YQ4KJtceBggI+22YGDOb7Tjunkp5MWiVkjnoogjhGRqB06xIFGoo4PLRK1kseK2B7+ - zof6kCtOFxRWBOOQKyEfD/oZk+eQAI3BLQKhEkDtGyBnGDififi7KsbcVRF3V8XQXRWxd1Vgd5U3L4zN - CbNmb5GZ29v7+z8eH1QtQ1717bKoWf7tKavpvUnQgEbp+iaMaSPEgUYSB3om8WjYvm5q1rUrDjZSTg9w - OcRIzccGBxufUyG7fXnNsR5Z2Ew57tPlYCO13PUY7BPPh2ZTvZYc6ZF1zHol8vRuOZ9NyT0ph8XM3yI6 - U5hkTCxqdwqTjIlFXWaCSfBY1M6bjeJecgl1WNzM6lgBfDgCoxEGDXiUnG0PlQlq3WCjuFdk7MsVWRP0 - Rt1NMXg3RfTdFMG7ObtbTud3k1vWDTVgyK0fl5ZN/UY3n9Cgl115uobBKKxq0zUMRmFVmK4BikJ9hHyE - INfxSTDvxpo0aKc//jU40MhpI5DWoU1n+sMZF4bcvDYHa23aRYnExzEWiVi5N/6EYl69zT+7RLuGwSis - Eu0asCgN82knJBiKwf4hDfrMU39FjQvoYkVhtqQqNjyjIiErp9GC2ypWzwPpc1RlVuQlozB3IOSkD/57 - DPURjvPxyZCV+pTKhSE3qw/n995kbp9et+9XqzfyGlkn0SZtIAEcQ9ek6g8c/wlG3fS13g4Lm/PNT+4c - DWiAo9RZU+fZSxYZCtAMxKM/KwYNcJT2KQ+jgwDwToQHdaY9uY9woiAbtc47Qq6rPa727v6GU015tGt/ - /MT75T0HG4kbKRgY6vvQbpHP1HY0bM9ZF5sj10q+8ycM9gleWgosLUVUWgo8LecP94spdccXk0OMjJ1I - XBYxk9+WNMGAk76GwaNDdhGnF2G/ftSw4epbOmyPuv6TIBCD3kZ4dMAekTjBlGnqg+BftaYRO70KOXGO - Ue34xHteaJGYlVgTGxxmpNbGJgg49csPadPUZOmJDFk541pIMBSDOq6FBEMxqBNukACOwV0g7+ODfvLC - T1gBxGlfTGEcOYYbgCjdlCArxxosZKZPJvYY5CO28B0DmE5Jz7p5Fg3YWRUfUudFvMfg47D/PMl2aV5w - 3B0Ke3lZ6ggGnNwq0OEHInAqQIcPRaB3QHwc8Vv5U7Bi2IqhOJExMP/+sOJUej2KePlr9kEDFqWdD6F3 - 9CEBEoOznthhATOjiwX2rjgdK7hPRZ/XOFGYjTr5aoKoc7tnOrdQKyXiy7IYU5YFv6yJUFkTsaVADJcC - EVEKRLAUkFfVHyHERV5Vb4KAs6nok9sGBxgZa+F7zPPp9xv575FDAjwG+Y1Jh0XMzDe2fRzzk3u0Jw4x - MvqePYg4Y944RhyhSGpTgnWqNr27ob6xFPCEIrbrZe8Ou1VW8+OZFjwaOzPB7/c6n/K6xpBiOA69gwwp - huOwluYHPAMROR1zwDAQhfoOMMAjEXLexefYFdN7cScOMap29x0Kua8JxIsu4q7EibWY/U6ve48Q4CI/ - dzhCsGvHce0AFzF3tQjgoeaqjnFNy/v5VJ9Ex3kC5NGonX5nLRT16naDvAkJwA9EeE7zMiqEEgzEONS1 - OhdmTXwBBNeMi8fY9iBoCkelPxSFBIMxdAoQhwuoZSBaVeTrt6Th53BXE44nmqqOiqQF4Riy+VWPuoi7 - YmGSUKzz2LJ1Ply2zqPz+PmIvB37Q4Z/R1+2oyo8SxOMl9V1FZFqLT8cQQ7z9s1zbJzWEo72k/62A2gY - iiIb2nadbVyok2Yg3l5WHXnTVSFRIS0TGpX8Up2Nol5yn8YkUev+UO8rofaqf5bdT+6FOxY0ml68Ixtf - wYxz4sMRYtpRMdyO6tex+bXMEQ/7I+pLMVhfGluiRMToDANR+LXXiQ9GiKmHxWA9LKJrRjGiZlTf2Rbp - U0S5aPlghK6URsToDMEoTb6LCaHwsJ+8SgnggxHaKedkvYqIcnKgkbr+nzpdaP2dGclyoJH+zuqKGUCh - oFfNbDPrwCOKe1mDvI5ErUVVfWcN4XsYdDNH7+jI3dgNnlMdmDju57aQA6PMdsgh7y3zyjs44Ob1HU4s - Zua+qQAJ0BjqtzEzt4njfr0eKyLAkR+IoId7m6ggrWIgTj/9GhWr1+Dx2PN7Bo3a202ZuHelo4N29hDe - FqAx2uovpmRbisE47FJuGtAojCfRLjzg5vUdngb7DUWVqraozc2cJLIFYAzeOBMbY+rhlGxBcxUwLaIm - z1AXFvmc3c71MOaOqc3FUG0uImtzMVibi/jaXIypzcX71OZibG0uompzMVCbm1uJ7tPmWTBjWI5AJN7Y - OTxujhlrhseZIqqtEwNtnYht68RwWyfi2zoxpq0T0W2dGNHWxY35h8b7MWPx8DhcxLTRItxGx47vh8f2 - jD1kTdBxLuePC/Ip9j0F2jj1o0WCVvKagh5DffSFnQ6LmRnvGDosaqav8HFY1EyvtR0WNdPLscOCZupb - fycKs7HmrD3asf85YZz+coQAF/Ehyp/QDlvqj9R+eMe4pul89vlb8jCZT762pzIxHoRhksFYTboi7q+J - OAYinSfPFTEDw4pQHFX51YxCiElCsegZ0qVDdnJV7dFDdnrFDSsG4+yzrH6HWEfNQDxG5Q4rhuLQu/6w - YihOZG7GWhbrS5xHy5AgFIMxuQ/woQjk6tiBQ24128CXK3rIzngJE3EMRoqriU+KwTj5PjJKvh8RI0nF - OjqOkgzGiqvFTorBOLrpzjMRGeuoGYgXW5OJMTWZiK/JxJiaTH1J5c13iHXSDMXjDOAxyVAs8qN70DAY - hTzYgBWhOLrTyBro4honHvvds8A7Z/qjOtOvJDI2BvZxyK8Tj603ad9Ofv8IfkNOn5hA76b2GOgjN7M9 - 5vj06ir+ubA+DvoZM0km6DlVuPQ7cdqjx0DfOmXY1inoovdRDA40kvsiPQb6iH2OI4S4yH0LE4Sd9Gc5 - gSc4cTvEDO0O033OaN4sErTSmxiDc43E7bX9nbXlX07LyslNrAsDbpYTcDHfR0bfQ2bs0APuzkN9j9l/ - f1nXEPRJlR5zfPK/NsaJOKn8F+NkHdSCROMsUHJY10xNESAt9PxJemieKzlGf+M8ngMN4SiyOqHO34OG - cBTGPQUNUBTmG+/hN93bebOqmWwbzj04koj1U7alvl1lo5C33d8jWeWNaBiXbOGQn/1q7tBb9xF7ZwX3 - zWo/7PYl4eZzm4ciNCuhLiEtnuj2noXMB+pWMifKt3EmrtCdw/QH1Vrs6TpF+bbE2JiW6jRZwKyXB+Xl - tiJ7TyRgPa470d9J6ywl2z3DUBTqwWWQYESMJCtfouMoyVAs8olxoGFMlPifdLQEoh375zG3yXAAkThv - z+BvE0a9Qzjw5iBn/xR435SI/VKC+6RE7I8S3Bcldj+U4X1Q+PufhPY94e53gu9zcto6cJNtdOt5EOlT - xpE7CiyO3jqNPqEM8EAE7onmT8HTzNWn/KQJpQi36xroufI7rqF+q165WWQl2dlxkJG+Rx66F+VTzJ40 - T+G9aOL2uBza3zJqb8uBfS25e1ri+1mqbWzYmXYXyLU7frbd4fl2pyZ9knTzL5rzhDk+b96CPFcGGuAo - 6n5y/Uc2YCYfiOXCA27y8ViQwI1Ba0i9FRSy3sg39KcsPQb6yE9Zeszx6ZdVju9J0DvePo76I9yol3/J - 8NVSF6D4a07UIFamNH27WxN0nPu0Flmyratdsjpst8Ra0KNde7vvj56cp4kNEHYW2UtWHOenNhnH7ihC - cdTnjL4v4oAj6c+N3Zk4kVzHYCT6YlLEMRTpxyEt8m0um+G4aL0Hjqj2mKLPi7twwK2vQt9RdoReMRSH - tdgHtQxFO8hG/J1CWqpA3LZosEuW63AjkatKsI7k7AiO7AbOPYQRP3+Rtbc4sq94NxvPePBnkY61W9Gi - l06TpCboONv1cpyeu0UiVkbP3UYhbz9sSounii63+XCEl7Q4ZDEhtMCPwZoNxHfQERFzHCI4xyG4sxEC - n40Q7NkIEZiNYO6vj+6tH7Wf7cA+tlF79g/s18/dqx/fp5+8Rz+wPz9rb35kX/6+dG0OxIGwjaJeenvn - sK7ZuF3kwbsLh9zk4btHD9nJA3jQ4EXZ76ta7eB0msslxvB4JwJrxgeZ7zn+mdqVMTjX2J4WoQ56oBl7 - zjXq5an0roLBOUbGKkxw/SXjjWbwPebj28fUzbcMDjd2u4WKRhbmJ67ektix0oZ3gqHJ4UbG8zYAD/uJ - z90APOwnnloI4J6feQafTXpWPUxTfTJeqrg45OdcMnzCm/EBL5MET3dzPmclRjCH8M9182Db/fKRs2q/ - pzwbbw2pBXpOxnP5nsJsjGzgwSE3MRN4cMjNeUYPG9Ao5Izmsr05vciT36d30/nkNrmbfJ2OtbqcbZw9 - SHg+XSwouhOEuJK7a5ZOcrYx3xO27DgBhmOVJ00meySrdJMcyle1irfJdrKzl9aj+xBBSTjWa12VT7IT - 85QLwgB42AREXRfVSo4Uk/r8AzmOwQbN5xHm86D5IsJ8ETR/jDB/DJp/iTD/EjRfRpgvQ+Yrvvgq5P0n - 3/vPkDf9yRenP0Pm1Z5vXu2D5ohrXgWveR1hXgfNm5xv3uRBc8Q1b4LXLCKuWYSu+edux69CFRx2n8e4 - zwfcURd+PnTlcZc+dO0XUfaLAfvHKPvHAfsvUfZfBuyXUfbLsD0q2QdSPSrRB9I8KskHUjwqwQfS+9cY - 969h928x7t/C7qsY91XY/c8YN9SD0IN12W1u94na5HW2bo4rfMmxQjIgtt5rIy6irwDiNHW6U8/fy4zs - 71HA24046qw51CVZbdG4XTTp+IlXEA65qz1fXZm9u0ycX1w9rXcif0nkP5Lvo9djAGjQm2TlOvl5HqHv - DEiUTbZmuSWHGLP1SodcFdX4ZWW4AYsiP9+Jp+TnL7wQJ3zIfxXnv0L83zdbllhylvHi8lduPnTRoJee - DxEDEoWWDy0OMXLzIWLAonDyIYQP+a/i/FeIn5YPLc4yJuum1u0TYaWEg9m+59dkvVqrH1C/7RuK0iZ9 - a1N/vDh+2t5bQdUDCi+OzJmMK+8oz9blRYbRIH0rz4jY2t3E2kQhZgOfBu3HJOfZDdq2lxU/t7ksZI7M - cagEiMXIdSYHGLlpgqdHRD6BeCQCM69AvBWhqwCf9e5lv5IOpIRp3B4lH3LLjv7by/inXBgPReg+Sp6r - uiQ830B4K0KZJ/JLjGxug5CTntFt0HCK8jzZVEm6Gb1zmYE4HtWEU1bMWxDgIuUpEwJcdUY6EtrlAKNI - X+g6BTmup0zmnLTI/842eoFUUyXNjiQGDV4UdXBKla8zWWUUclw+/qxMjAcibPOs2CT7hu4+kY41b7Jd - sq52K/kXeubyaMdeZ1v9kFoVNj1DokfSlHMSBzRYPFVtV2XGi9LBjltE3mExeIcPzZqZQy2yt66y7JDs - qo0stGrlrVotXlM2McN4I0JedbNeQnZDqKfEwrRt324S8VwdCj1jNP6ZPIDaXrW7n8xJalmnSrbuAtSf - 0s2G9AvCJjuq+pCeRj3l29SKdfnfVF2HGb4ySdV2Q4eVLNClaEj5BGBt82aTvFb1+P2KTMYyrav9G1nV - Q5ZrIzsYnN9qcZYx+7mX952gagHLsc0bIQsc+UdanG1U733uqrJ5qnYZoQh5ZMiaiF1aFHx3y1sRntLm - OasvCc6OsCwySeq0fMrICWqDtlOondB0lU62OqjrrbMibfKXrHhTK/1J+RKgLfu/0nW1ygnCFrAcxXrH - KjMWZxszIZLmOS3NzDCnqEEBEoN6uxzSsu7yotALSWT3h9SZhtiAuZG9T8p5fqjAiVHmssglr/lm/Mbx - Lmcbq017OjQjf3gsaKbePYvzjLLyTVap7NZcsC8ZUoBxVNYkV5E+7Lm7ntmHtrjzw6AeLCI7yTwejUCt - /zwWNQs59s+aqACmwotTiOd8q47CZqaRxyMRIgME/LtDEdO4YwovDre/6bGgmVNfnDjPeDj/lX2tFuuY - ZVErP5B8mrAtMrFZNaTJeUY1tE9/IepaCHZdcVxXgItxF0zOM6o0JcoUAnoYHVcX9bzkAnhkPBMnh/i5 - o5J5ptSvHqtuZ7V6yauDkL1OecP2lZA9DkKEQZcdudTzHKzxjMda5n31SrtrLWA5ajXu5403XNT3dm2O - /g5VbLK2Odsc1plMmjXJ2VOYTQ2g9kXK1Z5wxy/yvxlpa2C2r2tpyUKTA4zH9Nb/IHstGrLzLhe4WrFO - m4aW64+I7dFTmuTrMjHH17BHKB7rmUUjx0NrxtXaqOflCAHTj/rqp8z+jTorkVLp26DrpLfmPQS7rjiu - K8BFb80tzjNSW8sT45nId/TIuKaf7Fv6E72njB4u3Lu12kRy6gG0ZT9wJwUO+IzAgTtwOOCjhlfy9O2r - N39bqXfxhVA7C+7VkVbFVj+sGu1E+D7C+iJPJou78+TTbJkslkowVg6ggHd2t5z+Pp2TpR0HGO8//df0 - ekkWtpjhW630UEXNcJaj1x/alG87rMVFssqoug4DfM32I0vYcaDximG7sk3qIbD6a0LYTdnlTKM+/418 - L0zKt5HvhYUBPvK9sDnQeMWwmffiOZX/u9Cb/b2df/xwmVR7wh0B6ZBdZOPbG5g27GpxS6VXuqwLNS7M - SrUAaHSNifF9hI0q/NfX6lXvm+niej57WM7u78b6Ydqx8+rOTaju7D/8+sDVHknIen9/O53c0Z0tBxin - d49fp/PJcnpDlvYo4O22EZj97/RmORu/AwHG4xGYqWzRgH02uWSaTyRkpbWoG7RFPX1y93h7S9YpCHDR - WucN1jr3H1wvp+zSZcKA+0H+fTn5dEvPWScyZGVetMMDERbT/36c3l1Pk8ndN7LehEH3kqldIsblr+fM - lDiRkJVTISC1wPLbA8MlIcD1eDf7czpfsOsUh4ciLK9ZP77jQOPnK+7lnlDA++dsMeOXA4t27I/LLxJc - fpOV2uf7rpEmBYAEWIw/pt9mNzy7Rh3voake2qOX/hi/gtwnbeunyWJ2nVzf38nkmsj6g5QaHmy7r6fz - 5ezz7Fq20g/3t7Pr2ZRkB3DHP79NbmaLZfJwT71yB7W9N1/2aZ3uBEV4ZGBTQlga53KOcTaX7d39/Bu9 - cDio61083E6+Lad/LWnOE+b5usQl6joKs5G2lAJQx7uY8IqUBQac5BvvwiH3+E28IdY3H1ZFvmYkxJHz - jMSzEm0KszGS1CBRKzkxe9B3Lma/U20S8TyMaugI2a7pNeOqTpDrelARsoZwNoPLeUZWITQ53EjNLy4b - MNPyjIO6XkZhOUGIi/7T0ZLSf0T90Vg5md7MHibz5TdqhW5yjvGv5fTuZnqjek/J42LyO83r0bads6fh - Bt3T0P1kwVU6fZfZYvEoCWb769O2/W66XFxPHqbJ4uGPyTXFbJO4dcaVzhzn/XImO5DTzyTfEbJd98sv - 0zn1tp8g2/Xwx/Vi/A5SPQFZqMW7p0AbrWCfIN/1G9XzG+Dg/Ljf4N92xW8MADzspyfiVaBV0J+riZ0/ - da2kxpxkvY0P+lkp5CuG4zBSyjNAUVjXj1wx5xq9q1Jj12/kW3eiINt/P05uecYj6Vjn93990wPuNmV1 - W7ggPvJAJVCs9mro+pZzjOSOE9Rr4nWZsP4Sq7OE9JR4vWOsbxxRGYbqQXYVGKj9OANSZDQ654705/hI - fx4z0p+HR/rziJH+PDjSnzNH+nN0pG9+wkkGkw2Y6YlgoJ43eVgsEjmQmHxdELUGCVjJddEcmfGYs2c8 - 5oEZjzl3xmOOz3g8LmRPV3edKcKesm1qd3mKR33fNyST29/v51RPS2G2BU+3gHzL5Xz26XE5pSuPJGR9 - /Ivue/wLMOlWnKM7gpBT9groPglBrvktXTW/hU3kfrUFIk5imTU5xEgrrwYG+FgdPJsMWRd8LVRaqGPv - E4S4kundcv6NZWxRwEuv+A0M8BHOyDIZ2MTL4UcQcXJyeMchRkYObzHQ9+f9H7SFRSYHGInT50cGMP05 - oddekgFMnHsApz8j7a10F2mi94DZZeNfkrAg26WP8k729CcNANubs3Xy++fuRWbCiS0OBvs2q4Ljkxjs - 22ZFtusOS39rxh+wHHKEIu0OBT+EhENu8aPmuyUccjdVbPocDXCUp7o67BP553z8mZMYH4pA2bkBpkN2 - ve3ToR6/l1lAAcdRV5Ds60y9LskJYvJwBGYORfOmWvqrdk1gSjUbMjfrZ75awrg7IpkNPODXI+e4n2A6 - vEiyMDTq1Mx1tcnUm3xFWqv9aKiFGNN48US+2xf6WNnkZ7KuqnqTl2lDvfOIBYsWWYMjlnA0Zm0IOrBI - ETUiYAhHeWLWW7AkHItRA3t8OIJ4j18jhn6N3huE+UtaFjWLJFU1tbpzzRszguUIRKrKmLQyBFiMfZWX - jd6VjRei58MR+Pmq58MRVJaQpTbuxoCqYFyRZD8OaRERrjNYUdKt+q9u16+0JMcAeShC+9Y33dxykFEm - 3DEsXWvAtps6rDIZy7TKn8qDrt91RU/wOSRibVtglrZFLW9EYx1soVXX59Bkyevd5DPFaWCWr200acPJ - EwOYqPndoAAbq/sR7HO0H5bZE1koGcgk62m1iW6yS8V3utOkATu5kJsY5Dus6LLDCjCpbpbO/2TfiUSs - rLsN9vpUz8ksSLJiIetRx2Akcn2CS+xYuh9VZq8U9ZGxTM+peFYpp/sZyf7j1S/Jz53a7ze9PL9IhHg9 - JJs63TYffiOEGi8Fr6UbB7kc/zrCQusamJMA6Nj/1IjLy2ibSYLVhwfc5AEvprDi7L9nb9T2+8TYJt1D - 09XyoVRpVWdCZJR2BzEAUfTOXdTy56JBL3XuBeSHItDuJywIx6DndkwxEEfPp0SF0YYxUeITDp39OY4y - iK2yiYG+5lgA+9pfMPyQBojHaGVt0Ha295+RKhZoOdVua5XuHuneEbkog7wVobvTtI5vD0Eu3YmlHg+A - 4JCf1Rn2WNRM3wwQFUAx8vLlQ1QMRwDGEKRzMTwQcto7sNLVNg9FoA1GeghytXv/0XUtBxnJxdriQCNp - ENJDkItRlTkkYo255cjumMgXVMbm1xqoyo7bzouJdNtNXVECuaxtbufD4gt5yBOI+C5JOc5oXkX79Obv - i8tfk/Tl58VpD0bCCAVVIHGoO+yCMOImVUE2hxhl/yPuik1BIIbaKzAqxlGAxGg7PqRuAkQP2cnjw4Ak - GGtTyb5tTJxWgMQ45uFLVoATPWD/LcqOla+onATkos3F5eX5PxkT4C7oO+mDchfsnWojsSc9WSJrobE+ - C4Jcemsyuk1jkE+dI0nXKQqyCSGyj3SdxhyfvN6GnHJHCHLRU67HIB855U4UZKOnXI/ZPj1rRky4IwOY - yMnWU4CNmmgnCHCRk6ynelt+kUbs6QfTjp23px2AAl7i7m0uBxhpO645GOCj7UjjYKZvzd0dEUABLzkl - 12hKbqJy1GYgR2346bAJpcOGuUukT0JW2i6RLgcYOSVqEypRm6hdIjEej8BMZWSXyNPn5F0ifRKyUkvH - JlQ6qLtEWhDgotZZG6zO2vB3iQRhwE3eJdInQ1bmRaO7RJ6+wdklEoRB95KpXSJG8i6RPglZORUCUgtQ - dom0IMDF3CUS46EItF0iXQ40UneJBFDAy9olEqYde8wukagAi0HaJRJAbS97P0cQtt0R+zkiuOPn7ecI - oLaXup+jycAmyntXLucYefs5AqjrJe/n6GCej7iflE1hNtK7nQDqeDm7PHhgwEm+8fguD/7H41/Bg1jf - TN3lweU8I/ElV5vCbIwkBXc3cD4jJya0u8HxI8KrnwbieRjVkL+fo/ozeT9HC3Jd9P0cXc4zsgohvJ+j - +wk1v+D7OXqf0vIMup9j+yGjsAD7OVp/pv90tKRw9nN0OcfI2M/R5Rwjez9HmLbtnP0cXQ43LrhKp+/C - 388Rpm07bz9Hn8StM670/2/tXHrctqEwuu8/6a6jSZCui24CBCigKbolZJm2BduSItLOTH59SVm2dMlL - Wd9VdoMRz6FepPjy5dfAicZzJBB1wfEcCURdWDzHkeAsaPHm4jlO/o8VbCae4/3fX1DPF8Yhubgv/LVN - IiZ+rXeNxMwonueD39DYMJvLyit5ehXrruDp2dfVdu0VDIrn+ay7kpuByUUWazOBP/WL7tZcrM1UIsHd - mom1OaYRnX/ijCXnGJ0VHGuTUpwNjbUZk4F1bazNWQmXFxZrM+QCI9yo5Vq0suZsqi0rasgmWrGynkuq - 37Kiap+r1cUV+kxdLhksSIwU5NJRmDw9CpOvGYXJ50dh8hWjMPnsKEwuHIXJk6Mw0libHDtjxm8CG2tz - OCiItRmTjBWui/LEaFQuHo3KZ0ajculoVJ4ejcJjbVKK2pBYm/f0sQGLtUmplO1NpnvjfGiszZjkrMuD - Y04ZxoTG2oxAzgnE2iQQ58q/4ar8G2+C29WJWJvkEFhm+Vib5AhWXtlYm+SA3RiR0HGMUdRkTEXvjI+9 - ybVc+UNHWpjoneTfWPROBmW8+KeEjd75OABE75wyvElWZuLoneSQpMxE0TvJEUGZCaN3Tg5A0TtDjjGC - kyVx9M7Hf4HonVOGMUmeAX//Bfeeve+SeiqqozotrvgClPf6t0boHVDeK3QGvsZPDOGNfoJNfUa+CtLM - rYKMDipwsVpCwOQBryk0yTWFZs26PTO/bs/K1hja1BrDq3z97nVu/e5VOHd1Tc5dXaVzV9fU3NXxr6ar - 6r1L7Tozb987+++PxXUdx86bv+l6jdzhE/8/ra79YV2Ypn6zPvXfhS0WZ5DgUzn8V5wuy399y7HzZuTe - 8PjoP+mrPvW/k6ub7eKfwFEqtLk/JboHNvEd1Faf9PJIYQ+AOpri5E632yOaO0NMu04j5+KTE76qDRDI - 8QEQBxDl6Jaa0pezqqxevmhlyhBTp11J0FfkftwR1qOOy7+uAUZ8xnb+l2mAaiBGy3n7SW1OTXlUW1fO - /U9i9eJIGxw7NX8ejhbmLLLz/JhDc9uYFG2vBNjoa4+lecn88+8KWzW1UUVZ6tYWwE9m5xxRTv7nmPvl - VRylIlu70UrXZffRYmE7Ezj1f1GbS73F7sOdCU1t0RmtDroA3oaYpNY/+/Pf6v78ESkBJ87zxjZHXSv9 - 3r6499DV2IutMZrylqdK17Z/onh4lwWqVL7u9fHvJ1QRpQ3pXKxyX4amU+5UrGtKSLMKNKn8KmMuuvsl - d5NVpfLt3Psoy8aTKaup9rXM6smU9VKveJcHmHdn8lKSqVnvLyslGVJKstWlJFtQSrJfU0qypaUk+3Wl - JENKSSYuJdlMKcnEpSSbKSXZmlKSMaWkcS2ND1UW5UHf2v5boE/G0yk70GqPwITTaCtSOi5tVOeibZGX - PcFHOfQNRcFteHC8EeiKBFjk8x2/Psoz7pyivFdw5Q+ON56RcIoRSJwfKv+O7IQyQUaPD+7n67mjK2h9 - VKrNZbfTfqTCNV99M3txsX1umuQq2SOq4/eI6sZ9nm6RJoHvC8dSs/uz8EE3wLYwg/Le9rZkRFl3+4y7 - e2dJDpGEz8vX0aorfkiyuLMp808ts/7U1AhH4yEQcf1UL39kn9S+sAfdfe7jggFShubsPqqWzHwnOWvt - nmHW6a1QTXDO745lPpHQT3DOb8rCWvlNJzjr/95J1QM5Wk1WieYmQo4xSuYmWHjiPhQv4iEmFiZuH35r - hZ3Did9HC1/h5/CJ3/1b6xbax2XKBCZk/PgBMA7V2g72eIi6Li0iubSE3gHt7yE55YGG0JCc8Nj49QOg - DqNM01mNXMiDISagqXhLHdKqvpxOmKJHqGf5fg+31IRuG+R9cKlDGn2md4T1uL6aQOUoarssH34fkhMe - 6FvdUod03xvYXeoS0zww6jtUO+h8fHpqaKAy45MT/urn7QBBn54YkAjQQ/KRt/4R933s5bu5TJnRdL1/ - FPEZdAalXskMesiljW9S5VvaCRQ2Bp14X1XhW87V4hp1JKjlZBHDyRJ6Uza1Afg+PTGUrmuLGPr01NCd - fHTiLbC5FKUiG1C7j0Rk6fr5d1B0g0LXFrPQJ+waJa695f4NSB4MMel3q44XQHMDiMN9O8xBGwue0BQj - vmrbAhqXmtL1rkFwlzzgD9XGx+KsP6DTmGDE5wvoxRR75E1+MMRUF2e//UVtbFf4LfoAYYhSr1FV8Vmd - KoPUGxMqsJVA2/IBEEdTmtbPLbs3BHkGUyz21U0/toT6Boz42rICNC41pYfhXtGTjGHOPQwgC8R3klgN - WKhMVKoM/GUz0ZetabudYDIu5Fjjqmm4Zx42R8kEXAJn/aumwp552ByRSbAAY33I9FeAsT5w4ismJ9a2 - 0EaVm/K+qmSxNAQjp+1es8dalX50xYByxhDmAo6fEyh0ie5A4up9723IBioXHMy573dF5J7Ao/tdGAr/ - PRkJfziy18jWDATiXL7s9kUX3URkRsHl0760L36fkTbDMxjZWfPrCvMra37td3X006+CGz6lOftt7xUf - Kx53j+y8GdqyLyl4koc5+7W04LZ6z01srsv3USIQ57IN9OmLwMgJT4q9J3eoGI6YEtzdKuQmRv/Ll221 - 9x2rfpawOO2brrKHxf3ftIHP5aq7avcBrcpM4IG/7fymLP2MojEKi9GXFAR59FPO9r2vGwxmpyjj9Zn6 - msG+w94RpV4/3tLXwO7gQUPeAI28t9Unrnuva1MBQ0AJPPK7POEtzRg08p6a5mhcN/So1db1SX1PF9Qz - hiiXWwcaqPYo9vtv/wM/DBrFrZQEAA== + H4sICAAAAAAC/2JvcmluZ3NzbF9wcmVmaXhfc3ltYm9scy5oAKydXXPbuJZo3+dXuO683Kk6NRM77bT7 + vim20tG0Y/tISk9nXliURNk8oUiFoOy4f/0FQErEx94g94arTs10LK21KQDEF0Hgv/7r7DErszptss3Z + 6vX0j2RV1Xn5KESR7Otsm/9MnrJ0k9X/KZ7OqvLso/50sbg9W1e7Xd78v7MPV1fb9eV6e/nLxdXVh6sP + v/62uUiz83e/XqzTzdX5u8vLXy8v3n24+rd/+6//Oruu9q91/vjUnP3f9X+cXbw7v/rH2e9V9VhkZ7Ny + /Z/yK+pbD1m9y4XIZbymOjuI7B8y2v71H2e7apNv5f9Py81/VfXZJhdNna8OTXbWPOXiTFTb5iWts7Ot + /DAtX5Vrf6j3lcjOXvJG/oBa///q0Jxts+xMIk9ZnalfX6elTIh/nO3r6jnfyCRpntJG/p/sLF1Vz5ky + rU/XXlZNvs7UVbRx9/31Hj/a77O0PsvLs7QoFJln4vjrlp+nZ4v7T8v/mcynZ7PF2cP8/s/ZzfTm7P9M + FvLf/+dscnejvzT5uvx8Pz+7mS2ubyezL4uzye3tmaTmk7vlbLpQrv+ZLT+fzae/T+YSuZeU9PXuu+vb + rzezu981OPvycDuTUXrB2f0n5fgynV9/ln+ZfJzdzpbfdPhPs+XddLH4T+k4u7s/m/45vVueLT4rj3Fl + H6dnt7PJx9vp2Sf5r8ndN6VbPEyvZ5Pbf8jrnk+vl/+QiuN/yS9d398tpv/8KnXyO2c3ky+T39WFaPr4 + T/3DPk+Wi3sZdy5/3uLr7VL9jE/z+y9nt/cLdeVnXxdTGWOynChapqG85MU/JDeVFzhX1z2R/7tezu7v + lE8CMvRyPlHXcTf9/Xb2+/TueqrYew0s7+fyu18XHfOPs8l8tlBB778uFX2vnLoI39/dTfV32tRX6SGv + RV/FdC4T4stEiz/ZufGfuvx/vJ9Lp7x9ksnNTfIwn36a/XW2T0WTibPmpTqTRa9s8m2e1UIWHln4qzKT + mdCoIiYL9U6oPyhR3qi7VZW4anu2S9d1dZb93KelLoTyf3kjztL68bCTPnG2yiSc6UDy7v3Pf/v3jbyz + ywy8nP+b/uNs9R/gR8lM/vR5+4Wgw/ziWXr27/9+lqj/s/q3nprdJ9tE1jLwNfR/bP/wjx74D8shsoZq + 6ZDec7O8XSTrIpdJlewyWT1sxup80rEydKBHZPVzVnN0FulYVV2YrA7brSxuHDfA2xGez5MLfsr6NGBn + alEfO6V92rPHpEQ4HR5lmW7yXaZaNprXID3rk2zhiowptmHPzUoE5NfH5Fk4x1RdkZd5k6fF8Zckm0NX + 81ID4ao+7nQ+T4oq3STKoHo3sis2NhDE9ub7h+md+kBdA6XKdLne+DD9ktRZF28huwuqTRxphVjAvMqr + KLvD2xFeatmKcvUeDLkjLh8U9DHUH69nD7Lnkmwysa7zPaVIwjRoV/VDepD1fJlvGHoTR/0r1VvhuRWK + etf5XvbvI668F6AxNvljJpqIGL0AjcF2B5zffyZlusuY4o4O2tlX3cKoe5f+TGSVLXjl3THgUfIyNkpv + QKNEZEEw/ff1NiIDOjpgr5pqXRVJRISTAY1Sb9cx6XPEUf9zWhy4cs3i5qhyEyozuUhS2a4xzB2JWVdF + tf7e1Xc8u2kAo4hG9gjTesPNVIt3Itx/eUjSzSZZV7t9nempGGJ3cEADxNvWWQZ8U5AjYiIgpiwf7+jp + Z5Gw9U1+COJBIuYbVoB8g/i4yQKlyvIvVQ7eJeunVNbi66xuSGYfB/3ncf7zIb/+xMqRtHhkBAI9SMR2 + mHo9YYU5wrA7+9nUaVySeQ44kmh/JidAh/re9VMm68d9nT+rWfbv2SvV7gmAGG1/Vf62x7o67MkRbBzw + F1laG6knyBFcARbDzSdmJE+DxdtVm4wXQpGYtdLjKua1d7Dvzsp0VWRJtRZ71SjuCznQp4aAHGgkkT+W + WVcLqKkLCez2ghkSlqGxm0Ko/CvLjNzdxCR+rG1xEE/HW5f8w2wasMv2neyUjG/SjbhKuXybr2UtQLW6 + PBZB3S88tyJDVt7N7PJIhH1apzuWW5OYta1xGTW2g4P+9kYQjXo+Q9cbNGI/lfpkvWIFMAVIDN1sCJa9 + RRHvsTuQFLloWHrLAEeRf0oPhRySpkK8cFPJk4yMlRxEVm/SJn2ToCcbHD37mXBDdSjqLbMX2W3YZD+Z + 8hOPRYjsDYASOFZebqtknRbFKl1/58SxBHAMWRkU1WNUFEcBx1ETXbqG4N5AlgCPoadzWNMemASJJbMu + PpYrQWIxeoRHDjYye4MGCnt/HHL1SPvp0GyqF1aS2AY4in6ekj5RZ588GrZ3vSdZnuUwh532vgWORnyi + CaCItxCylpHfWX9vb1FWZvsWOJosvvn2NaoWcRTBOJts3zxFBNF8MAI32w3c9+snot03imqdsu5BUOLH + KjM5sml2+2S+IE+AmCxkfqELX3xPne2q54w7wWHTvl19kKTrtcxpqtpAg97ksao2EXLNhyPUWZk9Vk3O + GGAhGiReW01tD0XBitPjmH+VPOX0zpLJYuZKDgrWvEzu2LCZn82mYCBGbEYDHiSiHozo7BL537xgtiIQ + R39xxY7R4gG/6qtH+Fs84O8qmYgQJwMShX1TBO4ItQA441lbFPGWh92K+EjORhGviC+RYkyJFHElUgyV + SBFXIsVQiRTRJVKMKJFdr5JXfo4w5G7edQs0k31VMZoZm0cisOYLRWC+sP3sOHkjeOoTjviPfV/2/Bts + AaOds9PoPJBG8rND/cypdU5o0MuaNnB5JEK2fjquvZTN6DZ/5AeDVUhc1hxxTyJWkT+mxSMvIzo2bOan + jilAYsQ9YwEUSJy3uOPOR95xiRzSVi/JofxeVi/qgfW+m/XhZBIuw2JHRhvjF1mhOp+cVsk1wFHap/4s + fYcGvNz8H8x3/Xnk1AjmQSLqKeW03HCe6nsCNAb/OY4Yfo4j+tWuzJrGxBF/1PMcMeJ5jvGdmMJrGZAo + h7pWX1J9L24YW4HFkUV915VDXhRDAMeIfgImxj0BE2/6BEwQn4CZ3+9u633aPImYuKYHiVgJXZPLelZP + TPPS1pXAsbK0Ll71c7pu3QOnKQcsSDTe00QRepqoPtymhcjUmpS6a3azTdK9tKtbLU7AISd8JY91lkos + Ii1tAxwl6nmjGH7eKOKfN4oxzxtF7PNGMfy8UbzF80Yx7nnj8Wsik+3ytk4f1au03FiWBIkV+2xTjHu2 + KZjPNgX6bFN/IuKKl8kPR0jS+jE2inLAkUr19K1Nxag+NuQZiiiSdPOsFmiJbBMd1pHBsfUSwDoT+6oU + rEJhCZAYvCffIvTkW+jXSE6LYTnL/VELEk18P/UNI4o6oMHjHec1IuM5GiRet1UGJ0aLwt4fh3wdkT0G + jvoj1j+IEesfRNT6BzGw/qH9vFFjwKqUfS/xlF5cfkiqrTkSEbyoQ1bsarqerextyjv7sMt40V0LHO1Y + OfbrUpk1HyjCYsauNxEj15uY31OD76psZAUdE623hKOpG3/zlHFXuwRUSFxoZTe7K4jb8Oh5+aheTalq + 2bff6f2LBDc0oELi1s1eNbfbvMh40UwBEqOp83X0BI1vgaN1C4/U64IR1bZvwaKxS2ewNNoz0jGjONiE + RlXdr7a9VS+WcbuqoGhszJjuAm4LR2/S5iBif+1JMiYWr5FwHcFI/Rq8uGiWZ2RE8SbxRDDaQU2LyPon + ItRRgcSRdfbmiaXXZMgaV8xtBR4nW/OvX7G4uRYpVyzRoDc6aUwHEqk+8JohDcJO/jR3aH6764W+QccA + NgWjslbNisFVswc15N5SvS0F2OQ9/NCOgv+gP8Ky6SF7MlncnceF0IrBOKo/FRlHKeA488UkLsEswYgY + 7GTzLWOicRPPt8DRIl5idPBBPzvlXMdwpPZBLjftYNNw1LeIh0dSQ792W8rmNXnK6XPgoMSONb3+nCym + 8z+n8+T6/u7T7PfkdrZYqvfpKcFwy6ho1Nd0A5pR8YhL+nHLqGj0BiMosmN225Mlaovc04O1/kEiJeqA + Co5rPLNcp3s1POOE9C1wNGpBMTnMWO2S1WtDm0Dwadjevj1N3toHwAN+3tQWogjEYT+uwC2BaPssIs0U + POA262ARFcgyDUVt54Lj4rWOQKS3mQ4cqQxcRzsWZsdscdTPWQcB4EE/6+1qzIFHoi39tEnculO7W9fU + pXGwAY9y2lCO8fA85MEjdlMsRb7N9AouatdoyBWKvMv4kXZZ2EyciwVw3B+ZOcE8eUpFbOXmKPA4/Cql + p2F7LtpHZdw+jMnDEYjdTgODfXpNNq/q6NCgN6ZX4SjQODF1uBiqw8Ub1U5idO3UP33hxgmVUBFRA4lg + DSTiaiAxVAMJOZYoNslKva9WPhaZGpmyAgEeOGJT8Xv1RzZsTrZVHZHZgAaORx8+2qRtpb8iDr0ZHrFD + Y3B3xoidGYO7MqrtAdP9vsjb/QNUgW0o+7uHHH4k1k6MgV0Y1Udqlqh7AeOw+le2boQqQbIXTnvQMKBy + 4hbqS2qb8m5Pe1IkFx5wJ0UVGUAboCh6lN5N6qsmumjocXwHFKl53WfstDLgATczrVyDHaVdSfOUkxLn + BDkutcCp3UyRZOsxxxezg+fA7p30qwSuL2Z3zoGdOXm7ZGI7ZLJ3xwzsjMnYkgLciWJ9aJqnujo8Pukd + b4uM9oQCwG3/JiuyR3XqWrKuMz0lnhaqB0HqQaMSJ1alj2GRw5nvpB9hco5RNueMF7gMzPa1c66nNdnr + 5qfapy3T51ipMR8lyJALiqxne9vOBS0HABz1q7dAVFtNrpIxhxMpcj/Y4b1g32wfWMIesNH7v47Y+zWr + a9nvZR6g4sGO++e+qvUSHNXS7eTNWsublBQANNhRqM8i/GcQp4Mf1eIkvYk/xefTrr15Z75sTLvJfBqw + m48xVedCkCN4BigKr1kN71zbbsrfvyZy2kaInkqgBYjGfn4y9NyEtwMvtvtu/5whdsQUNmFRuc9lxjyP + 6b/TNePdjvrtmiJmOFCFxXXXMTFjehogXvfmSZ39OMhqXlb6xP1cUAkYK2aZPaKA4rzJky3SE61HvZUH + fdc+k/OMSbdEgyg8Yr6PuarHQQFvu2R99Uo/tAfAUT8jB/HV9MydsdFdseN2xB7aDdv4vJY9/2rHlLcw + 4O42O6AvQ/DpgL0/ooQdolfgcfqjdplRTgIwxnNG7OqaHGakHo9jk771uAcCY8YewH2/N/ahRvAEQAzV + hSd7FQS46M+Q0Of/xgfJX5fvfksWy/v5VK+myzc/mSEAExiVtdogvMqg2359JxJx2KtBDV1twL57S75b + tsB9Iv+Ri6eM7uo438je22FgH3n98TO5XZGI7zkN3JIiI99jFuy72ftBDOw9H73v/Ig956P3mx+x1zxn + n3l4j/l2Z9XjuC9pqu9ZmazkraimDjijsgGbH50xm4vubK9X4hwHUfStEwE84Gd2WF0eicCtVCwYcx+K + IjaJHAcSSb+D38jOndBTUroICFY80IREVYOjtDnUWT/EZMUEPFDEtnjzeqg2DdhZhwjZJGA1ltWTvQYb + NpOXtoECPwZ/34ahMyv0JtCrvKI6FQOYWDs/hE69OH0m1IxGuc5Y4iMMuOkdohrqEYlsre6afn9zPXXG + 68KFXFDkdr7XejueHhKQQLHa2SXWuNeCUbd6pZJx79s0ZueM7HoyZNWz4Xy1xiE/a4SOzmKJp7RWc2i8 + yRabRu2MHX59GrLzaj+83gMau+6MeXIM1DQuqhocsApQwDUuMuuOQDxARO6OH4/h3T6MleDpY5aI77SV + ugAO+NmPU30ath/K/Ad9irYnQauxY8PpERQjBKQZiscpwb7BjxKxRfHgyU0xpzaFT2yKOK0peFKT8SF9 + cZwHg25Om4OO2l8YvcsXsHf5Qu+rvUB9tRdZZWXsDqVN23b1zkLsU1jMYUfKS+ZboxboOY3tX4lSg/Ss + cmxO1SnE8YhkI2sLkqdFPI+Ss6YbXNYztz06orKFfBfQzKrNRvaCmggBkxfVnsHiLbMIaOx4qq9y2G+I + c0o9ZduKfFWn9Su5uJmcY1SH2fUPA6kjKwAH/O3qqHa5miDrLdq279LHfH2abzltUNeQyicqcWOprXvT + IqlkUaZOAHiw7eaeFYifE0h8s8t7o6s87OzhOSnffNq277OM1MlR33cNOrtoEo04nrpaq3OT9FTkvhIN + b5FsQAPHk5X2+Xv9iOxY4Ogv7gy5vMjP+SZrL5Hapnqw7W63ZZVl/PSrk22RPz411OdIQREQU899Fdlz + VpCj9CjgbbtAPLHB2uaaWGnUXj3BPKQQPZPQ+IBzRwG469eLtIzcVLO/ghYDVLhxhPuQ/1/E9f+Iwo7T + bSrbr6+kRPBg1622hZeRi/blGJraZl2zWiuc/521W5nkRd7ktMkK2IBFichtVOLGauu5OqO+LGGTrpVz + fh12dl3EuXXBM+v0h9QHGicIcEWdxDXm3Dv9nRfOFb9AV3zOyqNzJI845+ahZ+bFnJcXPitPfwq96UMO + AUmAWOR1Ati5eNwz8fDz8KLOwhs4By/yDLzB8+/iz74bc+6d4K3nFdh6Xn1KXHuStZrHpF6vxQJm3gl5 + wdPx1If0GieB6hvO8WHouXdRZ8QNnA8XcW5b8My2uPPahs5q0593h2ezCpcFA27uqWkDJ6bFn7I15oQt + /Z325TV1tGl7iBQ5iCuAYmyrep3pSTM9+yTSR0YcQALEoq+ORXdWEeQVnwJY8an+FtVrbYb6qxHrPwfO + 9VIf/2vz/fw8eanq72ldHUpyeri8H4G9enPgJK/oU7xGnOAVfXrXiJO7ok/tGnFiF+e0LvikrphTusIn + dMWezjV8Mpf+RnMgS5uD72G/ADlw1hXznCv0jKv4863GnG31BudajTrT6g3Osxp1lhXzHCv0DKvTAVTm + 5rD0dwsDGiQeL7vRs7JOH8Ys4kUlSCy187MaeK7lqEXWR/sqL3mpBonAmMwVVUNngPHP/wqd/dV+1k+n + cup5l4civOXJYpxTxQR9RaqAVqQK3tpBga0djD+Za8ypXPo7T9nG6C3K721zchMJSqBYvPKPl/y3ed2Z + cqbXG53nNfosr6hzvAbO8GpP3mKMcZGxbdxZYGPOAXub07PGnpxlHCX0pB6iUtduQjwaIWYNoRi7hlBE + ryEUI9YQRp7iNHiCE+/0JuzkpshTmwZPbOKe1oSf1MQ8pQk9oSn2dKbhk5n0N/xX9ciVGeQAIlHPf0LO + fuKd+4Sd+fQ25z2NPesp5pyn8BlPImY9rAivhxX0VacCWnXK6mnAvQxy+wi0jepPjD3WTA43kje79GDb + 3VTqwT1/tRXE2xH4Z3qFzvOKPMtr8ByvyDO8Bs/vijq7a+Dcrvgzu8ac1xV/VteYc7oizugKns8VezbX + 8LlcsadjDZ+MFX0q1ogTsdRKleQpK4pKDbfr1+OaKGIY0GFHYsxbgzPVLyktEdT3HYNaREdSKMByPF+8 + P05EkCfQPNYzs5SIq5vFZCkttjcvbxe8H++BtpMugyysH+yBtlOdD5asDtutLJAMM4Bb/ufz5Jydoj7s + u3lSzMZNYR923RcxqXARToULphSzRaTCRTgVItIgmAIcIWyK+O3IL99c5IlxmsNYp4OhPsp6HQDtvfnF + hnOdDob6KNcJoL1XtvrX828Py/vk49dPn6ZzPZRvDzvcHsr12BgDmqF4ahfgN4h30gTibbJsry+MHepk + CERRL0KUh6JgBzkKQjEOO77+sAuY9wfxxFYrOOAW498vgdiAmbQVJ0xb9sV8+SC/f7+cXi/VfSP/89Ps + dsrJ2yHVuLik/A5YRkUjloGQxo6n1nbOHj6f6ojdnnrnYwosjlpt3GS8AC2Lmg97pvawx5zyTxueVJGY + lVNofRq104qmBWJOagG0ScxKrSRc1PLqDSzvJl+m7KKMGIJRGG0zpgjF4bTJmAKJw2mLARqxE28kG8Sc + hOMNPBBxEl6TdTncSL3ZfRhx76s9PxWOMOam3fI2iDj1CuqYG9MUYDEI2495oO+Mu/2G7jxu4cDLBa32 + PyK+h1u08FIlnvItOWc05LuoLUcP9a7J9bUchCU308X1fPawpB7ejuBB//hNGkA46CbUXDBt2KeL5PrL + 5Hq0r/u+bViv1klWruvX8Yc5Opjj267OL65YSot0rE3NtVqkbd1kZF2H2J5sveJcmoE5PoYL8lTsvKgC + eSH01u/6A8qbUADqe7uAHK+B2t5D+VKne6qypzBbsk83m/ELqkDYdnOuE77KiGvEr3Bxd55M7r5R6sce + cTwfZ8tksVTfb49VJBldGHeTmgqAxc2P+rXDhivvcNzPV4eslObHR3EvYYoKQIPemFQWcCp/eWAXDwtF + vdQrNkDUSc46k3St9/e308kd+TpPmOOb3n39Mp1PltMbepI6LG5+JJYxG8W9OVsbSgdqdtko7hX8VBCh + VGiq5OMd16xhx/2JWcg+oaXs9+mdjHc7+9/pzXImh4Lp5l8kM8APRKA3TaBhIAr5loEEAzGImeDjA35q + cQf4gQj7mrBEBzcMRKHeXgA/HIG4xHFAA8fjtnA+HvTzyhXW2tkfM8sU2urNJpfcVLFR1EtMDRNEndRU + sEjXerec/q6eAe32NGfPIUbCYx2XQ4z0PDJAxEntQhgcYsx5whzzkXO75xCjYP5mgf5mVfUcZFX64Reu + uMMRP70rYpGO9e7r7S29MJ0oyEbM9I6BTNTsPkKO6/7jf0+vl2pnKMJCX5+EreS0MzjYSEy/EwXbqGnY + Y67vejntJxaIVaQLh9zUytKFQ256brl0yE7NOZsNmcm56MAhN7UKdGHH/SD/vpx8vJ1ykxwSDMQgJryP + D/ipyQ/wWISI9AmmDDtNAqnBT4dgClBeHgVQx7uY/vPr9O56ypmMdVjMzLUCxiXvMpfIFbbFrU2bdLOh + WR045F4XWVoS62lIEIpB7Y66MOymtlxom3X8gLDaxOVgI2UbMZdDjLyc2mD5Q66y8Jq8n/B/x/7hJxh1 + nw5j3qXiOzOE5YAjFVn5OP4dWZ+ErdRKF21zug/oU0UmGHAm409UhtiwOdnuY+QSh/2CV8sIrH5RW/wy + he9QY7J6Te5mN0xvR+P22LtDjLo73G8lqVi/RTTlgSPKAe/X5acrTpAORbzUDovB4UbujX5kHfPywzm3 + urZR1EvstZgg6qSmgUW6VuYzliX6jIX1YAV5msJ8hII+N9EfbPLtlq5TFGSjFxzkeQvnIQv8ZIX1OAV5 + hsJ8cII+LWE9IkGei8Q8DAk/AdGfyurtMSuzWh9LsFE7VdEj+A430reHKbm/fYQgF708HinIRh1fHCHI + RS6RHQS5BOe6BHxdal91luzcsX29m/05nS/4T84gwUAMYoXh4wN+aqYBvBthec1qIgwOMdIbCovErLu9 + 3qYuaXjqE4746aXEABFnzrvWHLtGcinoOcRIb1IsErFSqwWDw42c5sXHPf+nK3Y1YbO4mVwMDBK30guD + iTreP2eLWcQ8uI8H/cQEceGgm5osHu3Yacd1G4jjafsfjRz+qM1CST4bxbzP73nS5/eesUmqFeX8Lgdz + fHmT7ZLNRU6yHSHERdkDwAMxJ3HaxuBAI73gGBxoPHAu8ABenTrMgZMlLYcYyfWGCSLO/GLDUkoOMVJr + CIODjLwfjf1i1s9Ffqva/IJ1n3Qg5uTcJy0HGVnZgeTFPiX2PE8UZFPbFdNtisJsybr5yTMqErIeSt5v + bjnISNv/0+Uc427V7bpIfvZkkZi15GtLwNs2XzK9/6bd0QbnGGUveZc3+XNGryZs1PUemiSraHPSHQOY + GK19jzm+Jn28oL7o0TGASYw/StpkXFO22xd6/0BqJlikYf26/CyB5bdkdvfpPule8CTZUcNQFELaIvxQ + BEqNjAmgGH9Mv81umKnUs7iZkzJHEreyUuOE9t6Pk8XsOrm+v5NDjcnsbkkrLzAdso9PDYgNmQkpAsKG + e3afpPu9PtYpLzLKdvMAantPJxitm7qgWC3QcRZZWifbIh1/lKaDQb52Q1Cm1YAdt9roRB92rL9CMtuo + 46Ump5+K8i96uKgPYyFupooKkBjtaeCPh7ROyybLWGEcBxCJeHi3y9nGTXU8U5Hi6ynbllVbikZ+3ebV + jjCkx8gW5LgKwi4nJ8Bx1LRcdOrJ7i9JWhRUi2Jsk15rQ1gKZDK+afw28D0BWPZky9635GXeUD2K8U07 + NQnBSKMjBxv34zuGDub71O4usryOXxLkgb6TWac7KOZVh4iO3yYaYn0z9QQBl/OM1B/u/Nqn7OfmsCMV + 5g6xPSqDSlJZbgnX0pBbviNjm1Qx1IdTlbQUMjnX2DyRq8UTBLgoHTyDAUx6AynSyywAinmJ2WGBiHMj + OxJ19crSdixipt4QFog45SCc51Qg4qwJh+p5IOIkbSbvk761ovdIDMz2EQu7V85VI7DKq2Sf5jVRdOJ8 + I6MDaGC+j9a3aAnAQji/wWQA057s2fsWVSeuDluqqsN8n6jW3zNyoreUa/tJ9Px0DYfdKqvJ96OBgT51 + R8k2hKHsSNvKGPiAY559RSoQ8usOr5YjkApCSziWpiY3K0fGMREHOntvnEOt3P06nVp0/DLTnpYqynOq + RkOAizPLY4GuU9BuVw04jhfeVb0g1yQ4dbeAa25BrLeFV2sLcp0tgBpbncixo0kk4DrotasA61bdhysI + p0pbEOCSSa/Pq6SWAQ9G3GogsCfskwrCiJvthZ3UkboAZzMEeTZDALMZ+m/UEfQJAlx7smjvW6gzIwKc + GRHdhASx92JgsC+rtmqcf6hLjranfXtJWEpgMr7pNA9BLiE9GbASZ0ZEcGak/1Tss3WeFjx1B2Nu8gDJ + QX0vZzZHoLM5p6FYd0IT6RE5KnBiPFWHYpPIEREnpV0YdJOLXI8hPuKDFZMDjfSCYHCusc1J+RlNeMIc + X0nvYx8Z29RkglGx95RtO6hjn0lX1RK25Zk6f/bsz509c5LoGU6jF8bA6gUcWZGLFFCW2luX+MjkBEEu + TpfbJg3r7eSP6cXHi8sPo20nArIkn/KSUP04HGicUToNNgb6vu43lDlVFzScd8nH29ndTfuef/mcEXqT + Pgp7SbeWw8HGvHxOi5yUBCCN2pnJkAdSgTLPaGOW73r5V5KNP9yjJzwLMVuOiOchvJzWE56Fljwd4VlE + k9bUq9GMZfp9enf9Ua8DIah6CHAJUhqdGMv05f5uqS+YsujR5WAjsShYHGykZaeJoT5VyYiG8gIoKsBj + bKs62VWbQ3EQ3CiGAo5DKwwmhvqSQs2TbJjajrbs6UokuUheqppiNSjbtiFZNh5NvpAOsT1ifbEqKRYN + WI5VXtIcLWA75F9ykkMDgIN4LIDLAcZ9SrftU8+0Xq1Y19ZzrnGTrWkqCbiOJ8IajyPgOoqM9cNOmOvb + 7XOaSQKWQ68DJCj0930DZXt+kwFMxOakh2wXYfHHnf0efvtvap1xRGwPrbH12th1dShVBfuS/J3VlUow + QdJ5tGWXZZxWG7WA7cifKYL82aWp6XxEbM+BktvWW23y31n5lJbrbJPs8qJQjz9TXcnV+U729JtXPXlA + 0I/R2fF/HNKC1UFxSNv6k5Im8tsWTbwLvftvW1c72ZEpm8dql9WvJJVFWtbHNaWoyG/b9PGtVZUXWUKq + zj3WMTdJvV2/v7z40H3h/PL9B5IeEngxDuM3W+4Jz0K8446I5ZFtG63uaAHLQXoYcuc+B7lTfUVZpxF7 + xD3kusrsMVWvTNFkR8q1VaROawt4jpJ4MRJwHfvq5YImUYRnod8xBgXbtqmstdS8LE9r4K6fWMChMYf8 + m2o0aRZFWJYio90k+vu2gXQS4wkAHOdkybll2aW1eJKtDWlFh405PvGd2qM5Mbap2hDHiB0BWZIfh3z8 + O7Eu5xlprXBHQJYL3SbSXS0HGZnCsI/VjYEFeAzi/e2xnllPvQrqJXcUZktWhVoMvuFZjzRqrzZccwWU + fHI900OI65wlO8dsrPvSYhFzhBjx7g4FUScJyMLrQPuw5yZ2Co6I5xE/aqJGEpCloWv8cicOK6rmsIIs + rCJx4jwjo7rya6l9TutKtIDtoJVLt0zKIkX9JR1ieWiT++6cflnK5KHw6vu+gXoH9JDtOuyoXZgjAnqo + CWxxvvFV9o+pNsVYJtogxB2B7FPV4qjOX3Io1V4kpPYQoG07d44mMBtD2tXu+H3fQFkw2CO2R2SHTZXU + KemJrUFhNvV/HjOes2UtM/ECvStjXVLgWto/04aVFmcbqT2j2u8V1eQeUQ30hojH4PaEZ2FMdZiY56PN + SwlgXkrQ56UENC9F65G4vRFiT8TrhdB6IG7vQ/UgqGnQIZanqRLnaFaC0YdBd3fWGkPcka6V1dW1OMt4 + oE0IHNzZgAPtAdLBfYJ0oBWFg1sWntPikBHb3hNjmYjTWM4c1ukr20O5bvKqTJ4INRBIQ3aRFVtaG+6j + hvfrp+TL9Eu3xctopUX5NtIjEYPxTY919UI1KQY2tWcMcXwt6VspXfQe8T3qhan6mZxoHWb7dtmO8pTv + RNgW0dRES0t4lmKdNkSNQgAP4Qlxj3iekv6zSuh3lUVWUj2F+V7n9cePejqUMk1sMrApWVVVwdFpEHGS + Di/1ScRarRvyftOoAIuRb9rnpA3hTWHcgEQ58BPogKQQaUhqQb5L7NN1RnVpyHcdzj9QTRIBPd0ZV3JI + Jz/6OX64G1CAcYqMYS6g335BzmOJgJ7o3+4rgDjvL8je9xegh5GGCgJc9PvkAN0f8o+Ma1IQ4Loii64g + S3SmXoXzlHjGooHYHsrbp8fvO4ac+BKVBbkusU7rTbJ+yosNzWeAtlP+Rz5+Z4CegCyUzaJtyrFRdmU7 + AYCjbTjUoH78nnMgbLspi0yO3/cNCbnk95RtI/Svuq/bPLFPbSC2hzIsPH7fNCy67lVWq1H4JqvHyzwU + 8uZNt9fyUyoos164AYiiekHyEmi9KJ+1zWqfrTQvRbfq8pVSnUC0a9+/UrtRJmXbaHXmwqszF3p1WFq+ + Evv7Nocbk6zIdoQd2DAejqBKYGwU1wFE4qQMnCr0kZADIk7u7x/83Um+2xf5OqcPiHAHFok2WHFJxHrg + aw+Il3zzniDfVaSiIXX0LMz3VXs1S0dc5QXCA25WMfYNQ1F4g/Eh01BUXqGBHH4k0kj1hIAefsceVYBx + ioxhLjLAdUFOVGekevpj9G8Pj1S7L1FGqicE9DDS0B2pLqhLyA0E9DCuyR2pdn8mV2BQ3RUzUsUMdhTa + WGLhjSUWapHwcSHDqe3JHmmdZ8zhRdIvqjudYWIgSBGKw/s5vsCOQRozLdwx06LdnUi9KkOxnCDbtc+y + 7+2lNikpNS3Qdorv+Z6iUt93DM34J0rH77sGypORnjAs0/ly9ml2PVlOH+5vZ9ezKe2UCowPRyDckSAd + thOehCG44f8yuSa/gm9BgIuUwCYEuCg/1mAcE2n/k55wLJQ9T06A45hTNnjsCcdC2y3FQAzP/d2n5M/J + 7VfSKaw25dj0HgGZoOW/CyLOour2zGSJT7Rjb9fyFfn4Z/wOZvjmt8nNbLFMHu7JZ+FALG4mFEKPxK2U + QuCjpvfbw/I++fj106fpXH7j/paYFCAe9JMuHaIxe1oU448kA1DMS5rh8kjMyk/mUArrOWPZtPLMRxqz + U3pRLog52cUhUBL0Nijq0TQ7JUwDFoW28xvEeuYvX5fTv8iPswAWMZOGHy6IONXmLaStDWE6ZKc9UYNx + xH8o467f4MMR+L/BFHgxZEfxm2zhqQ/2IBh1M0qNiaLeg+7kJCv18wQzgOXwIi2Wk+XsOrKgwpIRsThZ + jljC0fiFGNOMihf9+4Ile/l5Pp3czG6S9aGuKY8WYBz36y2pu0P3uEFMRzhSedhldb6OCdQpwnH2lZoI + qWPidAovznq1Pr+4Unu51K97ar7YMObOygh3B/vu7Up9fM61Ozjmv4rzD15/lB11P6Xyf8nFO6r2yPnG + tiei+tb62HZ6Lxow+FGaOiJNLHjArf5JmI3HFV6cbVV/lzdEow5xzh/Lqs6SXbp5Tl7yfVaV+lO1qZ9a + oU6Zf+XI/WtTBw/yss9EPe/jeqcSJiW3WD2IOXn1kg0PuFllAVJgcXjl2YYH3DG/IVyeuy+xuqQWi5n1 + OPV79spzH2nMLpu+8VuSASjmpcz2u6DvVAdfvLb9p/aYOm4fJmAKRu3Om3uLsK4qGLe90PiglgeMyKv2 + DBKzkk/8RHDQr6v0brOxvCoZIRwDGEWnHmUHdYhFzWrNXUQWuwowTvOkT3aS3yU8bIBx3/+UqpWu9HFz + D3pOtQYxFTuisKN8W9txI/f3Tpxn1NWqeBWUd7kB1Pfqw6m2uToUNU+LZHWgLIcOOLxIRb6q0/qVk28m + 6nl3enqZozVI35rtCG+YWpDnUjUKr7YzSN962CWcuZ0T5xmrmBFQFR4BVeWaWpkpxPPsq+L1/P27S17/ + x6FxO6M0WSxuPtAeV4K0b5fjDiFv71X1k3XpDu756w2j3mkhxKX2nmnyfZFdUU7JCij8ONm23WBXDgkS + 9XW9GSFpWf2QCI+Zl2tuFIl6XjVfpF7ViemdgQ4w0tv0fAWh5yverucrKD1f8UY9XzG65yvYPV8R6Pnq + Y+g2MVdv0KA9st8oxvQbRVy/UQz1G3ndJ6zn1P09ybdJ+pzmRboqMp7aUnhxmkKcyxqaWkceMcO3nCc3 + 84+/0/aUtynAdtx5mSw8goCT1IaZEOBSb1cRlpramOF7Sq9Vz5w4sWNRve1mujhOVb0f6zIZ25StV++p + 3TaX84xMIeLbZBfqAQJL6rCe+X2E+X3AXNLz58jYppJ5fSV6baquI0zRGQjoSQ7l+imjHDIDwr67kh2O + fVrnDflSe9Kwfk50pNGu7vu+IdkfVqQEdDjbWO32B9m9Ifp6CrOp+YUnQp5AMOqmnXMCwpabsuSq+7rF + n3bwpyWjicE+WYrSXdZktSBsOYcKnBjNu+SR5FSA76D+5hbxPXuqZQ84fpB/kUQAT50/c37YkQOM5JvW + xHzfD6rph+tQh0L8+tv5b8nFu1+uaDYLtbzHLdn7ckcw+7DlJiwIbL9t08T9VA3E8rSLhlm/z0Utr6Df + SwK6lwT9PhDQfaCHPfqNJZqpg2wX4VTm7usWT1tQeQJMh051QTnNx2QM02w+vV7ez78tlnPqGaIQi5vH + DyN8ErdSbiIfNb2Lh9vJt+X0ryUxDWwONlJ+u0nBNtJvtjDL1y2UT+4mX6bU3+yxuJn02x0St9LSwEVB + LzMJ0F/P+uHIb+b9XOyX6jmyPeWhJggb7sUkWcyItYfB+Kau7aTKOsz3URKwR3yPbvOoJg3ZrnYIo15N + TZtDTTI6qO3dVDFqn/bs6hOiUiGe5zmr8+0r0dRCjks2jjefSSJN2BZqyfVLLWvQ5HCIkTdsQg1uFNLA + 6UQAFvIv9/p7x7/uyZ49ZPlB/112v/H0V+oAygUhJ3EI5XCA8QfZ9cOzUB+JOBjoIy8DgljbHDEwA2nE + LnOPcUsDOOI/rIp8zdafaNtObOu8do49JARY0MxLVQ8G3awUdVnbLBh1mwDrNsGolQRYKwnenSqwO5Xa + rPttOmlQ3H3fNhCHxSfCttA7FkCvgjG8NqHeNb3mzUq7HG5MtvlecLUattyMnrxNwbaKeMYOxEJm1YrR + nYrCbEnN8yU1ahRMI/iLiSMjD4SdPynvPHsg5CS0QhYEuUijLgeDfIJVagRSapqKW7aPpGsljrMsCHDR + qkQHc330C4OuSv0tecmbp6RUiwv1Yq4iS7+b7TvnZSCe3b+6vzNqxL+9ksZJdj/Nk98/dedxyh7V0/gT + 3XzSs5a5aPYXF7/wzA6N2C8/xNhPNGj/O8r+N2af3399SAhLjk0GMBE6ESYDmGiNsgEBrnYQ384PVDXZ + auOYv6oJux0DKOxttwbbFukjR93TiH1dbdM1M01OMOY+1M+ZKoE8+ZEO2inzugiO+DfZI6cE9ijiZRcT + tJS0tzVhe3SfBKxqLmL1GpPMngGJwi8nFg3YdYqRnhwDKOAVUfelGLgv1ef8ysqiEbveA0C9PKMOflbH + b8nuwY4VCTRZUf+Yfuvm2WljNwdEnKRRps15RpnhuSxKegwmsnU9fpM4VODHILWPHeFZiG3jEfE8nGl8 + AA16Odnu8UAE1STXFTk5exB2MubrEBzxk+fsYBqy6/uQei97LGjOyrWurgTDfGJhM21izycxK3kiHsE9 + fy6Sap/+OFBvwRPnGWV+XhBeR7Ipz3acMmc13bAAjcG/XYLPDbrvkKZVjgRkYfdkQB6MQB6a2aDnbKfp + 2Rft4oif/uADwTE/u3wEnoB03+D2wjwWNHPrUhGsS0VEXSqCdalg16UiUJfq3iSjmT1xoJFfKhwatnOb + WBsecCfpVn0o81oOFfIyJc2JjvN5V0B7aGRBluvLdPn5/qbdFiLPik3SvO4pFQzIWxHa5VOEw5ZNBjDp + t8Co/V4Xhbykma8TA5kIu3dbEODarAqySjKQ6UD/fe6Ig75i0IIAl56Zirl9QprR8YhTDkMqIG6uhsUN + OUaLQT6RpOpNbbWNQEMvbTYO++UQXncaOPIjC5h3B3qJlgxgovUJgbWhp79W6+ZCz1+QfScSsOq/X6xX + K7L1RKJWGZdplSRgFW9zH4qx96F4u/tQUO7Dtk+229eZENnmTWLjOiR+U/FvXIe3InRd/HxzURL20PdA + 0Cka+dmG4WxBy6lPKzvkRZN3tQSlnPmw4b65uLw8/031ofZpPn7C1MZQ33E6b/w7i6jAj0F6vmwwvon4 + /NWiTNvsYTJffiO/JuGBiHP8ewIOhvgorYHDGca732d3xN/bI55HFdb2ATdxTgDGQf88xj7H3fqUjuOd + lpWP8iNBjAApvDiUfDsRnqXOHmVVo07aLApdIxdZQ81C0OFFEnF5KobyVMTkqcDydD5PFpM/p3p/bmL5 + 9lHbq7b0yeq6qmkzDh4Zsm752q3tbceA+mOK08Agn3iVBWfH1Zq0bW9/Bu1gNpfDjUnJdSalbdV7Abcf + CYrT5BzjoVyzf74H2249r0/NqhOEuJJC/Ykj1GTISr6xANz3l9nP/lt6e0NqCN9gR5F/ZGehyzpm1bJ8 + nN1zypzLAmb1H1yzwQLm+eTuhq02YcCtd2mp2HYbt/36aELyLdNTmI180zho0Eu+bSAeiKDPRuYlRo8G + vbxkcfjhCLwEgiROrGqvBqm7tP5OsveY46vV0hIdklSsTQ43JusVVyrRgHe7Z3u3e8d74JS4A1jW6iwV + VcmumAHc9e+qZ9WqE7ZkcznQ2G2txxWbuOsXjTo4gWE2QNspUk4a9JRjk60t9XY6Mobpz4dkMp3c6HM5 + U8JpQh6IOIknm0EsYiaNWFwQcaouzPiTAAAU8VL2DvTAgLNd2r/J62xN2fl9yINEpIzLHQ4xVvuMd9EK + DDiTx7R5IqykRXgkgsgIbx25YMCZiHXaNMzLNgVIjCZ9JL3cBLCImbKDsQcCTvXIm7ZHEYACXvWWlqz4 + 6ydOTWfCiJubwgYLmNtXd5jpYcK2+6N64WpZ/UFYCmFRtu169vB5OteZqo/mo706hAnQGOt8T7zBPRh3 + 09ssn8btlLUAPop7m7rgeiWKeru9Pil9QkyAxqCteAJY3EzsJTgo6tWP+vd72ngJV6BxqD0HB8W9z4wK + BeLRCLw6HBSgMXbVhpu7CkW9xJ6OTeLWfMO15hvUWlNOrIdY1Cziy7gYU8bVl2JqgBMfjBBdHm1JMJba + ipZfYRoGMEpU+zrQtnLzAU//mJomXMtE5ehATjJrFrRW4d37/n1P7/ZAfR39t095mRaEfbR8ErLOqA3W + icJsrEvsQMj5lXTajcvZxptsLXP8YyqyD79QjCYHGtVdyhAqDPLpHKP7NAb5qLncU5CNniMmBxk3t+R6 + wQI9p+rBcm4YBwW9jMQ8YqiPd5ngXdN9xsqkHnSc+WMmaD9aE5CFXrZ7DPX9df+JqZQkaqXmikVCVnLR + OVGYjXWJcLnRHy0oq9gsCrMx8/uEYl5eWh5JzMq4bRwWMnOtuPFP2hpBh8ONzNwyYNzNy7Gexc3c9DVp + 2z4tWe26gUE+cuoaGOSjpmhPQTZ6KpocZGS06xboObntuoOCXkZiwu268QHvMsH6ufuMlUlYu/754Y8p + dw7VZRFz9nNf1Q1L3KKIV0/HqcfBtJEaxAcifN9sYwK0OOKnzhVaIOLkPjEBBUgM6lNAC0Sc1Gd0Fog6 + m8M+WclBW1InP/UieWYIzzMcUbxRREGOeNof7q1Cn4TBa9iL72+RzKZmMJ54m3iCGu8tkhj0AVdwrKfI + oY4g4nxSddOOp+1Y2/zlJuJpogeDbkYr9SWwNuX4GfEJn4GhPmK7b5OwVZ9/y5FqEHR2h9sypB0JWqnP + 8L5g63y+8FbjfMHW4nQf0Ar9CQJdxCdPX5AVNt3fyc+GTA40sp7VuCxs5t3h6L1N2rbAxjwfuw4K1D+c + VIRTT73a0+63wFDasOdm/Gbw1zJyw8+Jh4/TRJBOLLUpx/bH9eLqQjZB30i2E+Xapt8u9Ic025HybaxV + HRaIODe0Fs/kECO1hrZAxNnuafadtjrJp0P2WqRJlWb7pEhXWcGPY3vwiPqLu8ftObHJwBwDkfQlRUbq + HAORGM+7McdQJCESkRYNcZVdyBOIeDr9KSYZTQkSi9jqmxxuJM4zOCjiFW9034jR943egWrd7iam1pJx + w1mSEbEes7LfBiE6qGULRFdJImst9XXS1rQDnnER94dV9nP/FjFb00DUmJpQjKoJxRvUhGJUTSjeoCYU + o2pCYdRgXWpH/jLLRIj6Btnn68bHj2kGcN2I+G8VeDhidPsjhtufVAjiI1oDQ33JzWLCdCoU97Yb13HV + LY3b5/yrnoNXrSc+Ge1Hx0FGTrOAtAGUHe4MBjZx9guFccivZrJiAtg8EGGT0UeWBocbyfNNHgy61Xbi + DKvCUB/3Uk8sbtaLWjPa2kWIByJ0LxiQzR2HG3nJYcKAmzVWRsbJevQ5/sxXl0ONjFrwCGJOZr1tsJh5 + zr3aOXa158w0PUfT9Jybpud4mp5HpOl5ME3PuWl6HkrTphDq3lCLMWg7KwYtcLSkTl9YOwkHHKFI9F2F + cQUQh9GBAPsO9N3pPRKwth1osrLFUB+v8jVYwLzLZV+tfIzpSPgKIA5nPgeey1GTMbFlGXCEIvHLsq8A + 4hynQ8j2Ixhw8sqMRUN2vQ9He6gpXW7AuLvNGa68pXG7zg6uXMOAW3BbNYG3aiKiVRPBVk1wWzWBt2ri + TVo1MbJV0/u8Ep+iWSDk5Iz8kXG/HgSz7r8TCVr/Zvxi7wmk/jMr9ZCUI+62b2OA75m8/NrAUB8vPwwW + N9fZWi3r48o7fNAf9QtMhx2J9R4B8gYB590B+K2B41+Ji30MzPfRl/dibx4w1/OjK/l5a/ix1fv934mp + Z4GQk56C+FsAaiPSdveJJC3ylNSdcFnfvCG/VdVTjk0tZE4zkZxfXCXr1ToRT6lupUhyTDIyVpLv9rLv + kVP3ZBolDF3DepesikPWVBXtVQPcMjZacvU28ZKrUMSmTp52qU6Xi8sP/Ii2JxDxcb1jR5Fs2CyHHOVG + b3MTE6O3DEQTEYWx4wciyJJ6fhEVQxtGRHkfHeU9FuW3C36utyxiVodVR9dIrmRkrOgaKSQMXcMb3LGA + JxCRm3cdGzZH3rGeZSCaiMis8B17/Ab/jrUMI6K8j44C3bHrp1T+7+Jdsq+K1/P37y7JUTwDEGUjryTb + ZO/jbl/QMjZa1A08aASuojwUBf+3WjRg/xmfcT8Hc+7Uj6K5Txjia2qWr6lhX0bYs9fGYB+5AkR7K+0H + 1ZZ1fRIDfLKB5ORHiyE+Rn60GOzj5EeLwT5OfsD9iPYDTn60mO/rWnWqr8MQHz0/Ogz2MfKjw2AfIz+Q + vkH7ASM/Osz2rYr0e3axIvaSesq2MV4QA98MU00HsYR0iO8h5mSHAB7aDlcdAnreM0TvYRMnmY4cYuQk + WMeBRuYl+leoDuxVTTxFdmRskz6kXc8NrV5JB0IDbMBMew7toL63nXniXbHJBsz0KzZQ3Fut/sX1StT2 + PqVCV2dPab15SWtSSrisbT4eo96GTtLisarz5olUcWMOOBLzMXX4vHfzC6yH0z7t2Dekzdvk113+ksZf + erzu5RMlmrFN7cHoMfkNG6AozLwOnd3ef8zKZ5e1zfX6IvnlHbXy7infxlABnl9oDqfsUcuNX2b0+HKr + N7LRxwCIbF2rZeOH7Tb/SVWjIi/mxcUvRLkkfAutnwfNe8m/vb+iXoskPMslbQ6oJSBLQv9VHWXb1PSE + mqvQi593Kamwuixs7uoJ9aC13nD0lgCO0X52/KY47NUmPhkrGqLC4upDYhhv9MAGI8pfy+ndzfRGrVVJ + vi4mvxPPX4TxoJ/wkBWCg27KajeQ7u2fZg8L0t67JwBwJITNDyzIcelDgtbVoSSczeGBvfP36d10PrlN + 1FmzC1LG+yRmHZ/dLocZCZnsgbCT8vaJyyFGwpvtLocYudkTyJ128XmlDpi5Iwx8AopQnOe0OETE0Dji + 5xUytIxxi1ighOkljCynJhGrOCV+yc0/WxGKw88/Eci/xdePy/mUV7xNFjfTC0dP4lZGETHQ3vv5j5vR + +/uq79qk2kgwLTcUQYd4nqZO1w1RpBnD9GVyPdogv2uTnH2wXA4yEvbAsiDERVjU5XKAkVLsLQhwURYo + WhDgIhRvkwFMpJ2fbMqxkRb89YRjmVFTaeanEHFxn8k4JtqSPgNxPJTVySfAcMwXC/WiZzr+zjsRjiUr + qRZNOJbHrMxq4pyOBzpO/tQdgjt+7oQRCLvuqnh9L2/W52z8jrMeCDp3h4IhlFRvmy0WX+VXk5vZYpk8 + 3M/ulqR6DcGD/vH3MAgH3YS6D6Z7+5eb0dM58qsWR6vuToDtoFR2x+/bhmWdlmJb1TuK5gTZLlpl1xOm + 5XI8fmlx1PS89NPzkpiel156XnLS8xJOz0tyel766Tldfr6/obxA0hOe5VDSPZrpTXq4cH1/t1jOJ/Jm + WiTrp2z8NvUwHbBTaikQDrjHFxQADXgJtRPEGmb5ySdaEpwI16J3F6Md/euBoJN0BLjLucaiGr/ZcE9A + lmSVV3STolwbJTuPgOGYLhfXk4dpsnj4Q3bqSJnpo6iXUJZdEHVSfrhHwtZZsvrwi+qUEqZtMT4UoX0/ + kh+h5bEI3EycBfJwpu8K2bskdEsxHovAKyQztIzMuEVkFiohIjIdxGA6UF5l9UnMSnstE2IN8/1ydj2V + X6WVNYuCbIQSYDCQiZLzJtS77j/+d7JeiQvCuhsDcTy0SSkDcTw7mmPn8qSN0nvCtmxov2Tj/gr5HxtV + VPONWpUhKC4HRb2r1xh1R9t2/QyBcn6sBdku2lGfPeFYSmrhbAnbIv9wsV6tKJoO8T1FSdUUpW8hrEgz + EN8jyFcjnKuRWmoSd4jvaX42VI9EbI8g57gAclxqqZoO8T3EvOoQw/MwvVNfUm/vpkXRL9MSyboqRw8G + BzR+vNUhL9S+Zu1OtoIax8F9v66+RUb1dhjiI9S7Ngb7alLr7ZOAVaZ1/kg2agqw7Q+yMtZHwpCVPep7 + Ob8a/r2PuybfkV0thdlkGf4Xz6hI1LrJt1umVqG+9ykVT+8vqMqW8m15+v5ine6TB6rwBAJO9cBEb2BY + ka096nvbkbiqAWQFsKs2h4JegUAOP9JO1mXVmupuKcxGesoHoIA3223ot2hL+bayYlYjJ9B3yk4sJyE7 + zPeJpl6nIqN0xz0StDLSsaVAW7FOG4ZOYYhv/JNwBwN9JT8Ry1AqlrxkLLF0LAlbZDuY72uqonoZv/rO + wQzf8vN0Tl18ZkGQi9Q2WhRkI1Q0BgOZCON5CzJc+6yEu4ijxagBj9K+NMQO0eG4v13/y/Z3uO9/llEJ + c/EOhvqS8rBjOhXaex+mX5LJ4u5cL0wda7QgxEWZmPdAwPkiS0hGFmoKs7Eu8UTa1r8u3/2WzO4+3ZMT + 0iZDVur1+jRmZyUHgNv+1WuTCdaV26Rtlf+ZrOU9t0rHP490Odf4XfbIthXN1jKOqUrUobbjWyULsl1q + nl+9OXA9e5D1sE5oihXAbf++lh1Ryv6HFmS7qGXeL+k6r28+03ZU9UDIuZg8tC+W/TH+SQNMw/bk4etH + wuakAAp7uUlxJAHr9DoiKUwYdHMT4kQCVnUO3q9ko6YQ2xXLdoXZ5Ndnf+pXV6g3KOaAIvESFk9VfikI + loF51L02H7jX1Od6VR5XfoRhNzeV56H7WLWRZKOCEFcy+foXy6dAzHk9v+U5JYg559N/8pwSBJzE/gPc + czj+ld/OmDDmjroHPAMehVtebRz3xyRRoA1Sn0e1Q64AjRGTQKE2SX3Oa5dOZMB6xbZehayR7RTiwSLy + Ez6c6nGlZrDMzKPv3fmIezeqHXMFeIyYXJgP1Q+sdu0IBpys9s2EQ25OO2fCITenvTNh202e7ADmOdpB + Oaeps0nQyr1RABzxM4qvyyJmdoLArVr7IbdJ82nYzk4OpCVrPyQ3YwaG+a54vivUF5OwjmBEDMrRvkEJ + GovfFKMSMBazwARKS0xGBPNgHlefzIfqE26T69OInZ3a82BtRW1mewqzURtYm0StxKbVJlErsVG1yZA1 + uZv+D9+saMhOHKQis+anP0e03fg41fg87p4bGKlaX2LfHaGxqvWNqIQKtesxw1XYgEeJSqZgO88asjpo + yHvF914FvbEJP6L9B77G6wMgomDM2L7AqHG58dWIAjZQumIzajCP5vH11XxMfRXXVwiPz63vROXGfLBW + 5PUd4DG6/RmvD4GP0p3PWX0JfJzufM7qUwyM1K3PeX0L12BEkbf3+UXy8HGqVpuMNluUZ6O9wGJBnouy + 1MlAPI96Yv1d1plpuUnWWT1+MQ7GexH01g5Eq2Y8U3eaHGEDRQ+0nZcyq/64+XSRULbu8cCAM1l8npyz + xZp27ftVdsE60R7BQT/n3HUEt/2/JqtDuSkyVWOQipoFIk5V/vJtvpb3C89tCtwY1BvuV+B++1XfLvSf + fqQgm6rNeMYjiVn5yQkZoChxEYbs6gTkuAiuwY1Cede1J1yLWtmjzvWmvJ7nk6iVdBYhxGLm7i7PNjz5 + Ccf9z1lR7fn+Dsf8Ki+48pYNmyflZhr3E3yPHdEZgJDrKIgPR6A1Bz4dthPWSSO46+9aOpq1g1xXV2Bp + rg5yXcfdtE43AWcX9xEqN267z9YbRA2IvJiqf6jeJSZGOGKgT/B8wvbd386uv9FvHRsDfYQbxYRAF+W2 + sCjX9s+vk1vmr7VQ1Ev91QaIOsm/3iRdK3v/IwQP+qmpge6CBHxMThV8J6Tu8y+ThwdF0i/bIDErJ61N + FPVyLzZ0rfS0NUjDOr//Syb7dL5smye95/pidn9HS4ygZUw0QhIFHGMiURIuJHFjdalMTzYDRJzUxDlh + iI+cBD3XG+eTu5uke4NorM1kHJP8S5a+kkQt4ngIM2HH7zsG/YoJyaEJyNIebaJOdFC7p6mDkQjDpwGN + E4+4fYHJOKbskZaC8vuuoUxXRZZsq/p7cihFus2S1WG7zSgbxQ2KnJjbXH6RssW6TTm2dmBdbpJd1jxV + tPRwWMesX0tXYUnOE+XY9tX4A+FOgOsQ2WFTMYq9CTpOkWW0RFOA5+DngQjmgWjS5kD7rS1ieK5H7xor + v2px+uIIYxkDMTzmAyvKflEeaDuPT6eoSpOzjP+bnL+7+EVtwKB2tU/S558XBC9AW/bkYbFIHibzyRda + TxlAUe/41tcDUSehBfZJ26peNN5/X4tzObzNCIdwQaxtXuXjn7Qcv+8YirxUpxkl499zdjDbpzeLlfXg + nnRdPQXZKHeiCdku4hyOgbiebXooGmqd55G2lTgrZCC2Z1ukj6Sk14DjIN6m/r1p7h9P2OIfQANeaiHz + YNfdvEvWdZPQ1iMBKODdkHUbyLLbn9NFEgJdPziuH5ArI4sywLJN101V0xO+4wBj/mO3J+sUBLiIldCR + AUwl2VMCFvoPg37VD7Llh2eRdylt1GRjoE+2oYlsYahVh83a5lwk1T79cSAV1hNkuyLOx0VwxE8+BgOm + bTuxa+P1Z1QC01u/nrJt3XGKuqejF1ok95PpQ7J73JLqp4BmKJ7qu8WHO1qGoumncpGxWseoSBdvEOkC + j1RWZcaNoFjY3Hbh3qA0gKLhmPw88i0jo128STQvp5gnO4Mw6GbVUPg5PfpTyjF/J8Bz6Mtm9PodFPYy + +usOCnt137SudsTJHtSAR2mquBhNFYrQUE9oAWHH3ZYXTpZaJGjlZKhFgtaI7IQEaAxWZvq47Rf8EZEI + jYgEs7cv0N6+YPTQBdhDF7z+rMD6s5S1Xcfv+4ZkLwS5DbRAwFmnL2SdZFzT3xnN8rfT5h/2lJOTesK2 + 0E526AnIEtEtBAVgDE6OOijoJeZqT/U2ympje22x+hftiLCecCyUQ8JOgOMgHxNmU46NdlCYgViei4tf + CAr5bZcmp++J8UzEND4inoecMj1kuy4/UCSXH1yanjZHxjNR06ZDPA+nDFocbvxYVOvvguttac9Oz8sT + ZLneX1HKufy2S5Pz8sR4JmJeHhHPQ06bHrJcl+cXBIn8tksntDulIyALOZUtDjQSU9vEQB851W3Qc3J+ + MfxrGb8U/JWcOsLiPCMrzbz0mj18niw+J4QW60QYlofJH9ML8jndDgb6CBOZNuXZTs+GduKRqDRRz6v2 + XM1Ud42sNUjDSlqC5a6+av9N3dbapnrbcv51sUyW939M75Lr29n0bqkn9QijMNwQjLLKHvMyyYU4pOU6 + iwhmi0bErLNNtttTzuccoQrGlX/PxdNb/FjHNCbqm/xczxWOTKghEDzoJ9QYMB20q1kAUdeR94BhgaOp + 87Kn85i7zTYEo3BzxMCDflUgYwJoPhiBmec9HbSrgp3tIgK0ghExKEP7oCQYS5W+Xdakaiorsni5qsG4 + EfeOb4GjSbb9D265tgRwjPbs29Ns9jEJONEQFRw3+7nP6nyXlU3yfM6JZgmGY8hOym4VG0dLxsR6rvb1 + Nj6a1sDxuEUCLwnmkiOO2eThCMzKzarVvi6m8/YAWFISOBjoGz8+siDQRfipNmXYlp+u1DKR0Ts/nADH + sT8QHQroHX9dXF6ej97hpf22S6sysU/zmmY5Up6texqknzV11Q3RDBiMKJfvfvvzvXo/R20W0D7+pxxu + ifFgBLUPS0wEiwcjEN5hsSnMlqRFngqes2VRc5GPf3EfQFEvN3UHU7b9NBHfY+QSB/3Et3B8ErRuLnKG + UVKgjVILOxjokxUYQycpzEbZZM0nQWt+wTFKCrRxyyZeLttCxfvdJxY0k5a7uBxuTLZ7rlSioPdZr1ks + GdqO9KzdyXmyxRDZmjLTgPFeBFkhnDMK1xGDfOpVo3KT1uqNlyYr1bSYoOshCxhNpt0hY/g1hxuTVVUV + XK2GB9wJ+Q70+EAE+j1jsQHzYf2U1my3pj27rgAY1fqJ84x9oWFVIC7u+VVdTW/VOgq08e5wg4StDeWd + VQ8Enez7w4YDbnqGWaxnbhdUMnp6Peg5u1TnFFsTBbxNsm5+kpWaAm2c1v7E+UZdMFg/uydtazK5/f1+ + TnlR0aYgG+XIW5sCbZsDx7Y5wDZq4hkY6KPs++NgoI+TEVg+EOYlbAq0Cd4vFdgv1ZOwG55Rgq5zuZzP + Pn5dTmXLdCiJiWizuJm0vykID7iT1WtyN7uJCtE5RkS6//jf0ZGkY0Sk5mcTHUk60EjkOsIkUSu9rrBQ + 1Nu+sUiYeMf4cIRq9S/Z2sXEaA3hKJTDXjEejZBzLz/Hr5pcK5okapWV0nlMnp74cISoPDUMThS9T9Hk + 61/0Im+RmJWYjQaHGamZaIKYkzxacVDXO7v7xEjPIwXZqOnYMpCJnH4d5Lrmt/SdOX0Ss1J/b89hRvLv + NkDA+WW6/Hx/w/v1BoubOdfbo4A33WzeJXX2XH3PNmSzCcPuczV+p85qeTDsVp9ytIoDjO0riuKQN9mK + rDVhyE0cAXUMYNpkRaZezWP89B6FvPl2SzdKCHRRtmB2MMh3oKee349Tf2XdmMgdqXsrsh+qNswmO004 + 4BZZnacF297imJ83JwzxWIQiFQ1tgS/GYxFKeRExEXoei6DeJkubQ80McMJhfzKf/nn/x/SGIz+yiJlT + RXQcbuQMSH087KcOQ3087F/XeZOvebeV6whEos87eHTATpzxdlnErNco1ixxiyLeuIpgsB7Q23XQR1se + jdjjKpnBOqavI6hPbWEDEoW4mh5iATOjSw72xndps34iqzQF2DjdZLh/zBgEHinMRnzebYGAU4/iI24w + h8ciRNwEDg9HYG5XF1AgcdqKirS/K8YjEfi1kRiojUTEfSyC9zHl9X8LQlzUB2cWCDkrRi9bQYCL9iK/ + gwE+2iv9Dub4TvuCk5/BWSRmjXiugDhGRKJ26BAHGok6PrRI1EoeK2I71Tsf6qOcOF1QWBGMQ66EfDzo + Z0w/QwI0BvcWCN0B1L4BslO/85mIz1UxJldFXK6KoVwVsbkqsFzlzQtjc8Ks2Vtk5vb2/v6Prw+qliGv + bXZZ1Cz/9pjV9N4kaECjdH0TxrQR4kAjiQO9kHg0bF83NevaFQcbKXvkuxxipJZjg4ONT6mQ3b685liP + LGymHGrpcrCRet/1GOwTT4dmU72UHOmRdcx6ve30bjmfTck9KYfFzN8iOlOYZEwsancKk4yJRV2ogUnw + WNTOm43iXvId6rC4mdWxAvhwBEYjDBrwKDnbHronqHWDjeJekbEvV2RN0BuVm2IwN0V0bopgbs7ultP5 + 3eSWlaEGDLn149KyqV/p5hMa9LIrT9cwGIVVbbqGwSisCtM1QFGoj5CPEOQ6PgnmZaxJg3b641+DA42c + NgJpHdp0pj+ccWHIzWtzsNamXdZHfBxjkYiVm/EnFPPqzezZd7RrGIzCuqNdAxalYT7thARDMdg/pEGf + eeqvqHEBXawozJZUxYZnVCRk5TRacFvF6nkgfY6qzIq8ZNzMHQg56YP/HkN9hENrfDJkpT6lcmHIzerD + +b03Wdqn1+1bxOq9s0bWSbRJG0gAx9A1qfoDx3+CUTd9tbTDwuZ885M7RwMa4Ch11tR59pxFhgI0A/Ho + z4pBAxylfcrD6CAAvBPhQZ3cTu4jnCjIRq3zjpDrag9lvbu/4VRTHu3av37k/fKeg43E7QIMDPW9azeC + Z2o7OmQnH0MRUMBxclai5EiakEvYCYN9gpdnAsszEZVnAs+z+cP9YkrdP8XkECNjXw+XRczkdw9NMOCk + r5Xw6JBdxOlF2K8faWy4+pYO26Ou/yQIxKC3RR4dsEckTjBlmvog+FetacROr0JOnGNU+yfxnktaJGYl + 1sQGhxmptbEJAk79kkXaNDVZeiJDVs74GRIMxaCOnyHBUAzqxB4kgGNwF+L7+KCfvMAUVgBx2hdgGAd4 + 4QYgSjf1yCqxBguZ6ZOWPQb5iC18xwCmU9KzMs+iATur4kPqvIj3JXwc9p8n2S7NC467Q2Evr0gdwYCT + WwU6/EAETgXo8KEI9A6IjyP+iLrPxhG/HCxxKqMeRbz8NfugAYvSzofQO+CQAInBWU/ssICZ0fUBez2c + Dg/c16HPa5wozEadfDVB1LndM51bqPUQ/HtAhO4BEVs6xXDpFBGlUwRLJ3m1+xFCXOTV7iYIOBkrynvM + 8+m3BPlvY0MCPAb5vUOHRczM9559HPOT+2snDjEyelY9iDhj3ttFHKFI6tX+dao2SLuhvvcT8IQitqtO + 7w67VVbz45kWPBq7MMFvyTqf8jp+kGI4Dr37BymG47AWuAc8AxE53U7AMBCF+iYtwCMRct7F59gV0/tC + Jw4xqlbyDW5yXxOIF32LuxIn1mL2O73uPUKAizyrfoRg147j2gEuYulqEcBDLVUd45qW9/OpPrWM83zD + o1E7PWctFPXqdoO8lQfAD0R4SvMyKoQSDMQ41LU6Q2RNfI0C14yLx9g8IGgKR6U/8oMEgzF0ChA796hl + IFpV5OvXpOGXcFcTjieaqo6KpAXhGLL5VQ9yiHtLYZJQrPPYe+t8+N46jy7j5yPKduwPGf4d/b0dVeFZ + mmC8rK6riFRr+eEIcpi3b55i47SWcLSf9HcGQMNQFNnQtqtV40KdNAPx9rLqyJuuCokKaZnQqORX02wU + 9ZL7NCaJWveHel8Jta/5k+x+ci/csaDR9NIU2fgKZpwTH44Q046K4XZUv9TMr2WOeNgfUV+KwfrS2Fgk + IkZnGIjCr71OfDBCTD0sButhEV0zihE1o/rOtkgfI+6Llg9G6O7SiBidIRilyXcxIRQe9pPX4AB8MEI7 + 5ZysVxFRTg40Utf/UyfRrL8zI1kONNLfWV0xAygU9KqZbWYdeERxL2uQ15Gotaiq76whfA+DbuboHR25 + G7uSc6oDE8f93BZyYJTZDjlk3jKvvIMDbl7f4cRiZu56f0iAxlC/jVm4TRz369VGEQGO/EAEPdzbRAVp + FQNx+unXqFi9Bo/Hnt8zaNTebm3EzZWODtrZQ3hbgMZoq7+YO9tSDMZh3+WmAY3CeBLtwgNuXt/hcbDf + UFSpaova0sxJIlsAxuCNM7Exph5OyRY0VwHTImryDHVhkc/Z7VwPY+6Y2lwM1eYisjYXg7W5iK/NxZja + XLxNbS7G1uYiqjYXA7W5uSHnPm2eBDOG5QhE4o2dw+PmmLFmeJwpoto6MdDWidi2Tgy3dSK+rRNj2joR + 3daJEW1d3Jh/aLwfMxYPj8NFTBstwm107Ph+eGzP2InVBB3ncv51QT7xvKdAG6d+tEjQSl5T0GOoj74M + 02ExM+MNOodFzfQVPg6Lmum1tsOiZvp97LCgmfpO24nCbKw5a4927H9OGGeoHCHARXyI8ie0T5X6I7Uf + 3jGuaTqfffqWPEzmky/t2UaMB2GYZDBWk66Iu1QijoFI58lTRSzAsCIUR1V+NeMmxCShWPQC6dIhO7mq + 9ughO73ihhWDcfZZVr9BrKNmIB6jcocVQ3HoXX9YMRQnsjRjLYv1Jc6jZUgQisGY3Af4UARydezAIbea + beDLFT1kZ7xiiDgGI8XVxCfFYJx8Hxkl34+IkaRiHR1HSQZjxdViJ8VgHN1055mIjHXUDMSLrcnEmJpM + xNdkYkxNpr6kyuYbxDpphuJxBvCYZCgW+dE9aBiMQh5swIpQHN1pZA10cY0Tj/3uWeCdM/1RnekXCBnb + 6/o45NeJx9abtG8nv38EvyGnzx2gd1N7DPSRm9kec3x6dRX/dFUfB/2MmSQT9JwqXPqdOO3RY6BvnTJs + 6xR00fsoBgcayX2RHgN9xD7HEUJc5L6FCcJO+rOcwBOcuP1PhvY+6T5nNG8WCVrpTYzBuUbiJtX+/tTy + L6dl5eQm1oUBN8sJuJjvI6PvITP2nwH3nqG+x+y/v6xrCPqkSo85PvlfG+NcmVT+i3E+DWpBonEWKDms + a6amCJAWev4kPTRPlRyjv3Iez4GGcBRZnVDn70FDOAojT0EDFIX5xnv4Tfd23qxqJtuGkwdHErF+zLbU + t6tsFPK2u3Ekq7wRDeOSLRzys1/NHXrrPmJnqOCuUO2H3S4i3HJu81CEZiXUJaTFI93es5D5kG8YZVpR + vo0zcYXui6U/qNZiT9cpyrclxrarVKfJAubjChG9TCits5Ts9wxDUagHdUGCETGSrHyOjqMkQ7HIJ6SB + hjFR4n/S0RKIduxJx2ST4QAicd5zwd/7i3rbb+AdP85OJ/AOJxE7mwR3NInYySS4g0nsziXDO5bwdyoJ + 7VDC3ZkE35HktFXeJtvodu4g0seMI3cUWBy94yR96hfggQjcE7wfg6d3q0/5SRNKEW4nM9DH5HcxQz1M + vcayyEqys+MgI33vOXTvxceY3WMew7vGxO3pOLSfY9RejgP7OHL3cMT3b1QbzrAL7S5Qanf8YrvDy+1O + Tc8k6eZfNOcJc3zeDAN5Vgs0wFFUfnL9RzZgJh8A5cIDbvJxUJDAjUFrSL21DrLeyDf05yE9BvrIz0N6 + zPHp10qObzTQO94+jvoj3KiXf8nw1VKXivirQ9RwU6Y0fXtXE3Sc+7QWWbKtq12yOmy3xFrQo117u0OP + nkaniQ0QdhbZc1YcZ5I2GcfuKEJx1OeMvi/igCPpz419lDiRXMdgJPqyT8QxFOnHIS3ybS6b4bhovQeO + qHaDos9gu3DAra9C5yg7Qq8YisNaloNahqIdZCP+RiEtVSBue2uw7yzX4UYiV5VgHcnZARvZ/Zp76CB+ + 3iBrL21kH+1u3pzxiM4iHWu39kQvciZJTdBxtivbOD13i0SsjJ67jULeftiUFo8VXW7z4QjPaXHIYkJo + gR+DNRuI73UjIuY4RHCOQ3BnIwQ+GyHYsxEiMBvB3Lce3bM+aufZgR1no/bCH9gHn7sHPr7/PXnve2Df + e9ae98h+9/3dtTkQB8I2inrp7Z3DumYju8iDdxcOucnDd48espMH8KDBi7LfV7Xaa+k0l0uM4fFOBNaM + DzLfc/wztStjcK6xSo5HMtCMPeca9UJSelfB4BwjY70kuFKS8e4x+Mbx8T1h6jZZBocbu309RSNv5keu + 3pLYsdKGd5KeyeFGxvM2AA/7ic/dADzsJ56eB+Cen3kWnE16Vj1MU30yXqq4OOTnXDJ80pjxAa+QBE8Z + cz5nJUawhPDPF/Ng2/38nrO+vqc8G2+1pwV6TsZz+Z7CbIxi4MEhN7EQeHDIzXlGDxvQKOSC5rK9Ob3I + k9+nd9P55Da5m3yZjrW6nG2cPUh4Pl0sKLoThLiSu2uWTnK2Md8TNtc4AYZjlSdNJnskq3STHMoXtd62 + yXays5fWo/sQQUk41ktdlY+yE/OYC8IAeNgERF0X1UqOFJP6/B05jsEGzecR5vOg+SLCfBE0v48wvw+a + f4kw/xI0X0aYL0PmK774KuT9je/9LeRNf/LF6c+QebXnm1f7oDnimlfBa15HmNdB8ybnmzd50BxxzZvg + NYuIaxaha/652/GrUAWH3ecx7vMBd9SFnw9dedylD137RZT9YsD+Psr+fsD+S5T9lwH7ZZT9MmyPSvaB + VI9K9IE0j0rygRSPSvCB9P4Q4/4Qdv8a4/417L6KcV+F3b/FuKEehB6sy25zu6PTJq+zdXNc4UuOFZIB + sfWuGHERfQUQp6nTnXr+XmZkf48C3m7EUWfNoS7JaovG7aJJx0+8gnDIXe356srs3WXi/OLqcb0T+XMi + /5F8H70eA0CD3iQr18nP8wh9Z0CibLI1yy05xJitVzrkqqjGLyvDDVgU+flOPCY/f+GFOOFD/qs4/xXi + /77ZssSSs4wXlx+45dBFg156OUQMSBRaObQ4xMgth4gBi8IphxA+5L+K818hflo5tDjLmKybWrdPhJUS + Dmb7nl6S9WqtfkD9um8oSpv0rU39/uL4aZu3gqoHFF4cWTIZV95Rnq0riwyjQfpWnhGxtft+tYlCLAY+ + DdqPSc6zG7RtLyt+aXNZyBxZ4lAJEItR6kwOMHLTBE+PiHIC8UgEZlmBeCtCVwE+6X3GPpCOjoRp3B4l + H3LLjv7r8/inXBgPReg+Sp6quiQ830B4K0KZJ/JLjGJug5CTXtBt0HCK8jzZVEm6Gb3HmIE4HtWEU1bM + WxDgIpUpEwJcdUY6vNnlAKNIn+k6BTmux0yWnLTI/842eoFUUyXjj7zHDV4UdcRJla8zWWUUclw+/lRL + jAcibPOs2CT7hu4+kY41b7Jdsq52K/kXeuHyaMdeZ1v9kFrdbHqGRI+kKScaDmiweKrarsqMF6WDHbeI + zGExmMPN675b0J2kQlZ9eUl5JowanCiHZs28Dyyyt66y7JDsqo2sGtT6XnUBNWVTM4w3IuRVN7cmZGeH + emosTNv27SYRT9Wh0PNS45/8A6jtVbv9yfKqFo+qZOsuQP0p3WxIvyBssqOqD+lp1FO+Ta2Ll/9N1XWY + 4SuTVG0/dFjJaqMUDamcAKxt3mySl6oev3+RyVimdbV/Jat6yHJtZDeG81stzjJmP/cy3wmqFrAc27wR + 8oYj/0iLs43q7dJdVTaP1S4j3EIeGbImYpcWBd/d8laEx7R5yupLgrMjLItMkjotHzNygtqg7RRqZzTd + cJCtDup666xIm/w5K17V+wSkcgnQlv1f6bpa5QRhC1iOYr1j3TMWZxszIZLmKS3NwjCnqEEBEoOaXQ5p + WXd5UejlKrKTReqyQ2zALHsKpPP9UIETo8zlLZe85JvxG8m7nG2sNu1p0Yzy4bGgmZp7FucZZeWbrFLZ + rblgXzKkAOOookmuIn3Yc3c9s3ft7c4Pg3qwiOwk83g0ArX+81jULLJ1nTVRAUyFF6cQT/lWHY3NTCOP + RyJEBgj4d4cipnHHFF4cbn/TY0Ezp744cZ7xcP6Bfa0W65jlrVa+I/k0YVtkYrNqSJPzjGoCIf2FqGsh + 2HXFcV0BLkYumJxnVGlKlCkE9DA6ri7qeck34JHxTJwS4peOSpaZUr/grLqd1eo5rw5C9jplhu0rIXsc + hAiDLjtyqec5WOMZj7XM++qFlmstYDlqNe7njTdc1Pd2bY7+DlVssrY52xzWmUyaNcnZU5hNDaD2RcrV + nnDHL/K/GWlrYLava2nJQpMDjMf01v8gey0asvMuF7hasU6bhlbqj4jt0ROn5OsyMcfXsEcoHuuZRSPH + Q2vG1dqo5+UIAdOP+upnomeIy5RS6dug66S35j0Eu644rivARW/NLc4zUlvLE+OZyDl6ZFzTT3aW/kTz + lNHDhXu3VptITj2AtuwH7qTAAZ8ROHAHDgd81PBCnr598eZvK/XGvxBq/8K9OuKq2OpHYqOdCN9HWF/k + yWRxd558nC2TxVIJxsoBFPDO7pbT36dzsrTjAOP9x/+eXi/JwhYzfKuVHqqoGc5y9CpHm/Jth7W4SFYZ + VddhgK/ZvmcJOw40XjFsV7ZJPWpWf00Ieza7nGnU58GR88KkfBs5LywM8JHzwuZA4xXDZubFUyr/d6G3 + FHw9f//uMqn2hBwB6ZBdZOPbG5g27GoJTaXX06wLNS7MSrXMaHSNifF9hI26+a+v1QvlN9PF9Xz2sJzd + 3431w7Rj59Wdm1Dd2X/45YGrPZKQ9f7+djq5oztbDjBO775+mc4ny+kNWdqjgLfbrGD2v9Ob5Wz8PgcY + j0dgprJFA/bZ5JJpPpGQldaibtAW9fTJ3dfbW7JOQYCL1jpvsNa5/+B6OWXfXSYMuB/k35eTj7f0knUi + Q1bmRTs8EGEx/efX6d31NJncfSPrTRh0L5naJWJcfjhnpsSJhKycCgGpBZbfHhguCQGur3ezP6fzBbtO + cXgowvKa9eM7DjR+uuJe7gkFvH/OFjP+fWDRjv3r8rMEl99kpfbpvmukSQEgARbjj+m32Q3PrlHHe2iq + h/aApz/Gr1P3Sdv6cbKYXSfX93cyuSay/iClhgfb7uvpfDn7NLuWrfTD/e3sejYl2QHc8c9vk5vZYpk8 + 3FOv3EFt783nfVqnO0ERHhnYlBCWxrmcY5zNZXt3P/9Gvzkc1PUuHm4n35bTv5Y05wnzfF3iEnUdhdlI + G1cBqONdTHi3lAUGnOSMd+GQe/xW4RDrmw+rIl8zEuLIeUbi2Yk2hdkYSWqQqJWcmD3oOxez36k2iXge + RjV0hGzX9JpxVSfIdT2oCFlDOAHC5Twj6yY0OdxILS8uGzDTyoyDul7GzXKCEBf9p6N3Sv8R9Udj98n0 + ZvYwmS+/USt0k3OMfy2ndzfTG9V7Sr4uJr/TvB5t2zk7J27QnRPdTxZcpdN3mS0WXyXBbH992rbfTZeL + 68nDNFk8/DG5pphtErfOuNKZ47xfzmQHcvqJ5DtCtut++Xk6p2b7CbJdD39cL8bvU9UTkIV6e/cUaKPd + 2CfId/1K9fwKODg/7lf4t13xGwMAD/vpiXgVaBX052pi509dK6kxJ1lv44N+Vgr5iuE4jJTyDFAU1vUj + V8y5Ru+q1Nj1GznrThRk++fXyS3PeCQd6/z+r296wN2mrG4LF8RHHqgEitVeDV3fco6R3HGCek28LhPW + X2J1lpCeEq93jPWNIyrDUD3IrgIDtR9nQIqMRufckf4cH+nPY0b68/BIfx4x0p8HR/pz5kh/jo70zU84 + yWCyATM9EQzU8yYPi0UiBxKTLwui1iABK7kumiMzHnP2jMc8MOMx5854zPEZj68L2dPVXWeKsKdsm9rD + nuJR3/cNyeT29/s51dNSmG3B0y0g33I5n338upzSlUcSsn79i+77+hdg0q04R3cEIafsFdB9EoJc81u6 + an4Lm8j9agtEnMR71uQQI+1+NTDAx+rg2WTIuuBrobuFOvY+QYgrmd4t599YxhYFvPSK38AAH+EkLpOB + TbwSfgQRJ6eEdxxiZJTwFgN9f97/QVtYZHKAkTh9fmQA058Teu0lGcDEyQM4/Rlpb6W7SBO9B8wuG/+S + hAXZLn1geLKnP2kA2N6crZPfP3UvMhPOhXEw2LdZFRyfxGDfNiuyXXck+2sz/hjnkCMUaXco+CEkHHKL + HzXfLeGQu6li0+dogKM81tVhn8g/5+NPtsT4UATKzg0wHbLrzaUO9fgd0wIKOI66gmRfZ+p1SU4Qk4cj + MEsoWjbV0l+1awJTqtmQuVk/8dUSxt0RyWzgAb8eOcf9BNPhRZI3Q6PO5lxXm0y9yVektdqPhnoTYxov + nsh3+0IfXpv8TNZVVW/yMm2oOY9YsGiRNThiCUdj1oagA4sUUSMChnCUR2a9BUvCsRg1sMeHI4i3+DVi + 6NfovUGYv6RlUbNIUlVTq5xrXpkRLEcgUlXGpJUhwGLo7Q/1rmy8ED0fjsAvVz0fjqCKhLxr4zIGVAXj + iiT7cUiLiHCdwYqSbtV/dbt+pSU5BshDEdq3vunmloOMMuGOYelaA7bd1GGVyVimVf5YHnT9rit6gs8h + EWvbArO0LWp5IxrrYAutuj6HJkte7iafKE4Ds3xto0kbTp4YwEQt7wYF2Fjdj2Cfo/2wzB7JQslAJllP + q616k10qvtOdJg3YyTe5iUG+w4ouO6wAk+pm6fJP9p1IxMrKbbDXp3pO5o2kdg2m6lHHYCRyfYJL7Fi6 + H1VmLxT1kbFMT6l4Uimn+xnJ/v3VL8nPndrvN708v0iEeDkkmzrdNu9+JYQaLwWvpRsHuRz/OsJC6xqY + kwDo2P/UiMvLaJtJgtWHB9zkAS+msOLsv2ev1Pb7xNgm3UPT1fKhVGlVZ0JklHYHMQBR9M5d1PvPRYNe + 6twLyA9FoOUnLAjHoJd2TDEQR8+nRIXRhjFR4hMOnf05jjKIrbKJgb7meAP2tb9g+CENEI/Rytqg7Wzz + n5EqFmg51W5rle4e6d4R+VYGeStCl9O0jm8PQS7diaUeD4DgkJ/VGfZY1EzfDBAVQDHy8vldVAxHAMYQ + pNM3PBBy2juw0tU2D0WgDUZ6CHK1e//RdS0HGcm3tcWBRtIgpIcgF6Mqc0jEGpPlyO6YyBdUwebXGqjK + jtvOi4l0201dUQK5rG1u58Pib/KQJxDxTZJynNG8CvWkXshRbPKSN0+qnVlnybaqk+9l9VImaSlespq0 + aRlBaV5H+xTp74vLD0n6/PPitBckYaSEKpA41J1+QRhxk6pCm0OMsh8Ud8WmIBBD7VkYFeMoQGK0HTBS + dwWih+zkcWpAEoy1qWQfOyZOK0BiHMvwJSvAiR6w/xplx+6vqJIElKLNxeXl+W+MiXgX9J30yQEX7J1q + Q7NHPWkja6GxPguCXHqLNLpNY5BPnZpJ1ykKsgkhsvd0ncYcn7zehpxyRwhy0VOuxyAfOeVOFGSjp1yP + 2T49e0dMuCMDmMjJ1lOAjZpoJwhwkZOsp3pbfpFG7C0I046dt7cegAJe4i5yLgcYaTu/ORjgo+2M42Cm + b83dpRFAAS85JddoSm6iStRmoERt+OmwCaXDhrlbpU9CVtpulS4HGDl31CZ0R22idqvEeDwCM5WR3SpP + n5N3q/RJyEq9Ozahu4O6W6UFAS5qnbXB6qwNf7dKEAbc5N0qfTJkZV40ulvl6Ruc3SpBGHQvmdolYiTv + VumTkJVTISC1AGW3SgsCXMzdKjEeikDbrdLlQCN1t0oABbys3Sph2rHH7FaJCrAYpN0qAdT2sveVBGHb + HbGvJII7ft6+kgBqe6n7SpoMbKK8/+VyjvH/t3YGPY7aYBi+95/01mF2NT1Xvay0UiVS9YoIcRIUAix2 + sjP762sTEvjsz4T3Y26j4OcxIZgxNryW5UoyqO+FcyU9LPCBuVaUitmgd0wZ1PNK0iYCcMYJ//DxtIlw + 8/JXATk2NKNpEz4XGMGXbSkVswkOKZuy4G2DDyaXsnDfBLyCOkECj+AyFOZKuo/hXEkC+S48V9LnAqOo + EfK5kv4W9HyJ50oGW7FzJporedsoaCxMriT5GP/q0ZYiyZX0Oc8oyJX0Oc8ozpXkaWqX5Er6XNy4kSq9 + vos8V5KnqV2WKxmSces3qfSb50RzJQlEXXCuJIGoC8uVHAnOgjZvLldy8jnWsJlcyfvHb6jnjXFIvtwb + /90myY3f6n0jMTOK5/XgBzQ0zNay8ps8/RbrvsHTva/L3dpvMCie17Pum9wMTC2yzM8I/tQvOlpzmZ+x + QoKjNZP5OZYR7X9kjyX7GOwVnPlJKc6GZn6GpGddm/k5K+HqwjI/fc4zwp1arkcr687G+rKijmykFyu7 + c4ndt6y4tM9d1cUX9JlruWSwIDJSkEpHYdL4KEy6ZhQmnR+FSVeMwqSzozCpcBQmjY7CSDM/OXbGjB8E + NvNz2CjI/AxJxgpfi9LIaFQqHo1KZ0ajUuloVBofjcIzPylFbUjm5718aMAyPykVs21kug3nQzM/Q5Kz + Lg/pnDKMCc38DEDOCWR+Eohzpd9xVfqdN8H96kjmJ9kEtlk+85Nswdorm/lJNpitFgktxxhFXcZYimi4 + bSPXcu0PHWlhUkTJx1iKKIMyXvxfCZsi+tgApIhOGd4kazNhiijZJGkzQYoo2SJoM36K6GQDlCLqc4wR + nCwJU0QfnwIpolOGMUl+A/74C449e9wl16ngGtUp8YXPQ3mvO2uE3gHlvUKn52vcxBDe6SfY1KflT0Hq + uacgg40Z+LBaRMDUAT9TqKPPFOo1z+3p+ef2jOwZQxN7xvAqf373Ovf87lU4d3WNzl1dpXNX19jc1emv + pivrgy1tb2Y2Pzrz78/F1zqOnTd/V/UaucUn/n9aVbvNKtdNvTGu9N+5yRdXEOFjNfyXV5flbwFz7LwZ + OTY8PvordVVV/55c3ewWvwJHKd9m/5ToHtjEd8x2qlLLE8seAHU0eWV3tzsgmjtDTPtOIfviihO+rDUQ + KPkAiANIW7qVpvTlnJVGLX9oZcoQU6dsS1BX5HjcEdaTnZb/d/Uw4tOmc2+mAaqBGC3n3ZdsWzXFKdvZ + du5eiVWLEz84dmr+OmzN9Vlk5/mxhua2QCraX/Gw0deeCv2SuN+/y03Z1DrLi0K1JgdemZ1zBDW51zEP + yy9xlAps7VZlqi66jxaLD43g1P+WbS/1DjsOd8Y3tXmnVXZUOXA2hCS1/tnv/071+49ICThxnremOak6 + U+/tiz0P7RV7sTVEY96iKlVt+l8Uj5lZoIrVa08fd35CF6K4IV6LyY59mILLT7BdCWlVniZWX6n1RXWf + cjRZVazezp6PsmocGbO6UAqZ1ZEx66VecS4PMO9O5K0kyWa9n9ZKEqSVJKtbSbKglSSf00qSpa0k+bxW + kiCtJBG3kmSmlSTiVpLMtJJkTStJmFbS2J7GR1bkxVHd+v474J6Mp2N2oNcegBGnVkaktFzcmJ3ztkVO + 9ggf1NB3FAWH4cHxRuBWxMMCn7vx69OmcecU5b2Cb/7geOMZiXUMQOL8yNIfyIosE2T0uJBBd5072YbW + p2NtL/u9ciMVtvvqutmLm+1z06RWyVpVHb9WVTeuN3VLvAT+v3AsNds/cxe6AfaFGZT3trdHRjJjD5+2 + R+8sqSGQ8HX1wVxd/lNSxZ2NmX8pmfWXokY4jYdAxPUre/kj+ZIdcnNU3dc+FwyQMjRnd6laMvOd5Ky1 + /Q2TTu2EaoJzfrstcYWEfoJzfl3kxsgPOsFZ/49Oqh7I0aqTUjQ34XOMUTI3wcIT9zF/EQ8xsTBxu/it + FXYOJ36XWr7Cz+ETv/1YqRZaT2bKeCZk/PgBMI6sNR3scRB1XVpEcmkJvQf630NxygMdoaE44bHx6wdA + HTrTTWcU8kUeDDEBXcVbaZ/O6ktVYYoeoZ7l607cShO6bZDzwZb2afQ3vSOsx96rCVSWorbL8uH3oTjh + gXurW2mf7u8G9pe6wDQPjPqO5R7aH1eeGhqozbjihL+6eTtA0JcnBiSJeig+8sb9xP099vJVZabMaLre + /yniM+gMSr2SGXSfixs3UuUm7gQaG4NOvK9Z7nrO5eIr6khQS2UQQ2UIvS2aWgN8X54YCntrixj68tTQ + VS4leQcsckWpwAZc3UcisHT9/DsoukG+a4dZ6C9sOyW2v2U/BiQPhpjUu8lOF0BzA4jD/u/QR6UNuENT + jPjKXQtobGlK1/sGwW1xjz+WW5fFWX9AuzHBiM810IvOD8iZ/GCIqc7PbhmOWpsud0sFAkIfpV6dlfnX + rCo1ct2YUJ6tAPqWD4A4mkK3bm7ZniHIbzDFQl/d9GNLqG/AiK8tSkBjS1N6GO4V/ZIhzLmHAWSB+E4S + qwYblQ5alYb/s+ngP1vTdnvBZJzPscZV03DPPGyNkgm4CM76V02FPfOwNSKTYB7G+pDpLw9jfeDEV0hO + rG2udFZsi/tTJYulPhg4TfeaPJ5V6UdXNChnDH4t4Pg5gXyX6AhEvr27exuqgdoFB3Pu+1ERuSfw6H4X + RuG/R5Pwhy0HhSzNQCDO5dpu33TRxUxmFFw97Uv74tY7aRO8gpGdNb+uML+y5td+dUk3/So44FOas9/W + gHFZ8bh7ZOfN0NKBUcGTOvTZPUsLLu/33MTWunw9JwJxLtNA//oCMHDCk2Lv0RUqhi26AFfZ8rmJ0b35 + sisP7saqnyXMq0PTlea4+P43buBruaqu3H9AT2VGcM/fdm5Rln5GUesMy+iLCrw6+iln895fGzRmpyjj + dZW6K4N5h70jSr1uvKW/AtuNRwV5PTTw3p4+sbf3qtYlMAQUwQO/rRNeWo1BA2/VNCdtb0NPKtvZe1J3 + pwvqGUNQy+0GGrjsUez33/4Hk9kXTTeXBAA= EOF # We are renaming openssl to openssl_grpc so that there is no conflict with openssl if it exists diff --git a/src/objective-c/GRPCClient/GRPCCallLegacy.m b/src/objective-c/GRPCClient/GRPCCallLegacy.m index 4b84b5b8ada..0b028e92cf6 100644 --- a/src/objective-c/GRPCClient/GRPCCallLegacy.m +++ b/src/objective-c/GRPCClient/GRPCCallLegacy.m @@ -271,10 +271,14 @@ static NSString *const kBearerPrefix = @"Bearer "; } - (void)dealloc { - __block GRPCWrappedCall *wrappedCall = _wrappedCall; - dispatch_async(_callQueue, ^{ - wrappedCall = nil; - }); + if (_callQueue) { + __block GRPCWrappedCall *wrappedCall = _wrappedCall; + dispatch_async(_callQueue, ^{ + wrappedCall = nil; + }); + } else { + _wrappedCall = nil; + } } #pragma mark Read messages diff --git a/src/objective-c/GRPCClient/private/GRPCCore/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCCore/GRPCChannel.m index b6043d3d51c..5ad1cb462d4 100644 --- a/src/objective-c/GRPCClient/private/GRPCCore/GRPCChannel.m +++ b/src/objective-c/GRPCClient/private/GRPCCore/GRPCChannel.m @@ -54,8 +54,8 @@ if (_callOptions.transport != NULL) { id transportFactory = [[GRPCTransportRegistry sharedInstance] getTransportFactoryWithID:_callOptions.transport]; - if (! - [transportFactory respondsToSelector:@selector(createCoreChannelFactoryWithCallOptions:)]) { + if (![transportFactory + respondsToSelector:@selector(createCoreChannelFactoryWithCallOptions:)]) { // impossible because we are using GRPCCore now [NSException raise:NSInternalInconsistencyException format:@"Transport factory type is wrong"]; diff --git a/src/objective-c/GRPCClient/version.h b/src/objective-c/GRPCClient/version.h index 954d45fd329..940ea5f6866 100644 --- a/src/objective-c/GRPCClient/version.h +++ b/src/objective-c/GRPCClient/version.h @@ -22,4 +22,4 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.37.0-dev" +#define GRPC_OBJC_VERSION_STRING @"1.38.0-dev" diff --git a/src/objective-c/tests/InteropTests/InteropTests.m b/src/objective-c/tests/InteropTests/InteropTests.m index ee84f369397..a13b95a0d95 100644 --- a/src/objective-c/tests/InteropTests/InteropTests.m +++ b/src/objective-c/tests/InteropTests/InteropTests.m @@ -1096,7 +1096,7 @@ static dispatch_once_t initGlobalInterceptorFactory; options.PEMRootCertificates = [[self class] PEMRootCertificates]; options.hostNameOverride = [[self class] hostNameOverride]; options.flowControlEnabled = YES; - __block BOOL canWriteData = NO; + __block int writeMessageCount = 0; __block GRPCStreamingProtoCall *call = [_service fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] @@ -1112,8 +1112,9 @@ static dispatch_once_t initGlobalInterceptorFactory; id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; - XCTAssertTrue(canWriteData); - canWriteData = NO; + XCTAssertLessThanOrEqual( + index, writeMessageCount, + @"Message received before writing message."); [call writeMessage:request]; [call receiveNextMessage]; } else { @@ -1131,7 +1132,7 @@ static dispatch_once_t initGlobalInterceptorFactory; [expectation fulfill]; } writeMessageCallback:^{ - canWriteData = YES; + writeMessageCount++; }] callOptions:options]; [call start]; @@ -1338,7 +1339,7 @@ static dispatch_once_t initGlobalInterceptorFactory; }]; }]; - [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; + [self waitForExpectationsWithTimeout:STREAMING_CALL_TEST_TIMEOUT handler:nil]; } - (void)testCompressedUnaryRPC { @@ -1527,10 +1528,10 @@ static dispatch_once_t initGlobalInterceptorFactory; NSArray *requests = @[ @1, @2, @3, @4 ]; NSArray *responses = @[ @1, @2, @3, @4 ]; - __block int index = 0; + __block int messageIndex = 0; - id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] - requestedResponseSize:responses[index]]; + id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[messageIndex] + requestedResponseSize:responses[messageIndex]]; GRPCMutableCallOptions *options = [[GRPCMutableCallOptions alloc] init]; // For backwards compatibility options.transportType = [[self class] transportType]; @@ -1539,24 +1540,26 @@ static dispatch_once_t initGlobalInterceptorFactory; options.hostNameOverride = [[self class] hostNameOverride]; options.flowControlEnabled = YES; options.interceptorFactories = @[ factory ]; - __block BOOL canWriteData = NO; + + __block int writeMessageCount = 0; __block GRPCStreamingProtoCall *call = [_service fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil messageCallback:^(id message) { - XCTAssertLessThan(index, 4, + XCTAssertLessThan(messageIndex, 4, @"More than 4 responses received."); id expected = [RMTStreamingOutputCallResponse - messageWithPayloadSize:responses[index]]; + messageWithPayloadSize:responses[messageIndex]]; XCTAssertEqualObjects(message, expected); - index += 1; - if (index < 4) { + messageIndex += 1; + if (messageIndex < 4) { id request = [RMTStreamingOutputCallRequest - messageWithPayloadSize:requests[index] - requestedResponseSize:responses[index]]; - XCTAssertTrue(canWriteData); - canWriteData = NO; + messageWithPayloadSize:requests[messageIndex] + requestedResponseSize:responses[messageIndex]]; + XCTAssertLessThanOrEqual( + messageIndex, writeMessageCount, + @"Message received before writing message."); [call writeMessage:request]; [call receiveNextMessage]; } else { @@ -1568,13 +1571,13 @@ static dispatch_once_t initGlobalInterceptorFactory; XCTAssertNil(error, @"Finished with unexpected error: %@", error); - XCTAssertEqual(index, 4, + XCTAssertEqual(messageIndex, 4, @"Received %i responses instead of 4.", - index); + messageIndex); [expectation fulfill]; } writeMessageCallback:^{ - canWriteData = YES; + writeMessageCount++; }] callOptions:options]; [call start]; @@ -1582,6 +1585,7 @@ static dispatch_once_t initGlobalInterceptorFactory; [call writeMessage:request]; [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil]; + XCTAssertEqual(writeMessageCount, 4); XCTAssertEqual(startCount, 1); XCTAssertEqual(writeDataCount, 4); XCTAssertEqual(finishCount, 1); @@ -1592,15 +1596,13 @@ static dispatch_once_t initGlobalInterceptorFactory; XCTAssertEqual(didWriteDataCount, 4); } -// Chain a default interceptor and a hook interceptor which, after two writes, cancels the call +// Chain a default interceptor and a hook interceptor which, after one write, cancels the call // under the hood but forward further data to the user. - (void)testHijackingInterceptor { - NSUInteger kCancelAfterWrites = 2; + NSUInteger kCancelAfterWrites = 1; XCTAssertNotNil([[self class] host]); __weak XCTestExpectation *expectUserCallComplete = [self expectationWithDescription:@"User call completed."]; - __weak XCTestExpectation *expectCallInternalComplete = - [self expectationWithDescription:@"Internal gRPC call completed."]; NSArray *responses = @[ @1, @2, @3, @4 ]; __block int index = 0; @@ -1657,7 +1659,6 @@ static dispatch_once_t initGlobalInterceptorFactory; XCTAssertNil(trailingMetadata); XCTAssertNotNil(error); XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED); - [expectCallInternalComplete fulfill]; } didWriteDataHook:nil]; @@ -1713,7 +1714,7 @@ static dispatch_once_t initGlobalInterceptorFactory; XCTAssertEqual(writeDataCount, 4); XCTAssertEqual(finishCount, 1); XCTAssertEqual(responseHeaderCount, 1); - XCTAssertEqual(responseDataCount, 2); + XCTAssertEqual(responseDataCount, 1); XCTAssertEqual(responseCloseCount, 1); } @@ -1786,7 +1787,7 @@ static dispatch_once_t initGlobalInterceptorFactory; options.flowControlEnabled = YES; globalInterceptorFactory.enabled = YES; - __block BOOL canWriteData = NO; + __block int writeMessageCount = 0; __block GRPCStreamingProtoCall *call = [_service fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil @@ -1798,8 +1799,9 @@ static dispatch_once_t initGlobalInterceptorFactory; id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; - XCTAssertTrue(canWriteData); - canWriteData = NO; + XCTAssertLessThanOrEqual( + index, writeMessageCount, + @"Message received before writing message."); [call writeMessage:request]; [call receiveNextMessage]; } else { @@ -1814,7 +1816,7 @@ static dispatch_once_t initGlobalInterceptorFactory; [expectation fulfill]; } writeMessageCallback:^{ - canWriteData = YES; + writeMessageCount++; }] callOptions:options]; [call start]; @@ -1973,7 +1975,7 @@ static dispatch_once_t initGlobalInterceptorFactory; options.interceptorFactories = @[ factory ]; globalInterceptorFactory.enabled = YES; - __block BOOL canWriteData = NO; + __block int writeMessageCount = 0; __block GRPCStreamingProtoCall *call = [_service fullDuplexCallWithResponseHandler:[[InteropTestsBlockCallbacks alloc] initWithInitialMetadataCallback:nil @@ -1983,7 +1985,9 @@ static dispatch_once_t initGlobalInterceptorFactory; id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index] requestedResponseSize:responses[index]]; - canWriteData = NO; + XCTAssertLessThanOrEqual( + index, writeMessageCount, + @"Message received before writing message."); [call writeMessage:request]; [call receiveNextMessage]; } else { @@ -1995,7 +1999,7 @@ static dispatch_once_t initGlobalInterceptorFactory; [expectation fulfill]; } writeMessageCallback:^{ - canWriteData = YES; + writeMessageCount++; }] callOptions:options]; [call start]; diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h index 160fb7b8ffd..63aa8af776b 100644 --- a/src/objective-c/tests/version.h +++ b/src/objective-c/tests/version.h @@ -22,5 +22,5 @@ // instead. This file can be regenerated from the template by running // `tools/buildgen/generate_projects.sh`. -#define GRPC_OBJC_VERSION_STRING @"1.37.0-dev" -#define GRPC_C_VERSION_STRING @"15.0.0" +#define GRPC_OBJC_VERSION_STRING @"1.38.0-dev" +#define GRPC_C_VERSION_STRING @"16.0.0" diff --git a/src/php/README.md b/src/php/README.md index 7c0aac9e3ad..ae06c3577d2 100644 --- a/src/php/README.md +++ b/src/php/README.md @@ -230,7 +230,7 @@ Or require the `google/protobuf` composer package. Add this to your ### Generate PHP classes from your service definition -With all the above done, now you can define your message and service defintion +With all the above done, now you can define your message and service definition in a `.proto` file and generate the corresponding PHP classes, which you can import into your project, with a command similar to the following: diff --git a/src/php/bin/generate_proto_php.sh b/src/php/bin/generate_proto_php.sh index 5dd22f665f5..c90475368a4 100755 --- a/src/php/bin/generate_proto_php.sh +++ b/src/php/bin/generate_proto_php.sh @@ -40,7 +40,7 @@ mv $output_file ./src/proto/grpc/testing/test.proto # interop test protos $PROTOC --proto_path=. \ --php_out=src/php/tests/interop \ - --grpc_out=src/php/tests/interop \ + --grpc_out=generate_server:src/php/tests/interop \ --plugin=$PLUGIN \ src/proto/grpc/testing/messages.proto \ src/proto/grpc/testing/empty.proto \ @@ -53,12 +53,3 @@ mv $output_file ./src/proto/grpc/testing/empty.proto sed 's/grpc\.testing\.EmptyMessage/grpc\.testing\.Empty/g' \ src/proto/grpc/testing/test.proto > $output_file mv $output_file ./src/proto/grpc/testing/test.proto - -# Hack for xDS interop: need this to be a separate file in the correct namespace. -# To be removed when grpc_php_plugin generates service stubs. -echo ' ./src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php diff --git a/src/php/bin/run_xds_client.sh b/src/php/bin/run_xds_client.sh new file mode 100755 index 00000000000..82809a344b6 --- /dev/null +++ b/src/php/bin/run_xds_client.sh @@ -0,0 +1,63 @@ +#!/bin/bash +# Copyright 2021 gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +# This script is being launched from the run_xds_tests.py runner and is +# responsible for managing child PHP processes. + +cleanup () { + echo "Trapped SIGTERM. Cleaning up..." + set -x + kill -9 $PID1 + kill -9 $PID2 + running=false + set +x +} + +trap cleanup SIGTERM + +set -e +cd $(dirname $0)/../../.. +root=$(pwd) + +# tmp_file1 contains the list of RPCs (and their spec) the parent PHP +# process want executed +tmp_file1=$(mktemp) +# tmp_file2 contains the RPC result of each key initiated +tmp_file2=$(mktemp) + +set -x +# This is the PHP parent process, who is primarily responding to the +# run_xds_tests.py runner's stats requests +php -d extension=grpc.so -d extension=pthreads.so \ + src/php/tests/interop/xds_client.php $1 $2 $3 $4 $5 $6 \ + --tmp_file1=$tmp_file1 --tmp_file2=$tmp_file2 & +PID1=$! + +# This script watches RPCs written to tmp_file1, spawn off more PHP +# child processes to execute them, and writes the result to tmp_file2 +python3 -u src/php/bin/xds_manager.py \ + --tmp_file1=$tmp_file1 --tmp_file2=$tmp_file2 \ + --bootstrap_path=$GRPC_XDS_BOOTSTRAP & +PID2=$! +set +x + +# This will be killed by a SIGTERM signal from the run_xds_tests.py +# runner +running=true +while $running +do + sleep 1 +done diff --git a/src/php/bin/xds_manager.py b/src/php/bin/xds_manager.py new file mode 100755 index 00000000000..da7ea666b2a --- /dev/null +++ b/src/php/bin/xds_manager.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# Copyright 2021 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. +"""Manage PHP child processes for the main PHP xDS Interop client""" + +import argparse +import fcntl +import os +import subprocess + +# This script is being launched from src/php/bin/run_xds_client.sh +# to manage PHP child processes which will send 1 RPC each +# asynchronously. This script keeps track of all those open +# processes and reports back to the main PHP interop client each +# of the child RPCs' status code. + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--tmp_file1', nargs='?', default='') + parser.add_argument('--tmp_file2', nargs='?', default='') + parser.add_argument('--bootstrap_path', nargs='?', default='') + args = parser.parse_args() + server_address = '' + rpcs_started = [] + open_processes = {} + client_env = dict(os.environ) + client_env['GRPC_XDS_BOOTSTRAP'] = args.bootstrap_path + while True: + # tmp_file1 contains a list of RPCs (and their spec) the parent process + # wants executed + f1 = open(args.tmp_file1, 'r+') + fcntl.flock(f1, fcntl.LOCK_EX) + while True: + key = f1.readline() + if not key: + break + key = key.strip() + if key.startswith('server_address'): + if not server_address: + server_address = key[15:] + elif not key in rpcs_started: + # format here needs to be in sync with + # src/php/tests/interop/xds_client.php + items = key.split('|') + num = items[0] + metadata = items[2] + timeout_sec = items[3] + if items[1] == 'UnaryCall': + p = subprocess.Popen([ + 'php', '-d', 'extension=grpc.so', '-d', + 'extension=pthreads.so', + 'src/php/tests/interop/xds_unary_call.php', + '--server=' + server_address, '--num=' + str(num), + '--metadata=' + metadata, '--timeout_sec=' + timeout_sec + ], + env=client_env) + elif items[1] == 'EmptyCall': + p = subprocess.Popen([ + 'php', '-d', 'extension=grpc.so', '-d', + 'extension=pthreads.so', + 'src/php/tests/interop/xds_empty_call.php', + '--server=' + server_address, '--num=' + str(num), + '--metadata=' + metadata, '--timeout=' + timeout_sec + ], + env=client_env) + else: + continue + rpcs_started.append(key) + open_processes[key] = p + f1.truncate(0) + fcntl.flock(f1, fcntl.LOCK_UN) + f1.close() + # tmp_file2 contains the RPC result of each key received from tmp_file1 + f2 = open(args.tmp_file2, 'a') + fcntl.flock(f2, fcntl.LOCK_EX) + keys_to_delete = [] + for key, process in open_processes.items(): + result = process.poll() + if result is not None: + # format here needs to be in sync with + # src/php/tests/interop/xds_client.php + f2.write(key + ',' + str(process.returncode) + "\n") + keys_to_delete.append(key) + for key in keys_to_delete: + del open_processes[key] + fcntl.flock(f2, fcntl.LOCK_UN) + f2.close() diff --git a/src/php/composer.json b/src/php/composer.json index 511dbc825ce..3cea59fad82 100644 --- a/src/php/composer.json +++ b/src/php/composer.json @@ -2,7 +2,7 @@ "name": "grpc/grpc-dev", "description": "gRPC library for PHP - for Development use only", "license": "Apache-2.0", - "version": "1.37.0", + "version": "1.38.0", "require": { "php": ">=7.0.0", "google/protobuf": "^v3.3.0" diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c index ef6b86ebb86..1abc4a3faf7 100644 --- a/src/php/ext/grpc/call.c +++ b/src/php/ext/grpc/call.c @@ -314,6 +314,11 @@ PHP_METHOD(Call, startBatch) { goto cleanup; } + // c-core may call rand(). If we don't call srand() here, all the + // random numbers being returned would be the same. + gpr_timespec now = gpr_now(GPR_CLOCK_REALTIME); + srand(now.tv_nsec); + array_hash = Z_ARRVAL_P(array); char *key = NULL; diff --git a/src/php/ext/grpc/channel_credentials.c b/src/php/ext/grpc/channel_credentials.c index 43080661cd9..34b4c826085 100644 --- a/src/php/ext/grpc/channel_credentials.c +++ b/src/php/ext/grpc/channel_credentials.c @@ -233,10 +233,7 @@ PHP_METHOD(ChannelCredentials, createComposite) { * @return null */ PHP_METHOD(ChannelCredentials, createInsecure) { - grpc_channel_credentials* creds = grpc_insecure_credentials_create(); - zval* creds_object = grpc_php_wrap_channel_credentials( - creds, strdup("INSECURE"), false TSRMLS_CC); - RETURN_DESTROY_ZVAL(creds_object); + RETURN_NULL(); } /** diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h index 4762ae45cdd..7103ba859a3 100644 --- a/src/php/ext/grpc/version.h +++ b/src/php/ext/grpc/version.h @@ -20,6 +20,6 @@ #ifndef VERSION_H #define VERSION_H -#define PHP_GRPC_VERSION "1.37.0dev" +#define PHP_GRPC_VERSION "1.38.0dev" #endif /* VERSION_H */ diff --git a/src/php/lib/Grpc/CallInvoker.php b/src/php/lib/Grpc/CallInvoker.php index a1b45532120..aacd54e8628 100644 --- a/src/php/lib/Grpc/CallInvoker.php +++ b/src/php/lib/Grpc/CallInvoker.php @@ -21,7 +21,6 @@ namespace Grpc; /** * CallInvoker is used to pass the self defined channel into the stub, * while intercept each RPC with the channel accessible. - * THIS IS AN EXPERIMENTAL API. */ interface CallInvoker { diff --git a/src/php/lib/Grpc/DefaultCallInvoker.php b/src/php/lib/Grpc/DefaultCallInvoker.php index e5b1e13a674..217dafa816a 100644 --- a/src/php/lib/Grpc/DefaultCallInvoker.php +++ b/src/php/lib/Grpc/DefaultCallInvoker.php @@ -20,7 +20,6 @@ namespace Grpc; /** * Default call invoker in the gRPC stub. - * THIS IS AN EXPERIMENTAL API. */ class DefaultCallInvoker implements CallInvoker { diff --git a/src/php/lib/Grpc/Interceptor.php b/src/php/lib/Grpc/Interceptor.php index cc465b566e1..c3bf6165c19 100644 --- a/src/php/lib/Grpc/Interceptor.php +++ b/src/php/lib/Grpc/Interceptor.php @@ -23,7 +23,6 @@ namespace Grpc; * Represents an interceptor that intercept RPC invocations before call starts. * There is one proposal related to the argument $deserialize under the review. * The proposal link is https://github.com/grpc/proposal/pull/86. - * This is an EXPERIMENTAL API. */ class Interceptor { diff --git a/src/php/lib/Grpc/MethodDescriptor.php b/src/php/lib/Grpc/MethodDescriptor.php new file mode 100644 index 00000000000..c0faf75a887 --- /dev/null +++ b/src/php/lib/Grpc/MethodDescriptor.php @@ -0,0 +1,52 @@ +service = $service; + $this->method_name = $method_name; + $this->request_type = $request_type; + $this->call_type = $call_type; + } + + public const UNARY_CALL = 0; + public const SERVER_STREAMING_CALL = 1; + public const CLIENT_STREAMING_CALL = 2; + public const BIDI_STREAMING_CALL = 3; + + public $service; + public $method_name; + public $request_type; + public $call_type; +} diff --git a/src/php/lib/Grpc/RpcServer.php b/src/php/lib/Grpc/RpcServer.php index 4c88b2e1849..c631e58fa3d 100644 --- a/src/php/lib/Grpc/RpcServer.php +++ b/src/php/lib/Grpc/RpcServer.php @@ -32,137 +32,120 @@ namespace Grpc; */ class RpcServer extends Server { - protected $call; - // [ => [ - // 'service' => , - // 'method' => , - // 'request' => , - // ] ] - protected $paths_map; + // [ => MethodDescriptor ] + private $paths_map = []; - private function waitForNextEvent() { + private function waitForNextEvent() + { return $this->requestCall(); } - private function loadRequest($request) { - if (!$this->call) { - throw new Exception("serverCall is not ready"); - } - $event = $this->call->startBatch([ - OP_RECV_MESSAGE => true, - ]); - if (!$event->message) { - throw new Exception("Did not receive a proper message"); - } - $request->mergeFromString($event->message); - return $request; - } - - protected function sendOkResponse($response) { - if (!$this->call) { - throw new Exception("serverCall is not ready"); - } - $this->call->startBatch([ - OP_SEND_INITIAL_METADATA => [], - OP_SEND_MESSAGE => ['message' => - $response->serializeToString()], - OP_SEND_STATUS_FROM_SERVER => [ - 'metadata' => [], - 'code' => STATUS_OK, - 'details' => 'OK', - ], - OP_RECV_CLOSE_ON_SERVER => true, - ]); - } - /** * Add a service to this server * * @param Object $service The service to be added */ - public function handle($service) { - $rf = new \ReflectionClass($service); - - // If input does not have a parent class, which should be the - // generated stub, don't proceeed. This might change in the - // future. - if (!$rf->getParentClass()) return; - - // The input class name needs to match the service name - $service_name = $rf->getName(); - $namespace = $rf->getParentClass()->getNamespaceName(); - $prefix = ""; - if ($namespace) { - $parts = explode("\\", $namespace); - foreach ($parts as $part) { - $prefix .= lcfirst($part) . "."; - } + public function handle($service) + { + $methodDescriptors = $service->getMethodDescriptors(); + $exist_methods = array_intersect_key($this->paths_map, $methodDescriptors); + if (!empty($exist_methods)) { + fwrite(STDERR, "WARNING: " . 'override already registered methods: ' . + implode(', ', array_keys($exist_methods)) . PHP_EOL); } - $base_path = "/" . $prefix . $service_name; - - // Right now, assume all the methods in the class are RPC method - // implementations. Might change in the future. - $methods = $rf->getMethods(); - foreach ($methods as $method) { - $method_name = $method->getName(); - $full_path = $base_path . "/" . ucfirst($method_name); - $method_params = $method->getParameters(); - // RPC should have exactly 1 request param - if (count($method_params) != 1) continue; - $request_param = $method_params[0]; - // Method implementation must have type hint for request param - if (!$request_param->getType()) continue; - $request_type = $request_param->getType()->getName(); - - // $full_path needs to match the incoming event->method - // from requestCall() for us to know how to handle the request - $this->paths_map[$full_path] = [ - 'service' => $service, - 'method' => $method_name, - 'request' => new $request_type(), - ]; - } + $this->paths_map = array_merge($this->paths_map, $methodDescriptors); + return $this->paths_map; } - public function run() { + public function run() + { $this->start(); - while (true) { + while (true) try { // This blocks until the server receives a request $event = $this->waitForNextEvent(); - if (!$event) { - throw new Exception( - "Unexpected error: server->waitForNextEvent delivers" - . " an empty event"); - } - if (!$event->call) { - throw new Exception( - "Unexpected error: server->waitForNextEvent delivers" - . " an event without a call"); - } - $this->call = $event->call; - $full_path = $event->method; - - // TODO: Can send a proper UNIMPLEMENTED response in the future - if (!array_key_exists($full_path, $this->paths_map)) continue; - $service = $this->paths_map[$full_path]['service']; - $method = $this->paths_map[$full_path]['method']; - $request = $this->paths_map[$full_path]['request']; - - $request = $this->loadRequest($request); - if (!$request) { - throw new Exception("Unexpected error: fail to parse request"); - } - if (!method_exists($service, $method)) { - // TODO: Can send a proper UNIMPLEMENTED response in the future - throw new Exception("Method not implemented"); + $full_path = $event->method; + $context = new ServerContext($event); + $server_writer = new ServerCallWriter($event->call, $context); + + if (!array_key_exists($full_path, $this->paths_map)) { + $context->setStatus(Status::unimplemented()); + $server_writer->finish(); + continue; + }; + + $method_desc = $this->paths_map[$full_path]; + $server_reader = new ServerCallReader( + $event->call, + $method_desc->request_type + ); + + try { + $this->processCall( + $method_desc, + $server_reader, + $server_writer, + $context + ); + } catch (\Exception $e) { + $context->setStatus(Status::status( + STATUS_INTERNAL, + $e->getMessage() + )); + $server_writer->finish(); } + } catch (\Exception $e) { + fwrite(STDERR, "ERROR: " . $e->getMessage() . PHP_EOL); + exit(1); + } + } - // Dispatch to actual server logic - $response = $service->$method($request); - $this->sendOkResponse($response); - $this->call = null; + private function processCall( + MethodDescriptor $method_desc, + ServerCallReader $server_reader, + ServerCallWriter $server_writer, + ServerContext $context + ) { + // Dispatch to actual server logic + switch ($method_desc->call_type) { + case MethodDescriptor::UNARY_CALL: + $request = $server_reader->read(); + $response = + call_user_func( + array($method_desc->service, $method_desc->method_name), + $request ?? new $method_desc->request_type, + $context + ); + $server_writer->finish($response); + break; + case MethodDescriptor::SERVER_STREAMING_CALL: + $request = $server_reader->read(); + call_user_func( + array($method_desc->service, $method_desc->method_name), + $request ?? new $method_desc->request_type, + $server_writer, + $context + ); + break; + case MethodDescriptor::CLIENT_STREAMING_CALL: + $response = call_user_func( + array($method_desc->service, $method_desc->method_name), + $server_reader, + $context + ); + $server_writer->finish($response); + break; + case MethodDescriptor::BIDI_STREAMING_CALL: + call_user_func( + array($method_desc->service, $method_desc->method_name), + $server_reader, + $server_writer, + $context + ); + break; + default: + throw new \Exception(); } } } diff --git a/src/php/lib/Grpc/ServerCallWriter.php b/src/php/lib/Grpc/ServerCallWriter.php index f9d8d9e9cc5..aceb20c38bf 100644 --- a/src/php/lib/Grpc/ServerCallWriter.php +++ b/src/php/lib/Grpc/ServerCallWriter.php @@ -28,44 +28,51 @@ namespace Grpc; class ServerCallWriter { - public function __construct($call) + public function __construct($call, $serverContext) { $this->call_ = $call; + $this->serverContext_ = $serverContext; } public function start( - array $initialMetadata, $data = null, array $options = [] ) { $batch = []; - $this->addSendInitialMetadataOpIfNotSent($batch, $initialMetadata); + $this->addSendInitialMetadataOpIfNotSent( + $batch, + $this->serverContext_->initialMetadata() + ); $this->addSendMessageOpIfHasData($batch, $data, $options); $this->call_->startBatch($batch); } public function write( $data, - array $options = [], - array $initialMetadata = null + array $options = [] ) { $batch = []; - $this->addSendInitialMetadataOpIfNotSent($batch, $initialMetadata); + $this->addSendInitialMetadataOpIfNotSent( + $batch, + $this->serverContext_->initialMetadata() + ); $this->addSendMessageOpIfHasData($batch, $data, $options); $this->call_->startBatch($batch); } public function finish( - array $status = null, - array $initialMetadata = null, $data = null, array $options = [] ) { $batch = [ - OP_SEND_STATUS_FROM_SERVER => $status ?? Status::ok(), + OP_SEND_STATUS_FROM_SERVER => + $this->serverContext_->status() ?? Status::ok(), OP_RECV_CLOSE_ON_SERVER => true, ]; - $this->addSendInitialMetadataOpIfNotSent($batch, $initialMetadata); + $this->addSendInitialMetadataOpIfNotSent( + $batch, + $this->serverContext_->initialMetadata() + ); $this->addSendMessageOpIfHasData($batch, $data, $options); $this->call_->startBatch($batch); } @@ -98,4 +105,5 @@ class ServerCallWriter private $call_; private $initialMetadataSent_ = false; + private $serverContext_; } diff --git a/src/php/lib/Grpc/ServerContext.php b/src/php/lib/Grpc/ServerContext.php new file mode 100644 index 00000000000..104250ea21b --- /dev/null +++ b/src/php/lib/Grpc/ServerContext.php @@ -0,0 +1,76 @@ +event = $event; + } + + public function clientMetadata() + { + return $this->event->metadata; + } + public function deadline() + { + return $this->event->absolute_deadline; + } + public function host() + { + return $this->event->host; + } + public function method() + { + return $this->event->method; + } + + public function setInitialMetadata($initialMetadata) + { + $this->initialMetadata_ = $initialMetadata; + } + + public function initialMetadata() + { + return $this->initialMetadata_; + } + + public function setStatus($status) + { + $this->status_ = $status; + } + + public function status() + { + return $this->status_; + } + + private $event; + private $initialMetadata_; + private $status_; +} diff --git a/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php b/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php index 529f5b0c4a7..f99f489d4b8 100644 --- a/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php +++ b/src/php/tests/interop/Grpc/Testing/LoadBalancerStatsServiceStub.php @@ -1,6 +1,82 @@ setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Gets the accumulated stats for RPCs sent by a test client. + * @param \Grpc\Testing\LoadBalancerAccumulatedStatsRequest $request client request + * @param \Grpc\ServerContext $context server request context + * @return \Grpc\Testing\LoadBalancerAccumulatedStatsResponse for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function GetClientAccumulatedStats( + \Grpc\Testing\LoadBalancerAccumulatedStatsRequest $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\LoadBalancerAccumulatedStatsResponse { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/grpc.testing.LoadBalancerStatsService/GetClientStats' => new \Grpc\MethodDescriptor( + $this, + 'GetClientStats', + '\Grpc\Testing\LoadBalancerStatsRequest', + \Grpc\MethodDescriptor::UNARY_CALL + ), + '/grpc.testing.LoadBalancerStatsService/GetClientAccumulatedStats' => new \Grpc\MethodDescriptor( + $this, + 'GetClientAccumulatedStats', + '\Grpc\Testing\LoadBalancerAccumulatedStatsRequest', + \Grpc\MethodDescriptor::UNARY_CALL + ), + ]; + } + +} diff --git a/src/php/tests/interop/Grpc/Testing/ReconnectServiceStub.php b/src/php/tests/interop/Grpc/Testing/ReconnectServiceStub.php new file mode 100644 index 00000000000..450ecc0e8a1 --- /dev/null +++ b/src/php/tests/interop/Grpc/Testing/ReconnectServiceStub.php @@ -0,0 +1,80 @@ +setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * @param \Grpc\Testing\EmptyMessage $request client request + * @param \Grpc\ServerContext $context server request context + * @return \Grpc\Testing\ReconnectInfo for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function Stop( + \Grpc\Testing\EmptyMessage $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\ReconnectInfo { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/grpc.testing.ReconnectService/Start' => new \Grpc\MethodDescriptor( + $this, + 'Start', + '\Grpc\Testing\ReconnectParams', + \Grpc\MethodDescriptor::UNARY_CALL + ), + '/grpc.testing.ReconnectService/Stop' => new \Grpc\MethodDescriptor( + $this, + 'Stop', + '\Grpc\Testing\EmptyMessage', + \Grpc\MethodDescriptor::UNARY_CALL + ), + ]; + } + +} diff --git a/src/php/tests/interop/Grpc/Testing/TestServiceStub.php b/src/php/tests/interop/Grpc/Testing/TestServiceStub.php new file mode 100644 index 00000000000..d6c3fac7afe --- /dev/null +++ b/src/php/tests/interop/Grpc/Testing/TestServiceStub.php @@ -0,0 +1,222 @@ +setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * One request followed by one response. + * @param \Grpc\Testing\SimpleRequest $request client request + * @param \Grpc\ServerContext $context server request context + * @return \Grpc\Testing\SimpleResponse for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function UnaryCall( + \Grpc\Testing\SimpleRequest $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\SimpleResponse { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * One request followed by one response. Response has cache control + * headers set such that a caching HTTP proxy (such as GFE) can + * satisfy subsequent requests. + * @param \Grpc\Testing\SimpleRequest $request client request + * @param \Grpc\ServerContext $context server request context + * @return \Grpc\Testing\SimpleResponse for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function CacheableUnaryCall( + \Grpc\Testing\SimpleRequest $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\SimpleResponse { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * One request followed by a sequence of responses (streamed download). + * The server returns the payload with client desired type and sizes. + * @param \Grpc\Testing\StreamingOutputCallRequest $request client request + * @param \Grpc\ServerCallWriter $writer write response data of \Grpc\Testing\StreamingOutputCallResponse + * @param \Grpc\ServerContext $context server request context + * @return void + */ + public function StreamingOutputCall( + \Grpc\Testing\StreamingOutputCallRequest $request, + \Grpc\ServerCallWriter $writer, + \Grpc\ServerContext $context + ): void { + $context->setStatus(\Grpc\Status::unimplemented()); + $writer->finish(); + } + + /** + * A sequence of requests followed by one response (streamed upload). + * The server returns the aggregated size of client payload as the result. + * @param \Grpc\ServerCallReader $reader read client request data of \Grpc\Testing\StreamingInputCallRequest + * @param \Grpc\ServerContext $context server request context + * @return \Grpc\Testing\StreamingInputCallResponse for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function StreamingInputCall( + \Grpc\ServerCallReader $reader, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\StreamingInputCallResponse { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * A sequence of requests with each request served by the server immediately. + * As one request could lead to multiple responses, this interface + * demonstrates the idea of full duplexing. + * @param \Grpc\ServerCallReader $reader read client request data of \Grpc\Testing\StreamingOutputCallRequest + * @param \Grpc\ServerCallWriter $writer write response data of \Grpc\Testing\StreamingOutputCallResponse + * @param \Grpc\ServerContext $context server request context + * @return void + */ + public function FullDuplexCall( + \Grpc\ServerCallReader $reader, + \Grpc\ServerCallWriter $writer, + \Grpc\ServerContext $context + ): void { + $context->setStatus(\Grpc\Status::unimplemented()); + $writer->finish(); + } + + /** + * A sequence of requests followed by a sequence of responses. + * The server buffers all the client requests and then serves them in order. A + * stream of responses are returned to the client when the server starts with + * first request. + * @param \Grpc\ServerCallReader $reader read client request data of \Grpc\Testing\StreamingOutputCallRequest + * @param \Grpc\ServerCallWriter $writer write response data of \Grpc\Testing\StreamingOutputCallResponse + * @param \Grpc\ServerContext $context server request context + * @return void + */ + public function HalfDuplexCall( + \Grpc\ServerCallReader $reader, + \Grpc\ServerCallWriter $writer, + \Grpc\ServerContext $context + ): void { + $context->setStatus(\Grpc\Status::unimplemented()); + $writer->finish(); + } + + /** + * The test server will not implement this method. It will be used + * to test the behavior when clients call unimplemented methods. + * @param \Grpc\Testing\EmptyMessage $request client request + * @param \Grpc\ServerContext $context server request context + * @return \Grpc\Testing\EmptyMessage for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function UnimplementedCall( + \Grpc\Testing\EmptyMessage $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\EmptyMessage { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/grpc.testing.TestService/EmptyCall' => new \Grpc\MethodDescriptor( + $this, + 'EmptyCall', + '\Grpc\Testing\EmptyMessage', + \Grpc\MethodDescriptor::UNARY_CALL + ), + '/grpc.testing.TestService/UnaryCall' => new \Grpc\MethodDescriptor( + $this, + 'UnaryCall', + '\Grpc\Testing\SimpleRequest', + \Grpc\MethodDescriptor::UNARY_CALL + ), + '/grpc.testing.TestService/CacheableUnaryCall' => new \Grpc\MethodDescriptor( + $this, + 'CacheableUnaryCall', + '\Grpc\Testing\SimpleRequest', + \Grpc\MethodDescriptor::UNARY_CALL + ), + '/grpc.testing.TestService/StreamingOutputCall' => new \Grpc\MethodDescriptor( + $this, + 'StreamingOutputCall', + '\Grpc\Testing\StreamingOutputCallRequest', + \Grpc\MethodDescriptor::SERVER_STREAMING_CALL + ), + '/grpc.testing.TestService/StreamingInputCall' => new \Grpc\MethodDescriptor( + $this, + 'StreamingInputCall', + '\Grpc\Testing\StreamingInputCallRequest', + \Grpc\MethodDescriptor::CLIENT_STREAMING_CALL + ), + '/grpc.testing.TestService/FullDuplexCall' => new \Grpc\MethodDescriptor( + $this, + 'FullDuplexCall', + '\Grpc\Testing\StreamingOutputCallRequest', + \Grpc\MethodDescriptor::BIDI_STREAMING_CALL + ), + '/grpc.testing.TestService/HalfDuplexCall' => new \Grpc\MethodDescriptor( + $this, + 'HalfDuplexCall', + '\Grpc\Testing\StreamingOutputCallRequest', + \Grpc\MethodDescriptor::BIDI_STREAMING_CALL + ), + '/grpc.testing.TestService/UnimplementedCall' => new \Grpc\MethodDescriptor( + $this, + 'UnimplementedCall', + '\Grpc\Testing\EmptyMessage', + \Grpc\MethodDescriptor::UNARY_CALL + ), + ]; + } + +} diff --git a/src/php/tests/interop/Grpc/Testing/UnimplementedServiceStub.php b/src/php/tests/interop/Grpc/Testing/UnimplementedServiceStub.php new file mode 100644 index 00000000000..086cca2fb02 --- /dev/null +++ b/src/php/tests/interop/Grpc/Testing/UnimplementedServiceStub.php @@ -0,0 +1,62 @@ +setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/grpc.testing.UnimplementedService/UnimplementedCall' => new \Grpc\MethodDescriptor( + $this, + 'UnimplementedCall', + '\Grpc\Testing\EmptyMessage', + \Grpc\MethodDescriptor::UNARY_CALL + ), + ]; + } + +} diff --git a/src/php/tests/interop/Grpc/Testing/XdsUpdateClientConfigureServiceStub.php b/src/php/tests/interop/Grpc/Testing/XdsUpdateClientConfigureServiceStub.php new file mode 100644 index 00000000000..fb3bb1ce0bf --- /dev/null +++ b/src/php/tests/interop/Grpc/Testing/XdsUpdateClientConfigureServiceStub.php @@ -0,0 +1,61 @@ +setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/grpc.testing.XdsUpdateClientConfigureService/Configure' => new \Grpc\MethodDescriptor( + $this, + 'Configure', + '\Grpc\Testing\ClientConfigureRequest', + \Grpc\MethodDescriptor::UNARY_CALL + ), + ]; + } + +} diff --git a/src/php/tests/interop/Grpc/Testing/XdsUpdateHealthServiceStub.php b/src/php/tests/interop/Grpc/Testing/XdsUpdateHealthServiceStub.php new file mode 100644 index 00000000000..07ff63ab2d3 --- /dev/null +++ b/src/php/tests/interop/Grpc/Testing/XdsUpdateHealthServiceStub.php @@ -0,0 +1,80 @@ +setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * @param \Grpc\Testing\EmptyMessage $request client request + * @param \Grpc\ServerContext $context server request context + * @return \Grpc\Testing\EmptyMessage for response data, null if if error occured + * initial metadata (if any) and status (if not ok) should be set to $context + */ + public function SetNotServing( + \Grpc\Testing\EmptyMessage $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\EmptyMessage { + $context->setStatus(\Grpc\Status::unimplemented()); + return null; + } + + /** + * Get the method descriptors of the service for server registration + * + * @return array of \Grpc\MethodDescriptor for the service methods + */ + public final function getMethodDescriptors(): array + { + return [ + '/grpc.testing.XdsUpdateHealthService/SetServing' => new \Grpc\MethodDescriptor( + $this, + 'SetServing', + '\Grpc\Testing\EmptyMessage', + \Grpc\MethodDescriptor::UNARY_CALL + ), + '/grpc.testing.XdsUpdateHealthService/SetNotServing' => new \Grpc\MethodDescriptor( + $this, + 'SetNotServing', + '\Grpc\Testing\EmptyMessage', + \Grpc\MethodDescriptor::UNARY_CALL + ), + ]; + } + +} diff --git a/src/php/tests/interop/xds_client.php b/src/php/tests/interop/xds_client.php index 6927ce30a7d..c2e3cfcec52 100644 --- a/src/php/tests/interop/xds_client.php +++ b/src/php/tests/interop/xds_client.php @@ -25,12 +25,63 @@ $autoload_path = realpath(dirname(__FILE__).'/../../vendor/autoload.php'); require_once $autoload_path; +class XdsUpdateClientConfigureService + extends \Grpc\Testing\XdsUpdateClientConfigureServiceStub +{ + function configure( + \Grpc\Testing\ClientConfigureRequest $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\ClientConfigureResponse { + $rpc_types = $request->getTypes(); + $all_metadata = $request->getMetadata(); + $rpcs_to_send = []; + foreach ($rpc_types as $rpc_type) { + if ($rpc_type == + \Grpc\Testing\ClientConfigureRequest\RpcType::EMPTY_CALL) { + $rpcs_to_send[] = 'EmptyCall'; + } else if ($rpc_type == + \Grpc\Testing\ClientConfigureRequest\RpcType::UNARY_CALL) { + $rpcs_to_send[] = 'UnaryCall'; + } + } + $metadata_to_send = []; + foreach ($all_metadata as $metadata) { + $rpc_type = $metadata->getType(); + if ($rpc_type == + \Grpc\Testing\ClientConfigureRequest\RpcType::EMPTY_CALL) { + $rpc_type_key = 'EmptyCall'; + } else if ($rpc_type == + \Grpc\Testing\ClientConfigureRequest\RpcType::UNARY_CALL) { + $rpc_type_key = 'UnaryCall'; + } + $key = $metadata->getKey(); + $value = $metadata->getValue(); + if (!isset($metadata_to_send[$rpc_type_key])) { + $metadata_to_send[$rpc_type_key] = []; + } + $metadata_to_send[$rpc_type_key][$key] = $value; + } + global $client_thread; + echo "PHP parent: Setting client_thread rpc_config to \n"; + print_r($rpcs_to_send); + print_r($metadata_to_send); + echo "PHP parent: timeout_sec = ".$request->getTimeoutSec()."\n"; + $client_thread->rpc_config->update($rpcs_to_send, + $metadata_to_send, + $request->getTimeoutSec()); + return new Grpc\Testing\ClientConfigureResponse(); + } +} + // The main xds interop test runner will ping this service to ask for // the stats of the distribution of the backends, for the next X rpcs. class LoadBalancerStatsService extends \Grpc\Testing\LoadBalancerStatsServiceStub { - function getClientStats(\Grpc\Testing\LoadBalancerStatsRequest $request) { + function getClientStats( + \Grpc\Testing\LoadBalancerStatsRequest $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\LoadBalancerStatsResponse { $num_rpcs = $request->getNumRpcs(); $timeout_sec = $request->getTimeoutSec(); $rpcs_by_method = []; @@ -69,7 +120,8 @@ class LoadBalancerStatsService // '', 'hostname1', 'hostname2', '', 'hostname2', ... // ], // ] - foreach ($client_thread->results as $rpc => $results) { + foreach ((array)$client_thread->rpc_config->rpcs_to_send as $rpc) { + $results = $client_thread->results[$rpc]; // initialize, can always start from scratch here $rpcs_by_method[$rpc] = []; for ($i = $start_id; $i < $end_id; $i++) { @@ -108,71 +160,206 @@ class LoadBalancerStatsService $response->setNumFailures($num_failures); return $response; } + + function GetClientAccumulatedStats( + \Grpc\Testing\LoadBalancerAccumulatedStatsRequest $request, + \Grpc\ServerContext $context + ): ?\Grpc\Testing\LoadBalancerAccumulatedStatsResponse { + global $client_thread; + $response = new Grpc\Testing\LoadBalancerAccumulatedStatsResponse(); + $response->setNumRpcsStartedByMethod( + (array)$client_thread->num_rpcs_started_by_method); + $response->setNumRpcsSucceededByMethod( + (array)$client_thread->num_rpcs_succeeded_by_method); + $response->setNumRpcsFailedByMethod( + (array)$client_thread->num_rpcs_failed_by_method); + $accumulated_method_stats + = (array)$client_thread->accumulated_method_stats; + $stats_per_method = []; + foreach ($accumulated_method_stats as $rpc_name => $stats) { + $methodStats + = new Grpc\Testing\LoadBalancerAccumulatedStatsResponse\MethodStats(); + $methodStats->setRpcsStarted($stats['rpcs_started']); + $methodStats->setResult((array)$stats['result']); + $stats_per_method[$rpc_name] = $methodStats; + } + $response->setStatsPerMethod($stats_per_method); + return $response; + } +} + +class RpcConfig extends Volatile { + public $server_address; + public $qps; + public $fail_on_failed_rpcs; + public $rpcs_to_send; + public $metadata_to_send; + public $tmp_file1; + public $tmp_file2; + public $timeout_sec; + public function __construct($server_address, + $qps, + $fail_on_failed_rpcs, + $rpcs_to_send, + $metadata_to_send, + $tmp_file1, + $tmp_file2) { + $this->server_address = $server_address; + $this->qps = $qps; + $this->fail_on_failed_rpcs = $fail_on_failed_rpcs; + $this->rpcs_to_send = (array)$rpcs_to_send; + $this->metadata_to_send = (array)$metadata_to_send; + $this->tmp_file1 = $tmp_file1; + $this->tmp_file2 = $tmp_file2; + $this->timeout_sec = 30; + } + public function update($rpcs_to_send, $metadata_to_send, $timeout_sec) { + $this->rpcs_to_send = (array)$rpcs_to_send; + $this->metadata_to_send = (array)$metadata_to_send; + $this->timeout_sec = $timeout_sec; + } } // This client thread blindly sends a unary RPC to the server once // every 1 / qps seconds. class ClientThread extends Thread { - private $server_address_; private $target_seconds_between_rpcs_; - private $fail_on_failed_rpcs_; private $autoload_path_; private $TIMEOUT_US = 30 * 1e6; // 30 seconds + public $rpc_config; public $num_results = 0; public $results; - public function __construct($server_address, $qps, $fail_on_failed_rpcs, - $rpcs_to_send, $metadata_to_send, + public $RPC_MAP = [ + 'UnaryCall' => 'UNARY_CALL', + 'EmptyCall' => 'EMPTY_CALL', + ]; + + public $num_rpcs_started_by_method = []; + public $num_rpcs_succeeded_by_method = []; + public $num_rpcs_failed_by_method = []; + public $accumulated_method_stats = []; + + public function __construct($rpc_config, $autoload_path) { - $this->server_address_ = $server_address; - $this->target_seconds_between_rpcs_ = 1.0 / $qps; - $this->fail_on_failed_rpcs_ = $fail_on_failed_rpcs; - $this->rpcs_to_send = explode(',', $rpcs_to_send); - // Convert input in the form of - // rpc1:k1:v1,rpc2:k2:v2,rpc1:k3:v3 - // into - // [ - // 'rpc1' => [ - // 'k1' => 'v1', - // 'k3' => 'v3', - // ], - // 'rpc2' => [ - // 'k2' => 'v2' - // ], - // ] - $this->metadata_to_send = []; - if ($_all_metadata = explode(',', $metadata_to_send)) { - foreach ($_all_metadata as $one_metadata_pair) { - list($rpc, - $metadata_key, - $metadata_value) = explode(':', $one_metadata_pair); - // initialize in case we haven't seen this rpc before - if (!array_key_exists($rpc, $this->metadata_to_send)) { - $this->metadata_to_send[$rpc] = []; - } - $this->metadata_to_send[$rpc][$metadata_key] - = $metadata_value; - } - } + $this->rpc_config = $rpc_config; + $this->target_seconds_between_rpcs_ = 1.0 / $rpc_config->qps; $this->autoload_path_ = $autoload_path; $this->simple_request = new Grpc\Testing\SimpleRequest(); $this->empty_request = new Grpc\Testing\EmptyMessage(); $this->results = []; - foreach ($this->rpcs_to_send as $rpc) { + foreach (['UnaryCall', 'EmptyCall'] as $rpc) { $this->results[$rpc] = []; } + $this->outstanding_rpcs = []; + foreach (['UNARY_CALL', 'EMPTY_CALL'] as $rpc_stats_key) { + $this->num_rpcs_started_by_method[$rpc_stats_key] = 0; + $this->num_rpcs_succeeded_by_method[$rpc_stats_key] = 0; + $this->num_rpcs_failed_by_method[$rpc_stats_key] = 0; + $this->accumulated_method_stats[$rpc_stats_key] = [ + 'rpcs_started' => 0, + 'result' => [], + ]; + } } public function sendUnaryCall($stub, $metadata) { + $timeout = $this->rpc_config->timeout_sec ? + $this->rpc_config->timeout_sec * 1e6 : + $this->TIMEOUT_US; return $stub->UnaryCall($this->simple_request, $metadata, - ['timeout' => $this->TIMEOUT_US]); + ['timeout' => $timeout]); } public function sendEmptyCall($stub, $metadata) { + $timeout = $this->rpc_config->timeout_sec ? + $this->rpc_config->timeout_sec * 1e6 : + $this->TIMEOUT_US; return $stub->EmptyCall($this->empty_request, $metadata, - ['timeout' => $this->TIMEOUT_US]); + ['timeout' => $timeout]); + } + + public function add_rpc_result($rpc, $status_code) { + // $rpc here needs to be in the format of 'UnaryCall', 'EmptyCall' + if (!isset($this->accumulated_method_stats[$this->RPC_MAP[$rpc]] + ['result'][$status_code])) { + $this->accumulated_method_stats[$this->RPC_MAP[$rpc]] + ['result'][$status_code] = 0; + } + $this->accumulated_method_stats[$this->RPC_MAP[$rpc]] + ['result'][$status_code] += 1; + } + + public function check_child_process_result() { + if (sizeof($this->outstanding_rpcs) > 0 && + $this->rpc_config->tmp_file2) { + $keys_to_delete = []; + // tmp_file2 contains the RPC result of each RPC we + // originally wrote to tmp_file1 + $f2 = fopen($this->rpc_config->tmp_file2, 'r+'); + flock($f2, LOCK_EX); + while (true) { + $f2_line = fgets($f2); + if (!$f2_line) { + break; + } + // format here needs to be in sync with + // src/php/bin/xds_manager.py + $parts = explode(',', trim($f2_line)); + $key = $parts[0]; + $returncode = $parts[1]; + if (isset($this->outstanding_rpcs[$key])) { + $parts2 = explode('|', $key); + $result_num = $parts2[0]; + $rpc_name = $parts2[1]; + // Child processes can only communicate back the + // status code for now. + // Current interop test specs only call for + // reporting back the status code in these scenarios. + // If we ever need the hostname reported back from + // child processes, we need to enhance this + // communication framework through tmp files. + $this->results[$rpc_name][$result_num] = ""; + if ($returncode) { + $this->num_rpcs_failed_by_method + [$this->RPC_MAP[$rpc_name]] += 1; + } else { + $this->num_rpcs_succeeded_by_method + [$this->RPC_MAP[$rpc_name]] += 1; + } + $this->add_rpc_result($rpc_name, $returncode); + $keys_to_delete[] = $key; + } + } + foreach ($keys_to_delete as $key) { + unset($this->outstanding_rpcs[$key]); + } + ftruncate($f2, 0); + flock($f2, LOCK_UN); + fclose($f2); + } + } + + public function execute_rpc_in_child_process($rpc, $metadata_serialized) { + // tmp_file1 contains the list of RPCs (and their + // specs) we want executed. This will be picked up + // by src/php/bin/xds_manager.py + $f1 = fopen($this->rpc_config->tmp_file1, 'a'); + $key = implode('|', [$this->num_results, + $rpc, + $metadata_serialized, + $this->rpc_config->timeout_sec]); + flock($f1, LOCK_EX); + fwrite($f1, $key."\n"); + fflush($f1); + flock($f1, LOCK_UN); + fclose($f1); + $this->outstanding_rpcs[$key] = 1; + $this->num_rpcs_started_by_method[$this->RPC_MAP[$rpc]] += 1; + $this->accumulated_method_stats[$this->RPC_MAP[$rpc]] + ['rpcs_started'] += 1; } public function run() { @@ -180,10 +367,11 @@ class ClientThread extends Thread { // Hence we need to do this. require_once($this->autoload_path_); - $stub = new Grpc\Testing\TestServiceClient($this->server_address_, [ - 'credentials' => Grpc\ChannelCredentials::createInsecure() + $stub = new Grpc\Testing\TestServiceClient( + $this->rpc_config->server_address, + ['credentials' => Grpc\ChannelCredentials::createInsecure() ]); - # hrtime returns nanoseconds + // hrtime returns nanoseconds $target_next_start_us = hrtime(true) / 1000; while (true) { $now_us = hrtime(true) / 1000; @@ -191,27 +379,36 @@ class ClientThread extends Thread { if ($sleep_us < 0) { $target_next_start_us = $now_us + ($this->target_seconds_between_rpcs_ * 1e6); - echo sprintf( - "php xds: warning, rpc takes too long to finish. " - . "Deficit %.1fms." - . "If you consistently see this, the qps is too high.\n", - round(abs($sleep_us / 1000), 1)); } else { $target_next_start_us += ($this->target_seconds_between_rpcs_ * 1e6); usleep($sleep_us); } - foreach ($this->rpcs_to_send as $rpc) { - $metadata = array_key_exists( - $rpc, $this->metadata_to_send) ? - $this->metadata_to_send[$rpc] : []; + $this->check_child_process_result(); + foreach ($this->rpc_config->rpcs_to_send as $rpc) { + $metadata_to_send_arr + = (array)$this->rpc_config->metadata_to_send; + $metadata = array_key_exists($rpc, $metadata_to_send_arr) ? + $metadata_to_send_arr[$rpc] : []; // This copy is somehow necessary because // $this->metadata_to_send[$rpc] somehow becomes a // Volatile object, instead of an associative array. $metadata_array = []; + $execute_in_child_process = false; foreach ($metadata as $key => $value) { $metadata_array[$key] = [$value]; + if ($key == 'rpc-behavior' || $key == 'fi_testcase') { + $execute_in_child_process = true; + } } + if ($execute_in_child_process && $this->rpc_config->tmp_file1) { + // if 'rpc-behavior' is set, we need to pawn off + // the execution to some other child PHP processes + $this->execute_rpc_in_child_process( + $rpc, serialize($metadata_array)); + continue; + } + // Execute RPC within this script $call = null; if ($rpc == 'UnaryCall') { $call = $this->sendUnaryCall($stub, $metadata_array); @@ -220,19 +417,29 @@ class ClientThread extends Thread { } else { throw new Exception("Unhandled rpc $rpc"); } + $this->num_rpcs_started_by_method[$this->RPC_MAP[$rpc]] += 1; + $this->accumulated_method_stats[$this->RPC_MAP[$rpc]] + ['rpcs_started'] += 1; // the remote peer is being returned as part of the // initial metadata, according to the test spec $initial_metadata = $call->getMetadata(); list($response, $status) = $call->wait(); if ($status->code == Grpc\STATUS_OK && array_key_exists('hostname', $initial_metadata)) { - $this->results[$rpc][] = $initial_metadata['hostname'][0]; + $this->results[$rpc][$this->num_results] + = $initial_metadata['hostname'][0]; + $this->num_rpcs_succeeded_by_method + [$this->RPC_MAP[$rpc]] += 1; + $this->add_rpc_result($rpc, 0); } else { - if ($this->fail_on_failed_rpcs_) { + if ($this->rpc_config->fail_on_failed_rpcs_) { throw new Exception("$rpc failed with status " . $status->code); } - $this->results[$rpc][] = ""; + $this->results[$rpc][$this->num_results] = ""; + $this->num_rpcs_failed_by_method + [$this->RPC_MAP[$rpc]] += 1; + $this->add_rpc_result($rpc, $status->code); } } // $num_results here is only incremented when the group of @@ -250,18 +457,58 @@ class ClientThread extends Thread { // Note: num_channels are currently ignored for now $args = getopt('', ['fail_on_failed_rpcs:', 'num_channels:', - 'rpc:', 'metadata:', + 'rpc:', 'metadata:', 'tmp_file1:', 'tmp_file2:', 'server:', 'stats_port:', 'qps:']); -$client_thread = new ClientThread($args['server'], $args['qps'], - $args['fail_on_failed_rpcs'], - (empty($args['rpc']) ? 'UnaryCall' - : $args['rpc']), - $args['metadata'], +// Convert input in the form of +// rpc1:k1:v1,rpc2:k2:v2,rpc1:k3:v3 +// into +// [ +// 'rpc1' => [ +// 'k1' => 'v1', +// 'k3' => 'v3', +// ], +// 'rpc2' => [ +// 'k2' => 'v2' +// ], +// ] +$metadata_to_send = []; +if ($_all_metadata = explode(',', $args['metadata'])) { + foreach ($_all_metadata as $one_metadata_pair) { + list($rpc, + $metadata_key, + $metadata_value) = explode(':', $one_metadata_pair); + // initialize in case we haven't seen this rpc before + if (!array_key_exists($rpc, $metadata_to_send)) { + $metadata_to_send[$rpc] = []; + } + $metadata_to_send[$rpc][$metadata_key] = $metadata_value; + } +} +$rpcs_to_send = (empty($args['rpc']) ? 'UnaryCall' : $args['rpc']); + +// Need to communicate the xds server name to the async runner manager +if ($args['tmp_file1']) { + $f1 = fopen($args['tmp_file1'], 'w'); + fwrite($f1, 'server_address,'.$args['server']); + fclose($f1); +} + +$rpc_config = new RpcConfig($args['server'], + $args['qps'], + $args['fail_on_failed_rpcs'], + explode(',', $rpcs_to_send), + $metadata_to_send, + $args['tmp_file1'], + $args['tmp_file2']); + + +$client_thread = new ClientThread($rpc_config, $autoload_path); $client_thread->start(); $server = new Grpc\RpcServer(); $server->addHttp2Port('0.0.0.0:'.$args['stats_port']); $server->handle(new LoadBalancerStatsService()); +$server->handle(new XdsUpdateClientConfigureService()); $server->run(); diff --git a/src/php/tests/interop/xds_empty_call.php b/src/php/tests/interop/xds_empty_call.php new file mode 100644 index 00000000000..e975d67fb77 --- /dev/null +++ b/src/php/tests/interop/xds_empty_call.php @@ -0,0 +1,54 @@ + Grpc\ChannelCredentials::createInsecure() +]); + +$empty_request = new Grpc\Testing\EmptyMessage(); + +$timeout = $args['timeout_sec'] ? $args['timeout_sec'] * 1e6 : $TIMEOUT_US; +$metadata = []; +if ($args['metadata']) { + $metadata = unserialize($args['metadata']); +} + +$call = $stub->EmptyCall($empty_request, + $metadata, + ['timeout' => $timeout]); +list($response, $status) = $call->wait(); +exit($status->code); diff --git a/src/php/tests/interop/xds_unary_call.php b/src/php/tests/interop/xds_unary_call.php new file mode 100644 index 00000000000..8997e0b9b36 --- /dev/null +++ b/src/php/tests/interop/xds_unary_call.php @@ -0,0 +1,54 @@ + Grpc\ChannelCredentials::createInsecure() +]); + +$simple_request = new Grpc\Testing\SimpleRequest(); + +$timeout = $args['timeout_sec'] ? $args['timeout_sec'] * 1e6 : $TIMEOUT_US; +$metadata = []; +if ($args['metadata']) { + $metadata = unserialize($args['metadata']); +} + +$call = $stub->UnaryCall($simple_request, + $metadata, + ['timeout' => $timeout]); +list($response, $status) = $call->wait(); +exit($status->code); diff --git a/src/php/tests/unit_tests/ChannelCredentialsTest.php b/src/php/tests/unit_tests/ChannelCredentialsTest.php index a10b5b81ef1..ed61f3e3a43 100644 --- a/src/php/tests/unit_tests/ChannelCredentialsTest.php +++ b/src/php/tests/unit_tests/ChannelCredentialsTest.php @@ -43,7 +43,7 @@ class ChanellCredentialsTest extends \PHPUnit\Framework\TestCase public function testCreateInsecure() { $channel_credentials = Grpc\ChannelCredentials::createInsecure(); - $this->assertNotNull($channel_credentials); + $this->assertNull($channel_credentials); } public function testDefaultRootsPem() diff --git a/src/php/tests/unit_tests/ChannelTest.php b/src/php/tests/unit_tests/ChannelTest.php index a9341060d0e..b7df853bb2d 100644 --- a/src/php/tests/unit_tests/ChannelTest.php +++ b/src/php/tests/unit_tests/ChannelTest.php @@ -52,7 +52,7 @@ class ChannelTest extends \PHPUnit\Framework\TestCase $this->assertNotNull($xdsCreds); } - public function testCreateXdsWithInsecure() { + public function disabled_testCreateXdsWithInsecure() { $xdsCreds = \Grpc\ChannelCredentials::createXds( \Grpc\ChannelCredentials::createInsecure() ); @@ -64,9 +64,21 @@ class ChannelTest extends \PHPUnit\Framework\TestCase $xdsCreds = \Grpc\ChannelCredentials::createXds(null); } - public function testCreateXdsWithInvalidType() { - $this->expectException(\TypeError::class); - $xdsCreds = \Grpc\ChannelCredentials::createXds("invalid-type"); + public function testCreateXdsWithInvalidType() + { + $expected = $this->logicalOr( + // PHP8 + new \PHPUnit\Framework\Constraint\Exception(\InvalidArgumentException::class), + // PHP7 + new \PHPUnit\Framework\Constraint\Exception(\TypeError::class) + ); + try { + $xdsCreds = \Grpc\ChannelCredentials::createXds("invalid-type"); + } catch (\Throwable $exception) { + $this->assertThat($exception, $expected); + return; + } + $this->assertThat(null, $expected); } public function testGetConnectivityState() @@ -353,6 +365,7 @@ class ChannelTest extends \PHPUnit\Framework\TestCase ), 50306, ], + /* [ \Grpc\ChannelCredentials::createXds( \Grpc\ChannelCredentials::createInSecure() @@ -362,6 +375,7 @@ class ChannelTest extends \PHPUnit\Framework\TestCase ), 50307, ], + */ ]; } @@ -424,6 +438,7 @@ class ChannelTest extends \PHPUnit\Framework\TestCase ), 50353, ], + /* [ \Grpc\ChannelCredentials::createXds( \Grpc\ChannelCredentials::createSsl() @@ -440,6 +455,7 @@ class ChannelTest extends \PHPUnit\Framework\TestCase ), 50355, ], + */ [ \Grpc\ChannelCredentials::createSsl(), \Grpc\ChannelCredentials::createXds( diff --git a/src/php/tests/unit_tests/RpcServerTest.php b/src/php/tests/unit_tests/RpcServerTest.php new file mode 100644 index 00000000000..26e884af8d2 --- /dev/null +++ b/src/php/tests/unit_tests/RpcServerTest.php @@ -0,0 +1,85 @@ +server = new \Grpc\RpcServer(); + $this->mockService = $this->getMockBuilder(stdClass::class) + ->setMethods(['getMethodDescriptors', 'hello']) + ->getMock(); + } + + public function testHandleServices() + { + $helloMethodDescriptor = new \Grpc\MethodDescriptor( + $this->mockService, + 'hello', + 'String', + \Grpc\MethodDescriptor::UNARY_CALL + ); + $this->mockService->expects($this->once()) + ->method('getMethodDescriptors') + ->with() + ->will($this->returnValue([ + '/test/hello' => $helloMethodDescriptor + ])); + + $pathMap = $this->server->handle($this->mockService); + $this->assertEquals($pathMap, [ + '/test/hello' => $helloMethodDescriptor + ]); + + $mockService2 = $this->getMockBuilder(stdClass::class) + ->setMethods(['getMethodDescriptors', 'hello', 'bye']) + ->getMock(); + $helloMethodDescriptor2 = new \Grpc\MethodDescriptor( + $this->mockService, + 'hello', + 'Number', + \Grpc\MethodDescriptor::UNARY_CALL + ); + $byeMethodDescritor = new \Grpc\MethodDescriptor( + $this->mockService, + 'bye', + 'String', + \Grpc\MethodDescriptor::UNARY_CALL + ); + $mockService2->expects($this->once()) + ->method('getMethodDescriptors') + ->with() + ->will($this->returnValue([ + '/test/hello' => $helloMethodDescriptor2, + '/test/bye' => $byeMethodDescritor + ])); + + $pathMap = $this->server->handle($mockService2); + $this->assertEquals($pathMap, [ + '/test/hello' => $helloMethodDescriptor2, + '/test/bye' => $byeMethodDescritor + ]); + } +} diff --git a/src/php/tests/unit_tests/ServerCallTest.php b/src/php/tests/unit_tests/ServerCallTest.php index 8090c1c70c9..e6b474ee90d 100644 --- a/src/php/tests/unit_tests/ServerCallTest.php +++ b/src/php/tests/unit_tests/ServerCallTest.php @@ -20,16 +20,7 @@ require_once(dirname(__FILE__) . '/../../lib/Grpc/ServerCallReader.php'); require_once(dirname(__FILE__) . '/../../lib/Grpc/ServerCallWriter.php'); require_once(dirname(__FILE__) . '/../../lib/Grpc/Status.php'); - -// load protobuf from third_party -set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/../../../../third_party/protobuf/php/src/'); - -spl_autoload_register(function ($className) { -$classPath = str_replace('\\', DIRECTORY_SEPARATOR, $className); -if (strpos($classPath, 'Google/Protobuf') === 0 || strpos($classPath, 'GPBMetadata/Google/Protobuf') === 0) { -require_once($classPath . '.php'); -} -}); +require_once(dirname(__FILE__) . '/../../lib/Grpc/ServerContext.php'); class StartBatchEvent { @@ -40,6 +31,31 @@ class StartBatchEvent public $message; } +class StringValue +{ + public function setValue(string $value) + { + $this->value = $value; + } + + public function getValue(): string + { + return $this->value; + } + + public function serializeToString(): string + { + return $this->value; + } + + public function mergeFromString(string $value) + { + $this->value = $value; + } + + private $value = ''; +} + class ServerCallTest extends \PHPUnit\Framework\TestCase { public function setUp(): void @@ -47,11 +63,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase $this->mockCall = $this->getMockBuilder(stdClass::class) ->setMethods(['startBatch']) ->getMock(); + $this->serverContext = new \Grpc\ServerContext($this->mockCall); } public function newStringMessage(string $value = 'a string') { - $message = new \Google\Protobuf\StringValue(); + $message = new StringValue(); $message->setValue($value); return $message; } @@ -68,7 +85,7 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase $serverCallReader = new \Grpc\ServerCallReader( $this->mockCall, - '\Google\Protobuf\StringValue' + '\StringValue' ); $return = $serverCallReader->read(); $this->assertEquals($message, $return); @@ -82,8 +99,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase \Grpc\OP_SEND_INITIAL_METADATA => [], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->start([]); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setInitialMetadata([]); + $serverCallWriter->start(); } public function testStartWithMetadata() @@ -96,8 +117,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase \Grpc\OP_SEND_INITIAL_METADATA => $metadata, ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->start($metadata); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setInitialMetadata($metadata); + $serverCallWriter->start(); return $serverCallWriter; } @@ -113,8 +138,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase \Grpc\OP_SEND_MESSAGE => ['message' => $message->serializeToString()], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->start($metadata, $message); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setInitialMetadata($metadata); + $serverCallWriter->start($message); } public function testWriteStartWithMessageAndOptions() @@ -132,8 +161,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase ], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->start($metadata, $message, ['flags' => 0x02]); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setInitialMetadata($metadata); + $serverCallWriter->start($message, ['flags' => 0x02]); } public function testWriteDataOnly() @@ -147,7 +180,10 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase \Grpc\OP_SEND_MESSAGE => ['message' => $message->serializeToString()], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); $serverCallWriter->write($message); } @@ -165,7 +201,10 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase ], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); $serverCallWriter->write($message, ['flags' => 0x02]); } @@ -181,8 +220,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase \Grpc\OP_SEND_MESSAGE => ['message' => $message->serializeToString()], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->write($message, [], $metadata); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setInitialMetadata($metadata); + $serverCallWriter->write($message, []); } public function testFinish() @@ -201,8 +244,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase \Grpc\OP_SEND_INITIAL_METADATA => [], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->finish($status); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setStatus($status); + $serverCallWriter->finish(); } public function testFinishWithMetadataAndMessage() @@ -223,8 +270,13 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase ], ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->finish($status, $metadata, $message, ['flags' => 0x02]); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setInitialMetadata($metadata); + $this->serverContext->setStatus($status); + $serverCallWriter->finish($message, ['flags' => 0x02]); } public function testStartWriteFinish() @@ -259,8 +311,12 @@ class ServerCallTest extends \PHPUnit\Framework\TestCase \Grpc\OP_RECV_CLOSE_ON_SERVER => true, ])); - $serverCallWriter = new \Grpc\ServerCallWriter($this->mockCall); - $serverCallWriter->start($metadata); + $serverCallWriter = new \Grpc\ServerCallWriter( + $this->mockCall, + $this->serverContext + ); + $this->serverContext->setInitialMetadata($metadata); + $serverCallWriter->start(); $serverCallWriter->write($message1, [], $metadata2 /* should not send */); $serverCallWriter->write($message2, ['flags' => 0x02]); $serverCallWriter->finish(); diff --git a/src/proto/grpc/testing/xds/v3/BUILD b/src/proto/grpc/testing/xds/v3/BUILD index 024cd63d786..be730deaba1 100644 --- a/src/proto/grpc/testing/xds/v3/BUILD +++ b/src/proto/grpc/testing/xds/v3/BUILD @@ -15,6 +15,7 @@ licenses(["notice"]) # Apache v2 load("//bazel:grpc_build_system.bzl", "grpc_package", "grpc_proto_library") +load("//bazel:python_rules.bzl", "py_grpc_library", "py_proto_library") grpc_package( name = "xds_v3", @@ -26,6 +27,7 @@ grpc_proto_library( srcs = [ "address.proto", ], + well_known_protos = True, ) grpc_proto_library( @@ -223,6 +225,17 @@ grpc_proto_library( ], ) +grpc_proto_library( + name = "fault_common_proto", + srcs = [ + "fault_common.proto", + ], + well_known_protos = True, + deps = [ + "percent_proto", + ], +) + grpc_proto_library( name = "tls_proto", srcs = [ @@ -233,3 +246,62 @@ grpc_proto_library( "string_proto", ], ) + +grpc_proto_library( + name = "config_dump_proto", + srcs = [ + "config_dump.proto", + ], + well_known_protos = True, +) + +grpc_proto_library( + name = "csds_proto", + srcs = [ + "csds.proto", + ], + well_known_protos = True, + deps = [ + "base_proto", + "config_dump_proto", + ], +) + +grpc_proto_library( + name = "fault_proto", + srcs = [ + "fault.proto", + ], + well_known_protos = True, + deps = [ + "fault_common_proto", + "percent_proto", + "route_proto", + ], +) + +py_proto_library( + name = "csds_py_pb2", + deps = [":_csds_proto_only"], +) + +py_grpc_library( + name = "csds_py_pb2_grpc", + srcs = [":_csds_proto_only"], + deps = [":csds_py_pb2"], +) + +py_proto_library( + name = "config_dump_py_pb2", + deps = [":_config_dump_proto_only"], +) + +py_proto_library( + name = "base_py_pb2", + deps = [":_base_proto_only"], +) + +py_proto_library( + name = "percent_py_pb2", + deps = [":_percent_proto_only"], +) diff --git a/src/proto/grpc/testing/xds/v3/address.proto b/src/proto/grpc/testing/xds/v3/address.proto index abea8bf68a6..38592ccfda9 100644 --- a/src/proto/grpc/testing/xds/v3/address.proto +++ b/src/proto/grpc/testing/xds/v3/address.proto @@ -18,6 +18,8 @@ syntax = "proto3"; package envoy.config.core.v3; +import "google/protobuf/wrappers.proto"; + // [#protodoc-title: Network addresses] // [#next-free-field: 7] @@ -48,3 +50,13 @@ message Address { SocketAddress socket_address = 1; } } + +// CidrRange specifies an IP Address and a prefix length to construct +// the subnet mask for a `CIDR `_ range. +message CidrRange { + // IPv4 or IPv6 address, e.g. ``192.0.0.0`` or ``2001:db8::``. + string address_prefix = 1; + + // Length of prefix, e.g. 0, 32. + google.protobuf.UInt32Value prefix_len = 2; +} diff --git a/src/proto/grpc/testing/xds/v3/config_dump.proto b/src/proto/grpc/testing/xds/v3/config_dump.proto new file mode 100644 index 00000000000..d69b3109aac --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/config_dump.proto @@ -0,0 +1,284 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package envoy.admin.v3; + +import "google/protobuf/any.proto"; +import "google/protobuf/timestamp.proto"; + +// Resource status from the view of a xDS client, which tells the synchronization +// status between the xDS client and the xDS server. +enum ClientResourceStatus { + // Resource status is not available/unknown. + UNKNOWN = 0; + + // Client requested this resource but hasn't received any update from management + // server. The client will not fail requests, but will queue them until update + // arrives or the client times out waiting for the resource. + REQUESTED = 1; + + // This resource has been requested by the client but has either not been + // delivered by the server or was previously delivered by the server and then + // subsequently removed from resources provided by the server. For more + // information, please refer to the :ref:`"Knowing When a Requested Resource + // Does Not Exist" ` section. + DOES_NOT_EXIST = 2; + + // Client received this resource and replied with ACK. + ACKED = 3; + + // Client received this resource and replied with NACK. + NACKED = 4; +} + +message UpdateFailureState { + // What the component configuration would have been if the update had succeeded. + // This field may not be populated by xDS clients due to storage overhead. + google.protobuf.Any failed_configuration = 1; + + // Time of the latest failed update attempt. + google.protobuf.Timestamp last_update_attempt = 2; + + // Details about the last failed update attempt. + string details = 3; + + // This is the version of the rejected resource. + // [#not-implemented-hide:] + string version_info = 4; +} + +// Envoy's listener manager fills this message with all currently known listeners. Listener +// configuration information can be used to recreate an Envoy configuration by populating all +// listeners as static listeners or by returning them in a LDS response. +message ListenersConfigDump { + // Describes a statically loaded listener. + message StaticListener { + // The listener config. + google.protobuf.Any listener = 1; + + // The timestamp when the Listener was last successfully updated. + google.protobuf.Timestamp last_updated = 2; + } + + message DynamicListenerState { + // This is the per-resource version information. This version is currently taken from the + // :ref:`version_info ` field at the time + // that the listener was loaded. In the future, discrete per-listener versions may be supported + // by the API. + string version_info = 1; + + // The listener config. + google.protobuf.Any listener = 2; + + // The timestamp when the Listener was last successfully updated. + google.protobuf.Timestamp last_updated = 3; + } + + // Describes a dynamically loaded listener via the LDS API. + // [#next-free-field: 7] + message DynamicListener { + // The name or unique id of this listener, pulled from the DynamicListenerState config. + string name = 1; + + // The listener state for any active listener by this name. + // These are listeners that are available to service data plane traffic. + DynamicListenerState active_state = 2; + + // The listener state for any warming listener by this name. + // These are listeners that are currently undergoing warming in preparation to service data + // plane traffic. Note that if attempting to recreate an Envoy configuration from a + // configuration dump, the warming listeners should generally be discarded. + DynamicListenerState warming_state = 3; + + // The listener state for any draining listener by this name. + // These are listeners that are currently undergoing draining in preparation to stop servicing + // data plane traffic. Note that if attempting to recreate an Envoy configuration from a + // configuration dump, the draining listeners should generally be discarded. + DynamicListenerState draining_state = 4; + + // Set if the last update failed, cleared after the next successful update. + // The *error_state* field contains the rejected version of this particular + // resource along with the reason and timestamp. For successfully updated or + // acknowledged resource, this field should be empty. + UpdateFailureState error_state = 5; + + // The client status of this resource. + // [#not-implemented-hide:] + ClientResourceStatus client_status = 6; + } + + // This is the :ref:`version_info ` in the + // last processed LDS discovery response. If there are only static bootstrap listeners, this field + // will be "". + string version_info = 1; + + // The statically loaded listener configs. + repeated StaticListener static_listeners = 2; + + // State for any warming, active, or draining listeners. + repeated DynamicListener dynamic_listeners = 3; +} + +// Envoy's cluster manager fills this message with all currently known clusters. Cluster +// configuration information can be used to recreate an Envoy configuration by populating all +// clusters as static clusters or by returning them in a CDS response. +message ClustersConfigDump { + // Describes a statically loaded cluster. + message StaticCluster { + // The cluster config. + google.protobuf.Any cluster = 1; + + // The timestamp when the Cluster was last updated. + google.protobuf.Timestamp last_updated = 2; + } + + // Describes a dynamically loaded cluster via the CDS API. + // [#next-free-field: 6] + message DynamicCluster { + // This is the per-resource version information. This version is currently taken from the + // :ref:`version_info ` field at the time + // that the cluster was loaded. In the future, discrete per-cluster versions may be supported by + // the API. + string version_info = 1; + + // The cluster config. + google.protobuf.Any cluster = 2; + + // The timestamp when the Cluster was last updated. + google.protobuf.Timestamp last_updated = 3; + + // Set if the last update failed, cleared after the next successful update. + // The *error_state* field contains the rejected version of this particular + // resource along with the reason and timestamp. For successfully updated or + // acknowledged resource, this field should be empty. + // [#not-implemented-hide:] + UpdateFailureState error_state = 4; + + // The client status of this resource. + // [#not-implemented-hide:] + ClientResourceStatus client_status = 5; + } + + // This is the :ref:`version_info ` in the + // last processed CDS discovery response. If there are only static bootstrap clusters, this field + // will be "". + string version_info = 1; + + // The statically loaded cluster configs. + repeated StaticCluster static_clusters = 2; + + // The dynamically loaded active clusters. These are clusters that are available to service + // data plane traffic. + repeated DynamicCluster dynamic_active_clusters = 3; + + // The dynamically loaded warming clusters. These are clusters that are currently undergoing + // warming in preparation to service data plane traffic. Note that if attempting to recreate an + // Envoy configuration from a configuration dump, the warming clusters should generally be + // discarded. + repeated DynamicCluster dynamic_warming_clusters = 4; +} + +// Envoy's RDS implementation fills this message with all currently loaded routes, as described by +// their RouteConfiguration objects. Static routes that are either defined in the bootstrap configuration +// or defined inline while configuring listeners are separated from those configured dynamically via RDS. +// Route configuration information can be used to recreate an Envoy configuration by populating all routes +// as static routes or by returning them in RDS responses. +message RoutesConfigDump { + message StaticRouteConfig { + // The route config. + google.protobuf.Any route_config = 1; + + // The timestamp when the Route was last updated. + google.protobuf.Timestamp last_updated = 2; + } + + // [#next-free-field: 6] + message DynamicRouteConfig { + // This is the per-resource version information. This version is currently taken from the + // :ref:`version_info ` field at the time that + // the route configuration was loaded. + string version_info = 1; + + // The route config. + google.protobuf.Any route_config = 2; + + // The timestamp when the Route was last updated. + google.protobuf.Timestamp last_updated = 3; + + // Set if the last update failed, cleared after the next successful update. + // The *error_state* field contains the rejected version of this particular + // resource along with the reason and timestamp. For successfully updated or + // acknowledged resource, this field should be empty. + // [#not-implemented-hide:] + UpdateFailureState error_state = 4; + + // The client status of this resource. + // [#not-implemented-hide:] + ClientResourceStatus client_status = 5; + } + + // The statically loaded route configs. + repeated StaticRouteConfig static_route_configs = 2; + + // The dynamically loaded route configs. + repeated DynamicRouteConfig dynamic_route_configs = 3; +} + +// Envoy's admin fill this message with all currently known endpoints. Endpoint +// configuration information can be used to recreate an Envoy configuration by populating all +// endpoints as static endpoints or by returning them in an EDS response. +message EndpointsConfigDump { + message StaticEndpointConfig { + // The endpoint config. + google.protobuf.Any endpoint_config = 1; + + // [#not-implemented-hide:] The timestamp when the Endpoint was last updated. + google.protobuf.Timestamp last_updated = 2; + } + + // [#next-free-field: 6] + message DynamicEndpointConfig { + // [#not-implemented-hide:] This is the per-resource version information. This version is currently taken from the + // :ref:`version_info ` field at the time that + // the endpoint configuration was loaded. + string version_info = 1; + + // The endpoint config. + google.protobuf.Any endpoint_config = 2; + + // [#not-implemented-hide:] The timestamp when the Endpoint was last updated. + google.protobuf.Timestamp last_updated = 3; + + // Set if the last update failed, cleared after the next successful update. + // The *error_state* field contains the rejected version of this particular + // resource along with the reason and timestamp. For successfully updated or + // acknowledged resource, this field should be empty. + // [#not-implemented-hide:] + UpdateFailureState error_state = 4; + + // The client status of this resource. + // [#not-implemented-hide:] + ClientResourceStatus client_status = 5; + } + + // The statically loaded endpoint configs. + repeated StaticEndpointConfig static_endpoint_configs = 2; + + // The dynamically loaded endpoint configs. + repeated DynamicEndpointConfig dynamic_endpoint_configs = 3; +} diff --git a/src/proto/grpc/testing/xds/v3/csds.proto b/src/proto/grpc/testing/xds/v3/csds.proto new file mode 100644 index 00000000000..bbdfd4e048b --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/csds.proto @@ -0,0 +1,89 @@ +// Copyright 2021 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package envoy.service.status.v3; + +import "src/proto/grpc/testing/xds/v3/config_dump.proto"; +import "src/proto/grpc/testing/xds/v3/base.proto"; + + +// CSDS is Client Status Discovery Service. It can be used to get the status of +// an xDS-compliant client from the management server's point of view. It can +// also be used to get the current xDS states directly from the client. +service ClientStatusDiscoveryService { + rpc StreamClientStatus(stream ClientStatusRequest) returns (stream ClientStatusResponse) {} + rpc FetchClientStatus(ClientStatusRequest) returns (ClientStatusResponse) {} +} + +// Status of a config from a management server view. +enum ConfigStatus { + // Status info is not available/unknown. + UNKNOWN = 0; + + // Management server has sent the config to client and received ACK. + SYNCED = 1; + + // Config is not sent. + NOT_SENT = 2; + + // Management server has sent the config to client but hasn’t received + // ACK/NACK. + STALE = 3; + + // Management server has sent the config to client but received NACK. The + // attached config dump will be the latest config (the rejected one), since + // it is the persisted version in the management server. + ERROR = 4; +} + +// Request for client status of clients identified by a list of NodeMatchers. +message ClientStatusRequest { + // The node making the csds request. + config.core.v3.Node node = 2; +} + +// Detailed config (per xDS) with status. +// [#next-free-field: 8] +message PerXdsConfig { + // Config status generated by management servers. Will not be present if the + // CSDS server is an xDS client. + ConfigStatus status = 1; + + oneof per_xds_config { + admin.v3.ListenersConfigDump listener_config = 2; + + admin.v3.ClustersConfigDump cluster_config = 3; + + admin.v3.RoutesConfigDump route_config = 4; + + admin.v3.EndpointsConfigDump endpoint_config = 6; + } +} + +// All xds configs for a particular client. +message ClientConfig { + // Node for a particular client. + config.core.v3.Node node = 1; + + repeated PerXdsConfig xds_config = 2; +} + +message ClientStatusResponse { + // Client configs for the clients specified in the ClientStatusRequest. + repeated ClientConfig config = 1; +} diff --git a/src/proto/grpc/testing/xds/v3/fault.proto b/src/proto/grpc/testing/xds/v3/fault.proto new file mode 100644 index 00000000000..05ec641d0e0 --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/fault.proto @@ -0,0 +1,91 @@ +// Copyright 2020 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package envoy.extensions.filters.http.fault.v3; + +import "src/proto/grpc/testing/xds/v3/fault_common.proto"; +import "src/proto/grpc/testing/xds/v3/route.proto"; +import "src/proto/grpc/testing/xds/v3/percent.proto"; + +import "google/protobuf/wrappers.proto"; + +// [#protodoc-title: Fault Injection] +// Fault Injection :ref:`configuration overview `. +// [#extension: envoy.filters.http.fault] + +// [#next-free-field: 6] +message FaultAbort { + // Fault aborts are controlled via an HTTP header (if applicable). See the + // :ref:`HTTP fault filter ` documentation for + // more information. + message HeaderAbort { + } + + reserved 1; + + oneof error_type { + // HTTP status code to use to abort the HTTP request. + uint32 http_status = 2; + + // gRPC status code to use to abort the gRPC request. + uint32 grpc_status = 5; + + // Fault aborts are controlled via an HTTP header (if applicable). + HeaderAbort header_abort = 4; + } + + // The percentage of requests/operations/connections that will be aborted with the error code + // provided. + type.v3.FractionalPercent percentage = 3; +} + +// [#next-free-field: 15] +message HTTPFault { + // If specified, the filter will inject delays based on the values in the + // object. + common.fault.v3.FaultDelay delay = 1; + + // If specified, the filter will abort requests based on the values in + // the object. At least *abort* or *delay* must be specified. + FaultAbort abort = 2; + + // Specifies a set of headers that the filter should match on. The fault + // injection filter can be applied selectively to requests that match a set of + // headers specified in the fault filter config. The chances of actual fault + // injection further depend on the value of the :ref:`percentage + // ` field. + // The filter will check the request's headers against all the specified + // headers in the filter config. A match will happen if all the headers in the + // config are present in the request with the same values (or based on + // presence if the *value* field is not in the config). + repeated config.route.v3.HeaderMatcher headers = 4; + + // The maximum number of faults that can be active at a single time via the configured fault + // filter. Note that because this setting can be overridden at the route level, it's possible + // for the number of active faults to be greater than this value (if injected via a different + // route). If not specified, defaults to unlimited. This setting can be overridden via + // `runtime ` and any faults that are not injected + // due to overflow will be indicated via the `faults_overflow + // ` stat. + // + // .. attention:: + // Like other :ref:`circuit breakers ` in Envoy, this is a fuzzy + // limit. It's possible for the number of active faults to rise slightly above the configured + // amount due to the implementation details. + google.protobuf.UInt32Value max_active_faults = 6; +} diff --git a/src/proto/grpc/testing/xds/v3/fault_common.proto b/src/proto/grpc/testing/xds/v3/fault_common.proto new file mode 100644 index 00000000000..2c2aedc7896 --- /dev/null +++ b/src/proto/grpc/testing/xds/v3/fault_common.proto @@ -0,0 +1,49 @@ +// Copyright 2020 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Local copy of Envoy xDS proto file, used for testing only. + +syntax = "proto3"; + +package envoy.extensions.filters.common.fault.v3; + +import "src/proto/grpc/testing/xds/v3/percent.proto"; + +import "google/protobuf/duration.proto"; + +// Delay specification is used to inject latency into the +// HTTP/gRPC/Mongo/Redis operation or delay proxying of TCP connections. +message FaultDelay { + // Fault delays are controlled via an HTTP header (if applicable). See the + // :ref:`HTTP fault filter ` + // documentation for more information. + message HeaderDelay {} + + oneof fault_delay_secifier { + // Add a fixed delay before forwarding the operation upstream. See + // https://developers.google.com/protocol-buffers/docs/proto3#json for + // the JSON/YAML Duration mapping. For HTTP/Mongo/Redis, the specified + // delay will be injected before a new request/operation. For TCP + // connections, the proxying of the connection upstream will be delayed + // for the specified period. This is required if type is FIXED. + google.protobuf.Duration fixed_delay = 3; + + // Fault delays are controlled via an HTTP header (if applicable). + HeaderDelay header_delay = 5; + } + + // The percentage of operations/connections/requests on which the delay will + // be injected. + type.v3.FractionalPercent percentage = 4; +} diff --git a/src/proto/grpc/testing/xds/v3/listener.proto b/src/proto/grpc/testing/xds/v3/listener.proto index 40ce59cbe09..df9ee71e725 100644 --- a/src/proto/grpc/testing/xds/v3/listener.proto +++ b/src/proto/grpc/testing/xds/v3/listener.proto @@ -22,6 +22,7 @@ import "src/proto/grpc/testing/xds/v3/address.proto"; import "src/proto/grpc/testing/xds/v3/base.proto"; import "google/protobuf/any.proto"; +import "google/protobuf/wrappers.proto"; // [#protodoc-title: Listener configuration] // Listener :ref:`configuration overview ` @@ -40,7 +41,83 @@ message ApiListener { google.protobuf.Any api_listener = 1; } +message Filter { + reserved 3; + + // The name of the filter to instantiate. The name must match a + // :ref:`supported filter `. + string name = 1; + + // [#extension-category: envoy.filters.network] + oneof config_type { + // Filter specific configuration which depends on the filter being + // instantiated. See the supported filters for further documentation. + google.protobuf.Any typed_config = 4; + } +} + message FilterChainMatch { + enum ConnectionSourceType { + // Any connection source matches. + ANY = 0; + + // Match a connection originating from the same host. + SAME_IP_OR_LOOPBACK = 1; + + // Match a connection originating from a different host. + EXTERNAL = 2; + } + + reserved 1; + + // Optional destination port to consider when use_original_dst is set on the + // listener in determining a filter chain match. + google.protobuf.UInt32Value destination_port = 8; + + // If non-empty, an IP address and prefix length to match addresses when the + // listener is bound to 0.0.0.0/:: or when use_original_dst is specified. + repeated core.v3.CidrRange prefix_ranges = 3; + + // Specifies the connection source IP match type. Can be any, local or external network. + ConnectionSourceType source_type = 12; + + // The criteria is satisfied if the source IP address of the downstream + // connection is contained in at least one of the specified subnets. If the + // parameter is not specified or the list is empty, the source IP address is + // ignored. + repeated core.v3.CidrRange source_prefix_ranges = 6; + + // The criteria is satisfied if the source port of the downstream connection + // is contained in at least one of the specified ports. If the parameter is + // not specified, the source port is ignored. + repeated uint32 source_ports = 7; + + // If non-empty, a list of server names (e.g. SNI for TLS protocol) to consider when determining + // a filter chain match. Those values will be compared against the server names of a new + // connection, when detected by one of the listener filters. + // + // The server name will be matched against all wildcard domains, i.e. ``www.example.com`` + // will be first matched against ``www.example.com``, then ``*.example.com``, then ``*.com``. + // + // Note that partial wildcards are not supported, and values like ``*w.example.com`` are invalid. + // + // .. attention:: + // + // See the :ref:`FAQ entry ` on how to configure SNI for more + // information. + repeated string server_names = 11; + + // If non-empty, a transport protocol to consider when determining a filter chain match. + // This value will be compared against the transport protocol of a new connection, when + // it's detected by one of the listener filters. + // + // Suggested values include: + // + // * ``raw_buffer`` - default, used when no transport protocol is detected, + // * ``tls`` - set by :ref:`envoy.filters.listener.tls_inspector ` + // when TLS protocol is detected. + string transport_protocol = 9; + // If non-empty, a list of application protocols (e.g. ALPN for TLS protocol) to consider when // determining a filter chain match. Those values will be compared against the application // protocols of a new connection, when detected by one of the listener filters. @@ -70,6 +147,12 @@ message FilterChain { // The criteria to use when matching a connection to this filter chain. FilterChainMatch filter_chain_match = 1; + // A list of individual network filters that make up the filter chain for + // connections established with the listener. Order matters as the filters are + // processed sequentially as connection events happen. Note: If the filter + // list is empty, the connection will close by default. + repeated Filter filters = 3; + // Optional custom transport socket implementation to use for downstream connections. // To setup TLS, set a transport socket with name `tls` and // :ref:`DownstreamTlsContext ` in the `typed_config`. @@ -99,6 +182,17 @@ message Listener { // :ref:`FAQ entry `. repeated FilterChain filter_chains = 3; + // If a connection is redirected using *iptables*, the port on which the proxy + // receives it might be different from the original destination address. When this flag is set to + // true, the listener hands off redirected connections to the listener associated with the + // original destination address. If there is no listener associated with the original destination + // address, the connection is handled by the listener that receives it. Defaults to false. + google.protobuf.BoolValue use_original_dst = 4; + + // The default filter chain if none of the filter chain matches. If no default filter chain is supplied, + // the connection will be closed. The filter chain match is ignored in this field. + FilterChain default_filter_chain = 25; + // Used to represent an API listener, which is used in non-proxy clients. The type of API // exposed to the non-proxy application depends on the type of API listener. // When this field is set, no other field except for :ref:`name` diff --git a/src/python/grpcio/commands.py b/src/python/grpcio/commands.py index f4a3d2bdc04..df8fc46a3ca 100644 --- a/src/python/grpcio/commands.py +++ b/src/python/grpcio/commands.py @@ -258,10 +258,14 @@ class BuildExt(build_ext.build_ext): old_compile = self.compiler._compile def new_compile(obj, src, ext, cc_args, extra_postargs, pp_opts): - if src[-2:] == '.c': + if src.endswith('.c'): extra_postargs = [ arg for arg in extra_postargs if not '-std=c++' in arg ] + elif src.endswith('.cc') or src.endswith('.cpp'): + extra_postargs = [ + arg for arg in extra_postargs if not '-std=gnu99' in arg + ] return old_compile(obj, src, ext, cc_args, extra_postargs, pp_opts) diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py index e1c1e36a392..ea393c44c5e 100644 --- a/src/python/grpcio/grpc/__init__.py +++ b/src/python/grpcio/grpc/__init__.py @@ -406,8 +406,6 @@ class Call(six.with_metaclass(abc.ABCMeta, RpcContext)): class ClientCallDetails(six.with_metaclass(abc.ABCMeta)): """Describes an RPC to be invoked. - This is an EXPERIMENTAL API. - Attributes: method: The method name of the RPC. timeout: An optional duration of time in seconds to allow for the RPC. @@ -422,10 +420,7 @@ class ClientCallDetails(six.with_metaclass(abc.ABCMeta)): class UnaryUnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)): - """Affords intercepting unary-unary invocations. - - This is an EXPERIMENTAL API. - """ + """Affords intercepting unary-unary invocations.""" @abc.abstractmethod def intercept_unary_unary(self, continuation, client_call_details, request): @@ -459,10 +454,7 @@ class UnaryUnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)): class UnaryStreamClientInterceptor(six.with_metaclass(abc.ABCMeta)): - """Affords intercepting unary-stream invocations. - - This is an EXPERIMENTAL API. - """ + """Affords intercepting unary-stream invocations.""" @abc.abstractmethod def intercept_unary_stream(self, continuation, client_call_details, @@ -496,10 +488,7 @@ class UnaryStreamClientInterceptor(six.with_metaclass(abc.ABCMeta)): class StreamUnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)): - """Affords intercepting stream-unary invocations. - - This is an EXPERIMENTAL API. - """ + """Affords intercepting stream-unary invocations.""" @abc.abstractmethod def intercept_stream_unary(self, continuation, client_call_details, @@ -533,10 +522,7 @@ class StreamUnaryClientInterceptor(six.with_metaclass(abc.ABCMeta)): class StreamStreamClientInterceptor(six.with_metaclass(abc.ABCMeta)): - """Affords intercepting stream-stream invocations. - - This is an EXPERIMENTAL API. - """ + """Affords intercepting stream-stream invocations.""" @abc.abstractmethod def intercept_stream_stream(self, continuation, client_call_details, @@ -1188,6 +1174,16 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """ raise NotImplementedError() + def trailing_metadata(self): + """Access value to be used as trailing metadata upon RPC completion. + + This is an EXPERIMENTAL API. + + Returns: + The trailing :term:`metadata` for the RPC. + """ + raise NotImplementedError() + @abc.abstractmethod def abort(self, code, details): """Raises an exception to terminate the RPC with a non-OK status. @@ -1251,6 +1247,26 @@ class ServicerContext(six.with_metaclass(abc.ABCMeta, RpcContext)): """ raise NotImplementedError() + def code(self): + """Accesses the value to be used as status code upon RPC completion. + + This is an EXPERIMENTAL API. + + Returns: + The StatusCode value for the RPC. + """ + raise NotImplementedError() + + def details(self): + """Accesses the value to be used as detail string upon RPC completion. + + This is an EXPERIMENTAL API. + + Returns: + The details string of the RPC. + """ + raise NotImplementedError() + def disable_next_message_compression(self): """Disables compression for the next response message. @@ -1351,10 +1367,7 @@ class ServiceRpcHandler(six.with_metaclass(abc.ABCMeta, GenericRpcHandler)): class ServerInterceptor(six.with_metaclass(abc.ABCMeta)): - """Affords intercepting incoming RPCs on the service-side. - - This is an EXPERIMENTAL API. - """ + """Affords intercepting incoming RPCs on the service-side.""" @abc.abstractmethod def intercept_service(self, continuation, handler_call_details): @@ -1991,8 +2004,6 @@ def secure_channel(target, credentials, options=None, compression=None): def intercept_channel(channel, *interceptors): """Intercepts a channel through a set of interceptors. - This is an EXPERIMENTAL API. - Args: channel: A Channel. interceptors: Zero or more objects of type diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/aio/call.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/aio/call.pyx.pxi index 2c2a3ff3f6e..7bce1850dc8 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/call.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/call.pyx.pxi @@ -134,37 +134,38 @@ cdef class _AioCall(GrpcCallWrapper): cdef void _set_status(self, AioRpcStatus status) except *: cdef list waiters + # No more waiters should be expected since status has been set. self._status = status if self._initial_metadata is None: self._set_initial_metadata(_IMMUTABLE_EMPTY_METADATA) - # No more waiters should be expected since status - # has been set. - waiters = self._waiters_status - self._waiters_status = None - - for waiter in waiters: + for waiter in self._waiters_status: if not waiter.done(): waiter.set_result(None) + self._waiters_status = [] for callback in self._done_callbacks: callback() cdef void _set_initial_metadata(self, tuple initial_metadata) except *: + if self._initial_metadata is not None: + # Some gRPC calls might end before the initial metadata arrived in + # the Call object. That causes this method to be invoked twice: 1. + # filled with an empty metadata; 2. updated with the actual user + # provided metadata. + return + cdef list waiters + # No more waiters should be expected since initial metadata has been + # set. self._initial_metadata = initial_metadata - # No more waiters should be expected since initial metadata - # has been set. - waiters = self._waiters_initial_metadata - self._waiters_initial_metadata = None - - for waiter in waiters: + for waiter in self._waiters_initial_metadata: if not waiter.done(): waiter.set_result(None) - + self._waiters_initial_metadata = [] def add_done_callback(self, callback): if self.done(): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/iomgr.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/iomgr.pyx.pxi index 917ae24e11e..86171def061 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/iomgr.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/iomgr.pyx.pxi @@ -31,13 +31,13 @@ cdef grpc_custom_poller_vtable asyncio_pollset_vtable cdef bint so_reuse_port -cdef grpc_error* asyncio_socket_init( +cdef grpc_error_handle asyncio_socket_init( grpc_custom_socket* grpc_socket, int domain) with gil: socket = _AsyncioSocket.create(grpc_socket, None, None) Py_INCREF(socket) grpc_socket.impl = socket - return 0 + return 0 cdef void asyncio_socket_destroy(grpc_custom_socket* grpc_socket) with gil: @@ -84,7 +84,7 @@ cdef void asyncio_socket_read( socket.read(buffer_, length, read_cb) -cdef grpc_error* asyncio_socket_getpeername( +cdef grpc_error_handle asyncio_socket_getpeername( grpc_custom_socket* grpc_socket, const grpc_sockaddr* addr, int* length) with gil: @@ -99,7 +99,7 @@ cdef grpc_error* asyncio_socket_getpeername( return grpc_error_none() -cdef grpc_error* asyncio_socket_getsockname( +cdef grpc_error_handle asyncio_socket_getsockname( grpc_custom_socket* grpc_socket, const grpc_sockaddr* addr, int* length) with gil: @@ -118,7 +118,7 @@ cdef grpc_error* asyncio_socket_getsockname( return grpc_error_none() -cdef grpc_error* asyncio_socket_listen(grpc_custom_socket* grpc_socket) with gil: +cdef grpc_error_handle asyncio_socket_listen(grpc_custom_socket* grpc_socket) with gil: (<_AsyncioSocket>grpc_socket.impl).listen() return grpc_error_none() @@ -134,7 +134,7 @@ def _asyncio_apply_socket_options(object s, int flags): s.setsockopt(native_socket.IPPROTO_TCP, native_socket.TCP_NODELAY, True) -cdef grpc_error* asyncio_socket_bind( +cdef grpc_error_handle asyncio_socket_bind( grpc_custom_socket* grpc_socket, const grpc_sockaddr* addr, size_t len, int flags) with gil: @@ -166,7 +166,7 @@ cdef void asyncio_socket_accept( (<_AsyncioSocket>grpc_socket.impl).accept(grpc_socket_client, accept_cb) -cdef grpc_error* asyncio_resolve( +cdef grpc_error_handle asyncio_resolve( const char* host, const char* port, grpc_resolved_addresses** res) with gil: diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/resolver.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/resolver.pyx.pxi index 1a2e244ff9c..64e3e6396e9 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/resolver.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/resolver.pyx.pxi @@ -45,7 +45,7 @@ cdef class _AsyncioResolver: grpc_custom_resolve_callback( self._grpc_resolver, tuples_to_resolvaddr(resolved), - 0 + 0 ) cdef void resolve(self, const char* host, const char* port): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/socket.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/socket.pyx.pxi index eecef17d98a..43817ef87bf 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/socket.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/socket.pyx.pxi @@ -81,7 +81,7 @@ cdef class _AsyncioSocket: self._grpc_connect_cb( self._grpc_socket, - 0 + 0 ) cdef void connect(self, @@ -115,7 +115,7 @@ cdef class _AsyncioSocket: self._grpc_read_cb( self._grpc_socket, len(inbound_buffer), - 0 + 0 ) cdef void read(self, char * buffer_, size_t length, grpc_custom_read_callback grpc_read_cb): @@ -132,7 +132,7 @@ cdef class _AsyncioSocket: await self._writer.drain() self._grpc_write_cb( self._grpc_socket, - 0 + 0 ) except ConnectionError as connection_error: self._grpc_write_cb( diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/timer.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/timer.pyx.pxi index c1508373a4b..f2f7f492901 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/timer.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/iomgr/timer.pyx.pxi @@ -31,7 +31,7 @@ cdef class _AsyncioTimer: def on_time_up(self): self._active = False - grpc_custom_timer_callback(self._grpc_timer, 0) + grpc_custom_timer_callback(self._grpc_timer, 0) cpython.Py_DECREF(self) def __repr__(self): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pyx.pxi index c1b998cc887..2b46c0cc29f 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/aio/server.pyx.pxi @@ -197,15 +197,24 @@ cdef class _ServicerContext: def set_trailing_metadata(self, object metadata): self._rpc_state.trailing_metadata = tuple(metadata) + def trailing_metadata(self): + return self._rpc_state.trailing_metadata + def invocation_metadata(self): return self._rpc_state.invocation_metadata() def set_code(self, object code): self._rpc_state.status_code = get_status_code(code) + def code(self): + return self._rpc_state.status_code + def set_details(self, str details): self._rpc_state.status_details = details + def details(self): + return self._rpc_state.status_details + def set_compression(self, object compression): if self._rpc_state.metadata_sent: raise RuntimeError('Compression setting must be specified before sending initial metadata') @@ -252,6 +261,12 @@ cdef class _ServicerContext: else: return {} + def time_remaining(self): + if self._rpc_state.details.deadline.seconds == _GPR_INF_FUTURE.seconds: + return None + else: + return max(_time_from_timespec(self._rpc_state.details.deadline) - time.time(), 0) + cdef class _SyncServicerContext: """Sync servicer context for sync handler compatibility.""" @@ -311,6 +326,9 @@ cdef class _SyncServicerContext: def auth_context(self): return self._context.auth_context() + def time_remaining(self): + return self._context.time_remaining() + async def _run_interceptor(object interceptors, object query_handler, object handler_call_details): diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi index e7e59261b45..b2ca84fddc1 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx.pxi @@ -45,12 +45,17 @@ cdef int _get_metadata(void *state, cdef size_t metadata_count cdef grpc_metadata *c_metadata def callback(metadata, grpc_status_code status, bytes error_details): + cdef char* c_error_details = NULL + if error_details is not None: + c_error_details = error_details if status == StatusCode.ok: _store_c_metadata(metadata, &c_metadata, &metadata_count) - cb(user_data, c_metadata, metadata_count, status, NULL) + with nogil: + cb(user_data, c_metadata, metadata_count, status, NULL) _release_c_metadata(c_metadata, metadata_count) else: - cb(user_data, NULL, 0, status, error_details) + with nogil: + cb(user_data, NULL, 0, status, c_error_details) args = context.service_url, context.method_name, callback, _spawn_callback_async(state, args) return 0 # Asynchronous return diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/csds.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/csds.pyx.pxi new file mode 100644 index 00000000000..c33eb76e47f --- /dev/null +++ b/src/python/grpcio/grpc/_cython/_cygrpc/csds.pyx.pxi @@ -0,0 +1,21 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def dump_xds_configs(): + cdef grpc_slice client_config_in_slice + with nogil: + client_config_in_slice = grpc_dump_xds_configs() + cdef bytes result = _slice_bytes(client_config_in_slice) + return result diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi index b7d5e2e4c87..fb8ceae6a5d 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxi @@ -404,7 +404,15 @@ cdef extern from "grpc/grpc.h": void grpc_server_set_config_fetcher( grpc_server* server, grpc_server_config_fetcher* config_fetcher) nogil - grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create() nogil + ctypedef struct grpc_server_xds_status_notifier: + void (*on_serving_status_update)(void* user_data, const char* uri, + grpc_status_code code, + const char* error_message) + void* user_data; + + grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create( + grpc_server_xds_status_notifier notifier, + const grpc_channel_args* args) nogil int grpc_server_add_insecure_http2_port( @@ -425,6 +433,8 @@ cdef extern from "grpc/grpc.h": char* grpc_channelz_get_subchannel(intptr_t subchannel_id) char* grpc_channelz_get_socket(intptr_t socket_id) + grpc_slice grpc_dump_xds_configs() nogil + cdef extern from "grpc/grpc_security.h": @@ -576,7 +586,7 @@ cdef extern from "grpc/grpc_security.h": ctypedef void (*grpc_credentials_plugin_metadata_cb)( void *user_data, const grpc_metadata *creds_md, size_t num_creds_md, - grpc_status_code status, const char *error_details) + grpc_status_code status, const char *error_details) nogil ctypedef struct grpc_metadata_credentials_plugin: int (*get_metadata)( diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi index d857317ead0..c86ff2f1ff1 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx.pxi @@ -41,7 +41,7 @@ cdef class SocketWrapper: def __dealloc__(self): grpc_shutdown() -cdef grpc_error* socket_init(grpc_custom_socket* socket, int domain) with gil: +cdef grpc_error_handle socket_init(grpc_custom_socket* socket, int domain) with gil: sw = SocketWrapper() sw.c_socket = socket sw.sockopts = [] @@ -168,7 +168,7 @@ cdef void socket_read(grpc_custom_socket* socket, char* buffer, sw.len = length _spawn_greenlet(socket_read_async, sw) -cdef grpc_error* socket_getpeername(grpc_custom_socket* socket, +cdef grpc_error_handle socket_getpeername(grpc_custom_socket* socket, const grpc_sockaddr* addr, int* length) with gil: cdef char* src_buf @@ -181,7 +181,7 @@ cdef grpc_error* socket_getpeername(grpc_custom_socket* socket, length[0] = c_addr.len return grpc_error_none() -cdef grpc_error* socket_getsockname(grpc_custom_socket* socket, +cdef grpc_error_handle socket_getsockname(grpc_custom_socket* socket, const grpc_sockaddr* addr, int* length) with gil: cdef char* src_buf @@ -200,7 +200,7 @@ def applysockopts(s): s.setsockopt(gevent_socket.SOL_SOCKET, gevent_socket.SO_REUSEADDR, 1) s.setsockopt(gevent_socket.IPPROTO_TCP, gevent_socket.TCP_NODELAY, True) -cdef grpc_error* socket_bind(grpc_custom_socket* socket, +cdef grpc_error_handle socket_bind(grpc_custom_socket* socket, const grpc_sockaddr* addr, size_t len, int flags) with gil: addr_tuple = sockaddr_to_tuple(addr, len) @@ -219,7 +219,7 @@ cdef grpc_error* socket_bind(grpc_custom_socket* socket, else: return grpc_error_none() -cdef grpc_error* socket_listen(grpc_custom_socket* socket) with gil: +cdef grpc_error_handle socket_listen(grpc_custom_socket* socket) with gil: (socket.impl).socket.listen(50) return grpc_error_none() @@ -290,7 +290,7 @@ cdef void socket_resolve_async(grpc_custom_resolver* r, const char* host, const rw.c_port = port _spawn_greenlet(socket_resolve_async_python, rw) -cdef grpc_error* socket_resolve(const char* host, const char* port, +cdef grpc_error_handle socket_resolve(const char* host, const char* port, grpc_resolved_addresses** res) with gil: try: result = gevent_socket.getaddrinfo(host, port) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi index 0c5a4e5763d..9cf3113bbf7 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi @@ -23,11 +23,12 @@ cdef extern from "grpc/impl/codegen/slice.h": cdef extern from "src/core/lib/iomgr/error.h": struct grpc_error: pass + ctypedef grpc_error* grpc_error_handle # TODO(https://github.com/grpc/grpc/issues/20135) Change the filename # for something more meaningful. cdef extern from "src/core/lib/iomgr/python_util.h": - grpc_error* grpc_socket_error(char* error) + grpc_error_handle grpc_socket_error(char* error) char* grpc_slice_buffer_start(grpc_slice_buffer* buffer, int i) int grpc_slice_buffer_length(grpc_slice_buffer* buffer, int i) @@ -49,12 +50,12 @@ cdef extern from "src/core/lib/iomgr/resolve_address_custom.h": pass struct grpc_custom_resolver_vtable: - grpc_error* (*resolve)(const char* host, const char* port, grpc_resolved_addresses** res); + grpc_error_handle (*resolve)(const char* host, const char* port, grpc_resolved_addresses** res); void (*resolve_async)(grpc_custom_resolver* resolver, const char* host, const char* port); void grpc_custom_resolve_callback(grpc_custom_resolver* resolver, grpc_resolved_addresses* result, - grpc_error* error); + grpc_error_handle error); cdef extern from "src/core/lib/iomgr/tcp_custom.h": cdef int GRPC_CUSTOM_SOCKET_OPT_SO_REUSEPORT @@ -63,18 +64,18 @@ cdef extern from "src/core/lib/iomgr/tcp_custom.h": void* impl # We don't care about the rest of the fields ctypedef void (*grpc_custom_connect_callback)(grpc_custom_socket* socket, - grpc_error* error) + grpc_error_handle error) ctypedef void (*grpc_custom_write_callback)(grpc_custom_socket* socket, - grpc_error* error) + grpc_error_handle error) ctypedef void (*grpc_custom_read_callback)(grpc_custom_socket* socket, - size_t nread, grpc_error* error) + size_t nread, grpc_error_handle error) ctypedef void (*grpc_custom_accept_callback)(grpc_custom_socket* socket, grpc_custom_socket* client, - grpc_error* error) + grpc_error_handle error) ctypedef void (*grpc_custom_close_callback)(grpc_custom_socket* socket) struct grpc_socket_vtable: - grpc_error* (*init)(grpc_custom_socket* socket, int domain); + grpc_error_handle (*init)(grpc_custom_socket* socket, int domain); void (*connect)(grpc_custom_socket* socket, const grpc_sockaddr* addr, size_t len, grpc_custom_connect_callback cb); void (*destroy)(grpc_custom_socket* socket); @@ -84,13 +85,13 @@ cdef extern from "src/core/lib/iomgr/tcp_custom.h": grpc_custom_write_callback cb); void (*read)(grpc_custom_socket* socket, char* buffer, size_t length, grpc_custom_read_callback cb); - grpc_error* (*getpeername)(grpc_custom_socket* socket, + grpc_error_handle (*getpeername)(grpc_custom_socket* socket, const grpc_sockaddr* addr, int* len); - grpc_error* (*getsockname)(grpc_custom_socket* socket, + grpc_error_handle (*getsockname)(grpc_custom_socket* socket, const grpc_sockaddr* addr, int* len); - grpc_error* (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr, + grpc_error_handle (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr, size_t len, int flags); - grpc_error* (*listen)(grpc_custom_socket* socket); + grpc_error_handle (*listen)(grpc_custom_socket* socket); void (*accept)(grpc_custom_socket* socket, grpc_custom_socket* client, grpc_custom_accept_callback cb); @@ -104,7 +105,7 @@ cdef extern from "src/core/lib/iomgr/timer_custom.h": void (*start)(grpc_custom_timer* t); void (*stop)(grpc_custom_timer* t); - void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error); + void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error_handle error); cdef extern from "src/core/lib/iomgr/pollset_custom.h": struct grpc_custom_poller_vtable: @@ -119,11 +120,11 @@ cdef extern from "src/core/lib/iomgr/iomgr_custom.h": grpc_custom_timer_vtable* timer, grpc_custom_poller_vtable* poller); -cdef extern from "src/core/lib/iomgr/sockaddr_utils.h": +cdef extern from "src/core/lib/address_utils/sockaddr_utils.h": int grpc_sockaddr_get_port(const grpc_resolved_address *addr); cppstring grpc_sockaddr_to_string(const grpc_resolved_address *addr, bool_t normalize); - void grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port); + grpc_error_handle grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port); int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr, int port) const char* grpc_sockaddr_get_uri_scheme(const grpc_resolved_address* resolved_addr) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pyx.pxi index 3d6bb24f9a1..292e0473af6 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pyx.pxi @@ -17,10 +17,10 @@ from libc cimport string from libc.stdlib cimport malloc from libcpp.string cimport string as cppstring -cdef grpc_error* grpc_error_none(): - return 0 +cdef grpc_error_handle grpc_error_none(): + return 0 -cdef grpc_error* socket_error(str syscall, str err): +cdef grpc_error_handle socket_error(str syscall, str err): error_str = "{} failed: {}".format(syscall, err) error_bytes = str_to_bytes(error_str) return grpc_socket_error(error_bytes) diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi index ffd06ca4edc..d3caf3a5b84 100644 --- a/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi +++ b/src/python/grpcio/grpc/_cython/_cygrpc/server.pyx.pxi @@ -25,8 +25,12 @@ cdef class Server: self.c_server = NULL cdef _ChannelArgs channel_args = _ChannelArgs(arguments) self.c_server = grpc_server_create(channel_args.c_args(), NULL) + cdef grpc_server_xds_status_notifier notifier + notifier.on_serving_status_update = NULL + notifier.user_data = NULL if xds: - grpc_server_set_config_fetcher(self.c_server, grpc_server_config_fetcher_xds_create()) + grpc_server_set_config_fetcher(self.c_server, + grpc_server_config_fetcher_xds_create(notifier, channel_args.c_args())) self.references.append(arguments) def request_call( diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx index 0ce8bda0d89..b958975bb80 100644 --- a/src/python/grpcio/grpc/_cython/cygrpc.pyx +++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx @@ -41,6 +41,7 @@ include "_cygrpc/arguments.pyx.pxi" include "_cygrpc/call.pyx.pxi" include "_cygrpc/channel.pyx.pxi" include "_cygrpc/channelz.pyx.pxi" +include "_cygrpc/csds.pyx.pxi" include "_cygrpc/credentials.pyx.pxi" include "_cygrpc/completion_queue.pyx.pxi" include "_cygrpc/event.pyx.pxi" diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py index 9cdae5ef0af..b36bd7c8064 100644 --- a/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/src/python/grpcio/grpc/_grpcio_metadata.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!! -__version__ = """1.37.0.dev0""" +__version__ = """1.38.0.dev0""" diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py index 069ffa79822..6c6f02de8a0 100644 --- a/src/python/grpcio/grpc/_server.py +++ b/src/python/grpcio/grpc/_server.py @@ -305,6 +305,9 @@ class _Context(grpc.ServicerContext): with self._state.condition: self._state.trailing_metadata = trailing_metadata + def trailing_metadata(self): + return self._state.trailing_metadata + def abort(self, code, details): # treat OK like other invalid arguments: fail the RPC if code == grpc.StatusCode.OK: @@ -326,10 +329,16 @@ class _Context(grpc.ServicerContext): with self._state.condition: self._state.code = code + def code(self): + return self._state.code + def set_details(self, details): with self._state.condition: self._state.details = _common.encode(details) + def details(self): + return self._state.details + def _finalize_state(self): pass diff --git a/src/python/grpcio/grpc/aio/_base_server.py b/src/python/grpcio/grpc/aio/_base_server.py index 283f40f07f0..e22ef3e8303 100644 --- a/src/python/grpcio/grpc/aio/_base_server.py +++ b/src/python/grpcio/grpc/aio/_base_server.py @@ -193,7 +193,7 @@ class ServicerContext(Generic[RequestType, ResponseType], abc.ABC): """ @abc.abstractmethod - async def set_trailing_metadata(self, trailing_metadata: Metadata) -> None: + def set_trailing_metadata(self, trailing_metadata: Metadata) -> None: """Sends the trailing metadata for the RPC. This method need not be called by implementations if they have no @@ -295,3 +295,42 @@ class ServicerContext(Generic[RequestType, ResponseType], abc.ABC): Returns: A map of strings to an iterable of bytes for each auth property. """ + + def time_remaining(self) -> float: + """Describes the length of allowed time remaining for the RPC. + + Returns: + A nonnegative float indicating the length of allowed time in seconds + remaining for the RPC to complete before it is considered to have + timed out, or None if no deadline was specified for the RPC. + """ + + def trailing_metadata(self): + """Access value to be used as trailing metadata upon RPC completion. + + This is an EXPERIMENTAL API. + + Returns: + The trailing :term:`metadata` for the RPC. + """ + raise NotImplementedError() + + def code(self): + """Accesses the value to be used as status code upon RPC completion. + + This is an EXPERIMENTAL API. + + Returns: + The StatusCode value for the RPC. + """ + raise NotImplementedError() + + def details(self): + """Accesses the value to be used as detail string upon RPC completion. + + This is an EXPERIMENTAL API. + + Returns: + The details string of the RPC. + """ + raise NotImplementedError() diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py index 0cc1ff89eeb..c8c44688c38 100644 --- a/src/python/grpcio/grpc_core_dependencies.py +++ b/src/python/grpcio/grpc_core_dependencies.py @@ -40,6 +40,7 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc', 'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc', 'src/core/ext/filters/client_channel/lb_policy/priority/priority.cc', + 'src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc', 'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc', 'src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc', 'src/core/ext/filters/client_channel/lb_policy/xds/cds.cc', @@ -66,6 +67,8 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc', 'src/core/ext/filters/client_channel/resolver_registry.cc', 'src/core/ext/filters/client_channel/resolver_result_parsing.cc', + 'src/core/ext/filters/client_channel/retry_filter.cc', + 'src/core/ext/filters/client_channel/retry_service_config.cc', 'src/core/ext/filters/client_channel/retry_throttle.cc', 'src/core/ext/filters/client_channel/server_address.cc', 'src/core/ext/filters/client_channel/service_config.cc', @@ -75,6 +78,8 @@ CORE_SOURCE_FILES = [ 'src/core/ext/filters/client_channel/subchannel_pool_interface.cc', 'src/core/ext/filters/client_idle/client_idle_filter.cc', 'src/core/ext/filters/deadline/deadline_filter.cc', + 'src/core/ext/filters/fault_injection/fault_injection_filter.cc', + 'src/core/ext/filters/fault_injection/service_config_parser.cc', 'src/core/ext/filters/http/client/http_client_filter.cc', 'src/core/ext/filters/http/client_authority_filter.cc', 'src/core/ext/filters/http/http_filters_plugin.cc', @@ -120,9 +125,11 @@ CORE_SOURCE_FILES = [ 'src/core/ext/transport/chttp2/transport/writing.cc', 'src/core/ext/transport/inproc/inproc_plugin.cc', 'src/core/ext/transport/inproc/inproc_transport.cc', + 'src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c', 'src/core/ext/upb-generated/envoy/annotations/deprecation.upb.c', 'src/core/ext/upb-generated/envoy/annotations/resource.upb.c', 'src/core/ext/upb-generated/envoy/config/accesslog/v3/accesslog.upb.c', + 'src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c', 'src/core/ext/upb-generated/envoy/config/cluster/v3/circuit_breaker.upb.c', 'src/core/ext/upb-generated/envoy/config/cluster/v3/cluster.upb.c', 'src/core/ext/upb-generated/envoy/config/cluster/v3/filter.upb.c', @@ -147,12 +154,16 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upb-generated/envoy/config/listener/v3/listener.upb.c', 'src/core/ext/upb-generated/envoy/config/listener/v3/listener_components.upb.c', 'src/core/ext/upb-generated/envoy/config/listener/v3/udp_listener_config.upb.c', + 'src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c', + 'src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c', 'src/core/ext/upb-generated/envoy/config/rbac/v3/rbac.upb.c', 'src/core/ext/upb-generated/envoy/config/route/v3/route.upb.c', 'src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c', 'src/core/ext/upb-generated/envoy/config/route/v3/scoped_route.upb.c', 'src/core/ext/upb-generated/envoy/config/trace/v3/http_tracer.upb.c', 'src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c', + 'src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c', 'src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c', 'src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c', @@ -167,11 +178,14 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upb-generated/envoy/service/load_stats/v3/lrs.upb.c', 'src/core/ext/upb-generated/envoy/service/route/v3/rds.upb.c', 'src/core/ext/upb-generated/envoy/service/route/v3/srds.upb.c', + 'src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/metadata.upb.c', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/number.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/path.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/regex.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/string.upb.c', + 'src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c', 'src/core/ext/upb-generated/envoy/type/matcher/v3/value.upb.c', 'src/core/ext/upb-generated/envoy/type/metadata/v3/metadata.upb.c', 'src/core/ext/upb-generated/envoy/type/tracing/v3/custom_tag.upb.c', @@ -210,9 +224,11 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upb-generated/xds/core/v3/resource.upb.c', 'src/core/ext/upb-generated/xds/core/v3/resource_locator.upb.c', 'src/core/ext/upb-generated/xds/core/v3/resource_name.upb.c', + 'src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/annotations/deprecation.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/annotations/resource.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/accesslog/v3/accesslog.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/circuit_breaker.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/cluster.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/cluster/v3/filter.upbdefs.c', @@ -237,11 +253,15 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/listener_components.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/config/trace/v3/http_tracer.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c', @@ -256,11 +276,14 @@ CORE_SOURCE_FILES = [ 'src/core/ext/upbdefs-generated/envoy/service/load_stats/v3/lrs.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/rds.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/service/route/v3/srds.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/metadata.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/number.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/path.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/regex.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/string.upbdefs.c', + 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/matcher/v3/value.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/metadata/v3/metadata.upbdefs.c', 'src/core/ext/upbdefs-generated/envoy/type/tracing/v3/custom_tag.upbdefs.c', @@ -299,8 +322,11 @@ CORE_SOURCE_FILES = [ 'src/core/ext/xds/xds_certificate_provider.cc', 'src/core/ext/xds/xds_client.cc', 'src/core/ext/xds/xds_client_stats.cc', + 'src/core/ext/xds/xds_http_fault_filter.cc', 'src/core/ext/xds/xds_http_filters.cc', 'src/core/ext/xds/xds_server_config_fetcher.cc', + 'src/core/lib/address_utils/parse_address.cc', + 'src/core/lib/address_utils/sockaddr_utils.cc', 'src/core/lib/avl/avl.cc', 'src/core/lib/backoff/backoff.cc', 'src/core/lib/channel/channel_args.cc', @@ -323,6 +349,8 @@ CORE_SOURCE_FILES = [ 'src/core/lib/debug/stats.cc', 'src/core/lib/debug/stats_data.cc', 'src/core/lib/debug/trace.cc', + 'src/core/lib/event_engine/slice_allocator.cc', + 'src/core/lib/event_engine/sockaddr.cc', 'src/core/lib/gpr/alloc.cc', 'src/core/lib/gpr/atm.cc', 'src/core/lib/gpr/cpu_iphone.cc', @@ -363,6 +391,7 @@ CORE_SOURCE_FILES = [ 'src/core/lib/gprpp/mpscq.cc', 'src/core/lib/gprpp/stat_posix.cc', 'src/core/lib/gprpp/stat_windows.cc', + 'src/core/lib/gprpp/status_helper.cc', 'src/core/lib/gprpp/thd_posix.cc', 'src/core/lib/gprpp/thd_windows.cc', 'src/core/lib/gprpp/time_util.cc', @@ -411,8 +440,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/is_epollexclusive_available.cc', 'src/core/lib/iomgr/load_file.cc', 'src/core/lib/iomgr/lockfree_event.cc', - 'src/core/lib/iomgr/parse_address.cc', - 'src/core/lib/iomgr/poller/eventmanager_libuv.cc', 'src/core/lib/iomgr/polling_entity.cc', 'src/core/lib/iomgr/pollset.cc', 'src/core/lib/iomgr/pollset_custom.cc', @@ -426,7 +453,6 @@ CORE_SOURCE_FILES = [ 'src/core/lib/iomgr/resolve_address_posix.cc', 'src/core/lib/iomgr/resolve_address_windows.cc', 'src/core/lib/iomgr/resource_quota.cc', - 'src/core/lib/iomgr/sockaddr_utils.cc', 'src/core/lib/iomgr/socket_factory_posix.cc', 'src/core/lib/iomgr/socket_mutator.cc', 'src/core/lib/iomgr/socket_utils_common_posix.cc', @@ -469,11 +495,9 @@ CORE_SOURCE_FILES = [ 'src/core/lib/json/json_reader.cc', 'src/core/lib/json/json_util.cc', 'src/core/lib/json/json_writer.cc', + 'src/core/lib/matchers/matchers.cc', 'src/core/lib/profiling/basic_timers.cc', 'src/core/lib/profiling/stap_timers.cc', - 'src/core/lib/security/authorization/authorization_engine.cc', - 'src/core/lib/security/authorization/evaluate_args.cc', - 'src/core/lib/security/authorization/matchers.cc', 'src/core/lib/security/context/security_context.cc', 'src/core/lib/security/credentials/alts/alts_credentials.cc', 'src/core/lib/security/credentials/alts/check_gcp_environment.cc', @@ -617,6 +641,7 @@ CORE_SOURCE_FILES = [ 'third_party/abseil-cpp/absl/debugging/symbolize.cc', 'third_party/abseil-cpp/absl/hash/internal/city.cc', 'third_party/abseil-cpp/absl/hash/internal/hash.cc', + 'third_party/abseil-cpp/absl/hash/internal/wyhash.cc', 'third_party/abseil-cpp/absl/numeric/int128.cc', 'third_party/abseil-cpp/absl/status/status.cc', 'third_party/abseil-cpp/absl/status/status_payload_printer.cc', @@ -627,6 +652,8 @@ CORE_SOURCE_FILES = [ 'third_party/abseil-cpp/absl/strings/escaping.cc', 'third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc', 'third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc', + 'third_party/abseil-cpp/absl/strings/internal/cord_internal.cc', + 'third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc', 'third_party/abseil-cpp/absl/strings/internal/escaping.cc', 'third_party/abseil-cpp/absl/strings/internal/memutil.cc', 'third_party/abseil-cpp/absl/strings/internal/ostringstream.cc', @@ -779,7 +806,6 @@ CORE_SOURCE_FILES = [ 'third_party/boringssl-with-bazel/src/crypto/ex_data.c', 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/bcm.c', 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/fips_shared_support.c', - 'third_party/boringssl-with-bazel/src/crypto/fipsmodule/is_fips.c', 'third_party/boringssl-with-bazel/src/crypto/hkdf/hkdf.c', 'third_party/boringssl-with-bazel/src/crypto/hpke/hpke.c', 'third_party/boringssl-with-bazel/src/crypto/hrss/hrss.c', @@ -846,7 +872,6 @@ CORE_SOURCE_FILES = [ 'third_party/boringssl-with-bazel/src/crypto/x509/x509_ext.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_lu.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_obj.c', - 'third_party/boringssl-with-bazel/src/crypto/x509/x509_r2x.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_req.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_set.c', 'third_party/boringssl-with-bazel/src/crypto/x509/x509_trs.c', @@ -911,6 +936,7 @@ CORE_SOURCE_FILES = [ 'third_party/boringssl-with-bazel/src/ssl/d1_srtp.cc', 'third_party/boringssl-with-bazel/src/ssl/dtls_method.cc', 'third_party/boringssl-with-bazel/src/ssl/dtls_record.cc', + 'third_party/boringssl-with-bazel/src/ssl/encrypted_client_hello.cc', 'third_party/boringssl-with-bazel/src/ssl/handoff.cc', 'third_party/boringssl-with-bazel/src/ssl/handshake.cc', 'third_party/boringssl-with-bazel/src/ssl/handshake_client.cc', @@ -1017,8 +1043,6 @@ CORE_SOURCE_FILES = [ 'third_party/upb/upb/decode_fast.c', 'third_party/upb/upb/def.c', 'third_party/upb/upb/encode.c', - 'third_party/upb/upb/json_decode.c', - 'third_party/upb/upb/json_encode.c', 'third_party/upb/upb/msg.c', 'third_party/upb/upb/reflection.c', 'third_party/upb/upb/table.c', diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py index 4e7613d2560..c29bdb1e973 100644 --- a/src/python/grpcio/grpc_version.py +++ b/src/python/grpcio/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!! -VERSION = '1.37.0.dev0' +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_admin/.gitignore b/src/python/grpcio_admin/.gitignore new file mode 100644 index 00000000000..6f95c5f61ae --- /dev/null +++ b/src/python/grpcio_admin/.gitignore @@ -0,0 +1,6 @@ +*.proto +*_pb2.py +*_pb2_grpc.py +build/ +grpcio_admin.egg-info/ +dist/ diff --git a/src/python/grpcio_admin/MANIFEST.in b/src/python/grpcio_admin/MANIFEST.in new file mode 100644 index 00000000000..eb7e029a4ba --- /dev/null +++ b/src/python/grpcio_admin/MANIFEST.in @@ -0,0 +1,4 @@ +include grpc_version.py +recursive-include grpc_admin *.py +global-exclude *.pyc +include LICENSE diff --git a/src/python/grpcio_admin/README.rst b/src/python/grpcio_admin/README.rst new file mode 100644 index 00000000000..d9959840eb5 --- /dev/null +++ b/src/python/grpcio_admin/README.rst @@ -0,0 +1,23 @@ +gRPC Python Admin Interface Package +=================================== + +Debugging gRPC library can be a complex task. There are many configurations and +internal states, which will affect the behavior of the library. This Python +package will be the collection of admin services that are exposing debug +information. Currently, it includes: + +* Channel tracing metrics (grpcio-channelz) +* Client Status Discovery Service (grpcio-csds) + +Here is a snippet to create an admin server on "localhost:50051": + + server = grpc.server(ThreadPoolExecutor()) + port = server.add_insecure_port('localhost:50051') + grpc_admin.add_admin_servicers(self._server) + server.start() + +Welcome to explore the admin services with CLI tool "grpcdebug": +https://github.com/grpc-ecosystem/grpcdebug. + +For any issues or suggestions, please send to +https://github.com/grpc/grpc/issues. diff --git a/src/python/grpcio_admin/grpc_admin/BUILD.bazel b/src/python/grpcio_admin/grpc_admin/BUILD.bazel new file mode 100644 index 00000000000..bd81a665497 --- /dev/null +++ b/src/python/grpcio_admin/grpc_admin/BUILD.bazel @@ -0,0 +1,25 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +package(default_visibility = ["//visibility:public"]) + +py_library( + name = "grpc_admin", + srcs = glob(["*.py"]), + imports = ["../"], + deps = [ + "//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz", + "//src/python/grpcio_csds/grpc_csds", + ], +) diff --git a/src/python/grpcio_admin/grpc_admin/__init__.py b/src/python/grpcio_admin/grpc_admin/__init__.py new file mode 100644 index 00000000000..96dfca1e316 --- /dev/null +++ b/src/python/grpcio_admin/grpc_admin/__init__.py @@ -0,0 +1,42 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""gRPC Python's Admin interface.""" + +import grpc_csds +from grpc_channelz.v1 import channelz + + +def add_admin_servicers(server): + """Register admin servicers to a server. + + gRPC provides some predefined admin services to make debugging easier by + exposing gRPC's internal states. Each existing admin service is packaged as + a separate library, and the documentation of the predefined admin services + is usually scattered. It can be time consuming to get the dependency + management, module initialization, and library import right for each one of + them. + + This API provides a convenient way to create a gRPC server to expose admin + services. With this, any new admin services that you may add in the future + are automatically available via the admin interface just by upgrading your + gRPC version. + + Args: + server: A gRPC server to which all admin services will be added. + """ + channelz.add_channelz_servicer(server) + grpc_csds.add_csds_servicer(server) + + +__all__ = ['add_admin_servicers'] diff --git a/src/python/grpcio_admin/grpc_version.py b/src/python/grpcio_admin/grpc_version.py new file mode 100644 index 00000000000..fffb42c0c3b --- /dev/null +++ b/src/python/grpcio_admin/grpc_version.py @@ -0,0 +1,17 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_admin/grpc_version.py.template`!!! + +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_admin/setup.py b/src/python/grpcio_admin/setup.py new file mode 100644 index 00000000000..6c2438ef5ee --- /dev/null +++ b/src/python/grpcio_admin/setup.py @@ -0,0 +1,60 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Setup module for admin interface in gRPC Python.""" + +import os +import sys + +import setuptools + +_PACKAGE_PATH = os.path.realpath(os.path.dirname(__file__)) +_README_PATH = os.path.join(_PACKAGE_PATH, 'README.rst') + +# Ensure we're in the proper directory whether or not we're being used by pip. +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +# Break import-style to ensure we can actually find our local modules. +import grpc_version + +CLASSIFIERS = [ + 'Development Status :: 5 - Production/Stable', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: Apache Software License', +] + +PACKAGE_DIRECTORIES = { + '': '.', +} + +INSTALL_REQUIRES = ( + 'grpcio-channelz>={version}'.format(version=grpc_version.VERSION), + 'grpcio-csds>={version}'.format(version=grpc_version.VERSION), +) +SETUP_REQUIRES = INSTALL_REQUIRES + +setuptools.setup(name='grpcio-admin', + version=grpc_version.VERSION, + license='Apache License 2.0', + description='a collection of admin services', + long_description=open(_README_PATH, 'r').read(), + author='The gRPC Authors', + author_email='grpc-io@googlegroups.com', + classifiers=CLASSIFIERS, + url='https://grpc.io', + package_dir=PACKAGE_DIRECTORIES, + packages=setuptools.find_packages('.'), + install_requires=INSTALL_REQUIRES, + setup_requires=SETUP_REQUIRES) diff --git a/src/python/grpcio_channelz/grpc_version.py b/src/python/grpcio_channelz/grpc_version.py index bbaa9f43398..85b3bf06ac8 100644 --- a/src/python/grpcio_channelz/grpc_version.py +++ b/src/python/grpcio_channelz/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_channelz/grpc_version.py.template`!!! -VERSION = '1.37.0.dev0' +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_csds/.gitignore b/src/python/grpcio_csds/.gitignore new file mode 100644 index 00000000000..24f7dd994aa --- /dev/null +++ b/src/python/grpcio_csds/.gitignore @@ -0,0 +1,6 @@ +*.proto +*_pb2.py +*_pb2_grpc.py +build/ +grpcio_csds.egg-info/ +dist/ diff --git a/src/python/grpcio_csds/MANIFEST.in b/src/python/grpcio_csds/MANIFEST.in new file mode 100644 index 00000000000..4ecdf7428ed --- /dev/null +++ b/src/python/grpcio_csds/MANIFEST.in @@ -0,0 +1,4 @@ +include grpc_version.py +recursive-include grpc_csds *.py +global-exclude *.pyc +include LICENSE diff --git a/src/python/grpcio_csds/README.rst b/src/python/grpcio_csds/README.rst new file mode 100644 index 00000000000..f8803f253d8 --- /dev/null +++ b/src/python/grpcio_csds/README.rst @@ -0,0 +1,10 @@ +gRPC Python Client Status Discovery Service package +=================================================== + +CSDS is part of the Envoy xDS protocol: +https://www.envoyproxy.io/docs/envoy/latest/api-v3/service/status/v3/csds.proto. +It allows the gRPC application to programmatically expose the received traffic +configuration (xDS resources). Welcome to explore with CLI tool "grpcdebug": +https://github.com/grpc-ecosystem/grpcdebug. + +For any issues or suggestions, please send to https://github.com/grpc/grpc/issues. diff --git a/src/python/grpcio_csds/grpc_csds/BUILD.bazel b/src/python/grpcio_csds/grpc_csds/BUILD.bazel new file mode 100644 index 00000000000..2e799ef58ab --- /dev/null +++ b/src/python/grpcio_csds/grpc_csds/BUILD.bazel @@ -0,0 +1,31 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@grpc_python_dependencies//:requirements.bzl", "requirement") + +package(default_visibility = ["//visibility:public"]) + +py_library( + name = "grpc_csds", + srcs = glob(["*.py"]), + imports = ["../"], + deps = [ + "//src/proto/grpc/testing/xds/v3:base_py_pb2", + "//src/proto/grpc/testing/xds/v3:config_dump_py_pb2", + "//src/proto/grpc/testing/xds/v3:csds_py_pb2", + "//src/proto/grpc/testing/xds/v3:csds_py_pb2_grpc", + "//src/proto/grpc/testing/xds/v3:percent_py_pb2", + "//src/python/grpcio/grpc:grpcio", + ], +) diff --git a/src/python/grpcio_csds/grpc_csds/__init__.py b/src/python/grpcio_csds/grpc_csds/__init__.py new file mode 100644 index 00000000000..e30925585ca --- /dev/null +++ b/src/python/grpcio_csds/grpc_csds/__init__.py @@ -0,0 +1,59 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Channelz debug service implementation in gRPC Python.""" + +from grpc._cython import cygrpc + +from google.protobuf import json_format +try: + from envoy.service.status.v3 import csds_pb2, csds_pb2_grpc +except ImportError: + from src.proto.grpc.testing.xds.v3 import csds_pb2, csds_pb2_grpc + + +class ClientStatusDiscoveryServiceServicer( + csds_pb2_grpc.ClientStatusDiscoveryServiceServicer): + """CSDS Servicer works for both the sync API and asyncio API.""" + + @staticmethod + def FetchClientStatus(request, unused_context): + client_config = csds_pb2.ClientConfig.FromString( + cygrpc.dump_xds_configs()) + response = csds_pb2.ClientStatusResponse() + response.config.append(client_config) + return response + + @staticmethod + def StreamClientStatus(request_iterator, context): + for request in request_iterator: + yield ClientStatusDiscoveryServiceServicer.FetchClientStatus( + request, context) + + +def add_csds_servicer(server): + """Register CSDS servicer to a server. + + CSDS is part of xDS protocol used to expose in-effective traffic + configuration (or xDS resources). It focuses on simplify the debugging of + unexpected routing behaviors, which could be due to a misconfiguration, + unhealthy backends or issues in the control or data plane. + + Args: + server: A gRPC server to which the CSDS service will be added. + """ + csds_pb2_grpc.add_ClientStatusDiscoveryServiceServicer_to_server( + ClientStatusDiscoveryServiceServicer(), server) + + +__all__ = ['ClientStatusDiscoveryServiceServicer', 'add_csds_servicer'] diff --git a/src/python/grpcio_csds/grpc_version.py b/src/python/grpcio_csds/grpc_version.py new file mode 100644 index 00000000000..510a148a9ef --- /dev/null +++ b/src/python/grpcio_csds/grpc_version.py @@ -0,0 +1,17 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_csds/grpc_version.py.template`!!! + +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_csds/setup.py b/src/python/grpcio_csds/setup.py new file mode 100644 index 00000000000..c699fc7d921 --- /dev/null +++ b/src/python/grpcio_csds/setup.py @@ -0,0 +1,61 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Setup module for CSDS in gRPC Python.""" + +import os +import sys + +import setuptools + +_PACKAGE_PATH = os.path.realpath(os.path.dirname(__file__)) +_README_PATH = os.path.join(_PACKAGE_PATH, 'README.rst') + +# Ensure we're in the proper directory whether or not we're being used by pip. +os.chdir(os.path.dirname(os.path.abspath(__file__))) + +# Break import-style to ensure we can actually find our local modules. +import grpc_version + +CLASSIFIERS = [ + 'Development Status :: 5 - Production/Stable', + 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: Apache Software License', +] + +PACKAGE_DIRECTORIES = { + '': '.', +} + +INSTALL_REQUIRES = ( + 'protobuf>=3.6.0', + 'xds-protos>=0.0.7', + 'grpcio>={version}'.format(version=grpc_version.VERSION), +) +SETUP_REQUIRES = INSTALL_REQUIRES + +setuptools.setup(name='grpcio-csds', + version=grpc_version.VERSION, + license='Apache License 2.0', + description='xDS configuration dump library', + long_description=open(_README_PATH, 'r').read(), + author='The gRPC Authors', + author_email='grpc-io@googlegroups.com', + classifiers=CLASSIFIERS, + url='https://grpc.io', + package_dir=PACKAGE_DIRECTORIES, + packages=setuptools.find_packages('.'), + install_requires=INSTALL_REQUIRES, + setup_requires=SETUP_REQUIRES) diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py index 8fbcf9dca96..721f11f1f60 100644 --- a/src/python/grpcio_health_checking/grpc_version.py +++ b/src/python/grpcio_health_checking/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!! -VERSION = '1.37.0.dev0' +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py index bc7f7963446..41806876001 100644 --- a/src/python/grpcio_reflection/grpc_version.py +++ b/src/python/grpcio_reflection/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!! -VERSION = '1.37.0.dev0' +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_status/grpc_version.py b/src/python/grpcio_status/grpc_version.py index efe36468450..a432556f8b4 100644 --- a/src/python/grpcio_status/grpc_version.py +++ b/src/python/grpcio_status/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_status/grpc_version.py.template`!!! -VERSION = '1.37.0.dev0' +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py index fb9ca4ccf9a..ae0cd5b7689 100644 --- a/src/python/grpcio_testing/grpc_version.py +++ b/src/python/grpcio_testing/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!! -VERSION = '1.37.0.dev0' +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py index 889b0bd9dc3..f5f3849ad2c 100644 --- a/src/python/grpcio_tests/commands.py +++ b/src/python/grpcio_tests/commands.py @@ -231,6 +231,9 @@ class TestGevent(setuptools.Command): # TODO(https://github.com/grpc/grpc/pull/15411) enable this test 'unit._server_test.ServerTest.test_failed_port_binding_exception', ) + BANNED_MACOS_TESTS = ( + # TODO(https://github.com/grpc/grpc/issues/15411) enable this test + 'unit._dynamic_stubs_test.DynamicStubTest',) description = 'run tests with gevent. Assumes grpc/gevent are installed' user_options = [] @@ -258,6 +261,8 @@ class TestGevent(setuptools.Command): runner = tests.Runner() if sys.platform == 'win32': runner.skip_tests(self.BANNED_TESTS + self.BANNED_WINDOWS_TESTS) + elif sys.platform == 'darwin': + runner.skip_tests(self.BANNED_TESTS + self.BANNED_MACOS_TESTS) else: runner.skip_tests(self.BANNED_TESTS) result = gevent.spawn(runner.run, loader.suite) diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py index fb903df2b6a..fa15e9ac913 100644 --- a/src/python/grpcio_tests/grpc_version.py +++ b/src/python/grpcio_tests/grpc_version.py @@ -14,4 +14,4 @@ # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!! -VERSION = '1.37.0.dev0' +VERSION = '1.38.0.dev0' diff --git a/src/python/grpcio_tests/tests/admin/BUILD.bazel b/src/python/grpcio_tests/tests/admin/BUILD.bazel new file mode 100644 index 00000000000..d94be8c7cbf --- /dev/null +++ b/src/python/grpcio_tests/tests/admin/BUILD.bazel @@ -0,0 +1,26 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:python_rules.bzl", "py2and3_test") + +py2and3_test( + name = "test_admin", + size = "small", + srcs = ["test_admin.py"], + main = "test_admin.py", + deps = [ + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_admin/grpc_admin", + ], +) diff --git a/src/python/grpcio_tests/tests/admin/test_admin.py b/src/python/grpcio_tests/tests/admin/test_admin.py new file mode 100644 index 00000000000..484cfa04db2 --- /dev/null +++ b/src/python/grpcio_tests/tests/admin/test_admin.py @@ -0,0 +1,55 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""A test to ensure that admin services are registered correctly.""" + +import logging +import unittest +from concurrent.futures import ThreadPoolExecutor + +import grpc +import grpc_admin +from grpc_csds import csds_pb2, csds_pb2_grpc +from grpc_channelz.v1 import channelz_pb2, channelz_pb2_grpc + + +class TestAdmin(unittest.TestCase): + + def setUp(self): + self._server = grpc.server(ThreadPoolExecutor()) + port = self._server.add_insecure_port('localhost:0') + grpc_admin.add_admin_servicers(self._server) + self._server.start() + + self._channel = grpc.insecure_channel('localhost:%s' % port) + + def tearDown(self): + self._channel.close() + self._server.stop(0) + + def test_has_csds(self): + stub = csds_pb2_grpc.ClientStatusDiscoveryServiceStub(self._channel) + resp = stub.FetchClientStatus(csds_pb2.ClientStatusRequest()) + # No exception raised and the response is valid + self.assertGreater(len(resp.config), 0) + + def test_has_channelz(self): + stub = channelz_pb2_grpc.ChannelzStub(self._channel) + resp = stub.GetTopChannels(channelz_pb2.GetTopChannelsRequest()) + # No exception raised and the response is valid + self.assertGreater(len(resp.channel), 0) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py index 784307ae005..a5008970293 100644 --- a/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py +++ b/src/python/grpcio_tests/tests/channelz/_channelz_servicer_test.py @@ -350,6 +350,15 @@ class ChannelzServicerTest(unittest.TestCase): self.assertEqual(gsc_resp.subchannel.data.calls_succeeded, gs_resp.socket.data.messages_received) + if gs_resp.socket.remote.HasField("tcpip_address"): + address = gs_resp.socket.remote.tcpip_address.ip_address + self.assertTrue( + len(address) == 4 or len(address) == 16, address) + if gs_resp.socket.local.HasField("tcpip_address"): + address = gs_resp.socket.local.tcpip_address.ip_address + self.assertTrue( + len(address) == 4 or len(address) == 16, address) + def test_streaming_rpc(self): self._pairs = _generate_channel_server_pairs(1) # In C++, the argument for _send_successful_stream_stream is message length. @@ -413,6 +422,7 @@ class ChannelzServicerTest(unittest.TestCase): gs_resp = self._channelz_stub.GetSocket( channelz_pb2.GetSocketRequest( socket_id=gss_resp.server[0].listen_socket[0].socket_id)) + # If the RPC call failed, it will raise a grpc.RpcError # So, if there is no exception raised, considered pass diff --git a/src/python/grpcio_tests/tests/csds/BUILD.bazel b/src/python/grpcio_tests/tests/csds/BUILD.bazel new file mode 100644 index 00000000000..3cf916d727d --- /dev/null +++ b/src/python/grpcio_tests/tests/csds/BUILD.bazel @@ -0,0 +1,27 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("//bazel:python_rules.bzl", "py2and3_test") + +py2and3_test( + name = "test_csds", + size = "small", + srcs = ["test_csds.py"], + main = "test_csds.py", + deps = [ + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_csds/grpc_csds", + "@six", + ], +) diff --git a/src/python/grpcio_tests/tests/csds/test_csds.py b/src/python/grpcio_tests/tests/csds/test_csds.py new file mode 100644 index 00000000000..f9709435923 --- /dev/null +++ b/src/python/grpcio_tests/tests/csds/test_csds.py @@ -0,0 +1,134 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""A simple test to ensure that the Python wrapper can get xDS config.""" + +import logging +import os +import time +from six.moves import queue +import unittest +from concurrent.futures import ThreadPoolExecutor + +import grpc +import grpc_csds + +from google.protobuf import json_format +try: + from envoy.service.status.v3 import csds_pb2, csds_pb2_grpc +except ImportError: + from src.proto.grpc.testing.xds.v3 import csds_pb2, csds_pb2_grpc + +_DUMMY_XDS_ADDRESS = 'xds:///foo.bar' +_DUMMY_BOOTSTRAP_FILE = """ +{ + \"xds_servers\": [ + { + \"server_uri\": \"fake:///xds_server\", + \"channel_creds\": [ + { + \"type\": \"fake\" + } + ], + \"server_features\": [\"xds_v3\"] + } + ], + \"node\": { + \"id\": \"python_test_csds\", + \"cluster\": \"test\", + \"metadata\": { + \"foo\": \"bar\" + }, + \"locality\": { + \"region\": \"corp\", + \"zone\": \"svl\", + \"sub_zone\": \"mp3\" + } + } +}\ +""" + + +class TestCsds(unittest.TestCase): + + def setUp(self): + os.environ['GRPC_XDS_BOOTSTRAP_CONFIG'] = _DUMMY_BOOTSTRAP_FILE + self._server = grpc.server(ThreadPoolExecutor()) + port = self._server.add_insecure_port('localhost:0') + grpc_csds.add_csds_servicer(self._server) + self._server.start() + + self._channel = grpc.insecure_channel('localhost:%s' % port) + self._stub = csds_pb2_grpc.ClientStatusDiscoveryServiceStub( + self._channel) + + def tearDown(self): + self._channel.close() + self._server.stop(0) + os.environ.pop('GRPC_XDS_BOOTSTRAP_CONFIG', None) + + def get_xds_config_dump(self): + return self._stub.FetchClientStatus(csds_pb2.ClientStatusRequest()) + + def test_has_node(self): + resp = self.get_xds_config_dump() + self.assertEqual(1, len(resp.config)) + self.assertEqual(4, len(resp.config[0].xds_config)) + self.assertEqual('python_test_csds', resp.config[0].node.id) + self.assertEqual('test', resp.config[0].node.cluster) + + def test_no_lds_found(self): + dummy_channel = grpc.insecure_channel(_DUMMY_XDS_ADDRESS) + + # Force the XdsClient to initialize and request a resource + with self.assertRaises(grpc.RpcError) as rpc_error: + dummy_channel.unary_unary('')(b'', wait_for_ready=False) + self.assertEqual(grpc.StatusCode.UNAVAILABLE, + rpc_error.exception.code()) + + # The resource request will fail with DOES_NOT_EXIST (after 15s) + while True: + resp = self.get_xds_config_dump() + config = json_format.MessageToDict(resp) + ok = False + try: + for xds_config in config["config"][0]["xdsConfig"]: + if "listenerConfig" in xds_config: + listener = xds_config["listenerConfig"][ + "dynamicListeners"][0] + if listener['clientStatus'] == 'DOES_NOT_EXIST': + ok = True + break + except KeyError as e: + logging.debug("Invalid config: %s\n%s: %s", config, type(e), e) + pass + if ok: + break + time.sleep(1) + dummy_channel.close() + + +class TestCsdsStream(TestCsds): + + def get_xds_config_dump(self): + if not hasattr(self, 'request_queue'): + request_queue = queue.Queue() + response_iterator = self._stub.StreamClientStatus( + iter(request_queue.get, None)) + request_queue.put(csds_pb2.ClientStatusRequest()) + return next(response_iterator) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json index bd4139b4922..93f55bfd52e 100644 --- a/src/python/grpcio_tests/tests/tests.json +++ b/src/python/grpcio_tests/tests/tests.json @@ -60,6 +60,7 @@ "unit._invocation_defects_test.InvocationDefectsTest", "unit._local_credentials_test.LocalCredentialsTest", "unit._logging_test.LoggingTest", + "unit._metadata_code_details_test.InspectContextTest", "unit._metadata_code_details_test.MetadataCodeDetailsTest", "unit._metadata_flags_test.MetadataFlagsTest", "unit._metadata_test.MetadataTest", diff --git a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py index 5b06eb2bfe8..900fabd19af 100644 --- a/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py +++ b/src/python/grpcio_tests/tests/unit/_metadata_code_details_test.py @@ -658,6 +658,64 @@ class MetadataCodeDetailsTest(unittest.TestCase): self.assertEqual(_DETAILS, exception_context.exception.details()) +class _InspectServicer(_Servicer): + + def __init__(self): + super(_InspectServicer, self).__init__() + self.actual_code = None + self.actual_details = None + self.actual_trailing_metadata = None + + def unary_unary(self, request, context): + super(_InspectServicer, self).unary_unary(request, context) + + self.actual_code = context.code() + self.actual_details = context.details() + self.actual_trailing_metadata = context.trailing_metadata() + + +class InspectContextTest(unittest.TestCase): + + def setUp(self): + self._servicer = _InspectServicer() + self._server = test_common.test_server() + self._server.add_generic_rpc_handlers( + (_generic_handler(self._servicer),)) + port = self._server.add_insecure_port('[::]:0') + self._server.start() + + self._channel = grpc.insecure_channel('localhost:{}'.format(port)) + self._unary_unary = self._channel.unary_unary( + '/'.join(( + '', + _SERVICE, + _UNARY_UNARY, + )), + request_serializer=_REQUEST_SERIALIZER, + response_deserializer=_RESPONSE_DESERIALIZER, + ) + + def tearDown(self): + self._server.stop(None) + self._channel.close() + + def testCodeDetailsInContext(self): + self._servicer.set_code(_NON_OK_CODE) + self._servicer.set_details(_DETAILS) + + with self.assertRaises(grpc.RpcError) as exc_info: + self._unary_unary.with_call(object(), metadata=_CLIENT_METADATA) + + err = exc_info.exception + self.assertEqual(_NON_OK_CODE, err.code()) + + self.assertEqual(self._servicer.actual_code, _NON_OK_CODE) + self.assertEqual(self._servicer.actual_details.decode('utf-8'), + _DETAILS) + self.assertEqual(self._servicer.actual_trailing_metadata, + _SERVER_TRAILING_METADATA) + + if __name__ == '__main__': logging.basicConfig() unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests_aio/tests.json b/src/python/grpcio_tests/tests_aio/tests.json index 17ea7c8aa89..4d20c1d143e 100644 --- a/src/python/grpcio_tests/tests_aio/tests.json +++ b/src/python/grpcio_tests/tests_aio/tests.json @@ -36,6 +36,7 @@ "unit.secure_call_test.TestUnaryUnarySecureCall", "unit.server_interceptor_test.TestServerInterceptor", "unit.server_test.TestServer", + "unit.server_time_remaining_test.TestServerTimeRemaining", "unit.timeout_test.TestTimeout", "unit.wait_for_connection_test.TestWaitForConnection", "unit.wait_for_ready_test.TestWaitForReady" diff --git a/src/python/grpcio_tests/tests_aio/unit/_common.py b/src/python/grpcio_tests/tests_aio/unit/_common.py index 016280a1528..11513a722c0 100644 --- a/src/python/grpcio_tests/tests_aio/unit/_common.py +++ b/src/python/grpcio_tests/tests_aio/unit/_common.py @@ -21,6 +21,8 @@ from grpc.aio._metadata import Metadata from tests.unit.framework.common import test_constants +ADHOC_METHOD = '/test/AdHoc' + def seen_metadata(expected: Metadata, actual: Metadata): return not bool(set(tuple(expected)) - set(tuple(actual))) @@ -97,3 +99,20 @@ class CountingResponseIterator: def __aiter__(self): return self._forward_responses() + + +class AdhocGenericHandler(grpc.GenericRpcHandler): + """A generic handler to plugin testing server methods on the fly.""" + _handler: grpc.RpcMethodHandler + + def __init__(self): + self._handler = None + + def set_adhoc_handler(self, handler: grpc.RpcMethodHandler): + self._handler = handler + + def service(self, handler_call_details): + if handler_call_details.method == ADHOC_METHOD: + return self._handler + else: + return None diff --git a/src/python/grpcio_tests/tests_aio/unit/compatibility_test.py b/src/python/grpcio_tests/tests_aio/unit/compatibility_test.py index 0bb3a3acc89..e1f0f4d5845 100644 --- a/src/python/grpcio_tests/tests_aio/unit/compatibility_test.py +++ b/src/python/grpcio_tests/tests_aio/unit/compatibility_test.py @@ -35,29 +35,12 @@ _NUM_STREAM_RESPONSES = 5 _REQUEST_PAYLOAD_SIZE = 7 _RESPONSE_PAYLOAD_SIZE = 42 _REQUEST = b'\x03\x07' -_ADHOC_METHOD = '/test/AdHoc' def _unique_options() -> Sequence[Tuple[str, float]]: return (('iv', random.random()),) -class _AdhocGenericHandler(grpc.GenericRpcHandler): - _handler: grpc.RpcMethodHandler - - def __init__(self): - self._handler = None - - def set_adhoc_handler(self, handler: grpc.RpcMethodHandler): - self._handler = handler - - def service(self, handler_call_details): - if handler_call_details.method == _ADHOC_METHOD: - return self._handler - else: - return None - - @unittest.skipIf( os.environ.get('GRPC_ASYNCIO_ENGINE', '').lower() == 'custom_io_manager', 'Compatible mode needs POLLER completion queue.') @@ -70,7 +53,7 @@ class TestCompatibility(AioTestBase): test_pb2_grpc.add_TestServiceServicer_to_server(TestServiceServicer(), self._async_server) - self._adhoc_handlers = _AdhocGenericHandler() + self._adhoc_handlers = _common.AdhocGenericHandler() self._async_server.add_generic_rpc_handlers((self._adhoc_handlers,)) port = self._async_server.add_insecure_port('[::]:0') @@ -240,8 +223,8 @@ class TestCompatibility(AioTestBase): return request self._adhoc_handlers.set_adhoc_handler(echo_unary_unary) - response = await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST - ) + response = await self._async_channel.unary_unary(_common.ADHOC_METHOD + )(_REQUEST) self.assertEqual(_REQUEST, response) async def test_sync_unary_unary_metadata(self): @@ -253,7 +236,7 @@ class TestCompatibility(AioTestBase): return request self._adhoc_handlers.set_adhoc_handler(metadata_unary_unary) - call = self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST) + call = self._async_channel.unary_unary(_common.ADHOC_METHOD)(_REQUEST) self.assertTrue( _common.seen_metadata(aio.Metadata(*metadata), await call.initial_metadata())) @@ -266,7 +249,8 @@ class TestCompatibility(AioTestBase): self._adhoc_handlers.set_adhoc_handler(abort_unary_unary) with self.assertRaises(aio.AioRpcError) as exception_context: - await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST) + await self._async_channel.unary_unary(_common.ADHOC_METHOD + )(_REQUEST) self.assertEqual(grpc.StatusCode.INTERNAL, exception_context.exception.code()) @@ -278,7 +262,8 @@ class TestCompatibility(AioTestBase): self._adhoc_handlers.set_adhoc_handler(set_code_unary_unary) with self.assertRaises(aio.AioRpcError) as exception_context: - await self._async_channel.unary_unary(_ADHOC_METHOD)(_REQUEST) + await self._async_channel.unary_unary(_common.ADHOC_METHOD + )(_REQUEST) self.assertEqual(grpc.StatusCode.INTERNAL, exception_context.exception.code()) @@ -290,7 +275,7 @@ class TestCompatibility(AioTestBase): yield request self._adhoc_handlers.set_adhoc_handler(echo_unary_stream) - call = self._async_channel.unary_stream(_ADHOC_METHOD)(_REQUEST) + call = self._async_channel.unary_stream(_common.ADHOC_METHOD)(_REQUEST) async for response in call: self.assertEqual(_REQUEST, response) @@ -303,7 +288,7 @@ class TestCompatibility(AioTestBase): raise RuntimeError('Test') self._adhoc_handlers.set_adhoc_handler(error_unary_stream) - call = self._async_channel.unary_stream(_ADHOC_METHOD)(_REQUEST) + call = self._async_channel.unary_stream(_common.ADHOC_METHOD)(_REQUEST) with self.assertRaises(aio.AioRpcError) as exception_context: async for response in call: self.assertEqual(_REQUEST, response) @@ -320,8 +305,8 @@ class TestCompatibility(AioTestBase): self._adhoc_handlers.set_adhoc_handler(echo_stream_unary) request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES) - response = await self._async_channel.stream_unary(_ADHOC_METHOD)( - request_iterator) + response = await self._async_channel.stream_unary(_common.ADHOC_METHOD + )(request_iterator) self.assertEqual(_REQUEST, response) async def test_sync_stream_unary_error(self): @@ -335,8 +320,8 @@ class TestCompatibility(AioTestBase): self._adhoc_handlers.set_adhoc_handler(echo_stream_unary) request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES) with self.assertRaises(aio.AioRpcError) as exception_context: - response = await self._async_channel.stream_unary(_ADHOC_METHOD)( - request_iterator) + response = await self._async_channel.stream_unary( + _common.ADHOC_METHOD)(request_iterator) self.assertEqual(grpc.StatusCode.UNKNOWN, exception_context.exception.code()) @@ -350,8 +335,8 @@ class TestCompatibility(AioTestBase): self._adhoc_handlers.set_adhoc_handler(echo_stream_stream) request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES) - call = self._async_channel.stream_stream(_ADHOC_METHOD)( - request_iterator) + call = self._async_channel.stream_stream( + _common.ADHOC_METHOD)(request_iterator) async for response in call: self.assertEqual(_REQUEST, response) @@ -366,8 +351,8 @@ class TestCompatibility(AioTestBase): self._adhoc_handlers.set_adhoc_handler(echo_stream_stream) request_iterator = iter([_REQUEST] * _NUM_STREAM_RESPONSES) - call = self._async_channel.stream_stream(_ADHOC_METHOD)( - request_iterator) + call = self._async_channel.stream_stream( + _common.ADHOC_METHOD)(request_iterator) with self.assertRaises(aio.AioRpcError) as exception_context: async for response in call: self.assertEqual(_REQUEST, response) diff --git a/src/python/grpcio_tests/tests_aio/unit/metadata_test.py b/src/python/grpcio_tests/tests_aio/unit/metadata_test.py index 2261446b3ea..8f8c39214c8 100644 --- a/src/python/grpcio_tests/tests_aio/unit/metadata_test.py +++ b/src/python/grpcio_tests/tests_aio/unit/metadata_test.py @@ -33,6 +33,7 @@ _TEST_GENERIC_HANDLER = '/test/TestGenericHandler' _TEST_UNARY_STREAM = '/test/TestUnaryStream' _TEST_STREAM_UNARY = '/test/TestStreamUnary' _TEST_STREAM_STREAM = '/test/TestStreamStream' +_TEST_INSPECT_CONTEXT = '/test/TestInspectContext' _REQUEST = b'\x00\x00\x00' _RESPONSE = b'\x01\x01\x01' @@ -75,6 +76,9 @@ _INVALID_METADATA_TEST_CASES = ( ), ) +_NON_OK_CODE = grpc.StatusCode.NOT_FOUND +_DETAILS = 'Test details!' + class _TestGenericHandlerForMethods(grpc.GenericRpcHandler): @@ -95,6 +99,8 @@ class _TestGenericHandlerForMethods(grpc.GenericRpcHandler): grpc.stream_unary_rpc_method_handler(self._test_stream_unary), _TEST_STREAM_STREAM: grpc.stream_stream_rpc_method_handler(self._test_stream_stream), + _TEST_INSPECT_CONTEXT: + grpc.unary_unary_rpc_method_handler(self._test_inspect_context), } @staticmethod @@ -153,6 +159,19 @@ class _TestGenericHandlerForMethods(grpc.GenericRpcHandler): yield _RESPONSE context.set_trailing_metadata(_TRAILING_METADATA) + @staticmethod + async def _test_inspect_context(request, context): + assert _REQUEST == request + context.set_code(_NON_OK_CODE) + context.set_details(_DETAILS) + context.set_trailing_metadata(_TRAILING_METADATA) + + # ensure that we can read back the data we set on the context + assert context.get_code() == _NON_OK_CODE + assert context.get_details() == _DETAILS + assert context.get_trailing_metadata() == _TRAILING_METADATA + return _RESPONSE + def service(self, handler_call_details): return self._routing_table.get(handler_call_details.method) @@ -291,6 +310,15 @@ class TestMetadata(AioTestBase): self.assertEqual(expected_sum, metadata_obj + aio.Metadata( ('third', '3'))) + async def test_inspect_context(self): + multicallable = self._client.unary_unary(_TEST_INSPECT_CONTEXT) + call = multicallable(_REQUEST) + with self.assertRaises(grpc.RpcError) as exc_data: + await call + + err = exc_data.exception + self.assertEqual(_NON_OK_CODE, err.code()) + if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) diff --git a/src/python/grpcio_tests/tests_aio/unit/server_time_remaining_test.py b/src/python/grpcio_tests/tests_aio/unit/server_time_remaining_test.py new file mode 100644 index 00000000000..0de87b532fb --- /dev/null +++ b/src/python/grpcio_tests/tests_aio/unit/server_time_remaining_test.py @@ -0,0 +1,70 @@ +# Copyright 2021 The gRPC Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Test the time_remaining() method of async ServicerContext.""" + +import asyncio +import logging +import unittest +import datetime + +import grpc +from grpc import aio + +from tests_aio.unit._common import ADHOC_METHOD, AdhocGenericHandler +from tests_aio.unit._test_base import AioTestBase + +_REQUEST = b'\x09\x05' +_REQUEST_TIMEOUT_S = datetime.timedelta(seconds=5).total_seconds() + + +class TestServerTimeRemaining(AioTestBase): + + async def setUp(self): + # Create async server + self._server = aio.server(options=(('grpc.so_reuseport', 0),)) + self._adhoc_handlers = AdhocGenericHandler() + self._server.add_generic_rpc_handlers((self._adhoc_handlers,)) + port = self._server.add_insecure_port('[::]:0') + address = 'localhost:%d' % port + await self._server.start() + # Create async channel + self._channel = aio.insecure_channel(address) + + async def tearDown(self): + await self._channel.close() + await self._server.stop(None) + + async def test_servicer_context_time_remaining(self): + seen_time_remaining = [] + + @grpc.unary_unary_rpc_method_handler + def log_time_remaining(request: bytes, + context: grpc.ServicerContext) -> bytes: + seen_time_remaining.append(context.time_remaining()) + return b"" + + # Check if the deadline propagates properly + self._adhoc_handlers.set_adhoc_handler(log_time_remaining) + await self._channel.unary_unary(ADHOC_METHOD)( + _REQUEST, timeout=_REQUEST_TIMEOUT_S) + self.assertGreater(seen_time_remaining[0], _REQUEST_TIMEOUT_S / 2) + # Check if there is no timeout, the time_remaining will be None + self._adhoc_handlers.set_adhoc_handler(log_time_remaining) + await self._channel.unary_unary(ADHOC_METHOD)(_REQUEST) + self.assertIsNone(seen_time_remaining[1]) + + +if __name__ == '__main__': + logging.basicConfig(level=logging.DEBUG) + unittest.main(verbosity=2) diff --git a/src/python/grpcio_tests/tests_py3_only/interop/BUILD.bazel b/src/python/grpcio_tests/tests_py3_only/interop/BUILD.bazel index 21d207119d0..506d744400f 100644 --- a/src/python/grpcio_tests/tests_py3_only/interop/BUILD.bazel +++ b/src/python/grpcio_tests/tests_py3_only/interop/BUILD.bazel @@ -8,5 +8,22 @@ py_binary( "//src/proto/grpc/testing:py_test_proto", "//src/proto/grpc/testing:test_py_pb2_grpc", "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz", + ], +) + +py_binary( + name = "xds_interop_server", + srcs = ["xds_interop_server.py"], + python_version = "PY3", + deps = [ + "//src/proto/grpc/testing:empty_py_pb2", + "//src/proto/grpc/testing:py_messages_proto", + "//src/proto/grpc/testing:py_test_proto", + "//src/proto/grpc/testing:test_py_pb2_grpc", + "//src/python/grpcio/grpc:grpcio", + "//src/python/grpcio_channelz/grpc_channelz/v1:grpc_channelz", + "//src/python/grpcio_health_checking/grpc_health/v1:grpc_health", + "//src/python/grpcio_reflection/grpc_reflection/v1alpha:grpc_reflection", ], ) diff --git a/src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.client b/src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.client new file mode 100644 index 00000000000..e8184e7bf49 --- /dev/null +++ b/src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.client @@ -0,0 +1,25 @@ +FROM phusion/baseimage:master@sha256:65ea10d5f757e5e86272625f8675d437dd83d8db64bdb429e2354d58f5462750 + +RUN apt-get update -y && \ + apt-get install -y \ + build-essential \ + clang \ + python3 \ + python3-dev + +WORKDIR /workdir + +RUN ln -s /usr/bin/python3 /usr/bin/python +RUN mkdir /artifacts + +COPY . . +RUN tools/bazel build -c dbg //src/python/grpcio_tests/tests_py3_only/interop:xds_interop_client +RUN cp -rL /workdir/bazel-bin/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client* /artifacts/ + +FROM phusion/baseimage:master@sha256:65ea10d5f757e5e86272625f8675d437dd83d8db64bdb429e2354d58f5462750 +COPY --from=0 /artifacts ./ + +RUN apt-get update -y && apt-get install -y python3 +RUN ln -s /usr/bin/python3 /usr/bin/python + +ENTRYPOINT ["/xds_interop_client"] diff --git a/src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.server b/src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.server new file mode 100644 index 00000000000..b7259bf995d --- /dev/null +++ b/src/python/grpcio_tests/tests_py3_only/interop/Dockerfile.server @@ -0,0 +1,25 @@ +FROM phusion/baseimage:master@sha256:65ea10d5f757e5e86272625f8675d437dd83d8db64bdb429e2354d58f5462750 + +RUN apt-get update -y && \ + apt-get install -y \ + build-essential \ + clang \ + python3 \ + python3-dev + +WORKDIR /workdir + +RUN ln -s /usr/bin/python3 /usr/bin/python +RUN mkdir /artifacts + +COPY . . +RUN tools/bazel build -c dbg //src/python/grpcio_tests/tests_py3_only/interop:xds_interop_server +RUN cp -rL /workdir/bazel-bin/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_server* /artifacts/ + +FROM phusion/baseimage:master@sha256:65ea10d5f757e5e86272625f8675d437dd83d8db64bdb429e2354d58f5462750 +COPY --from=0 /artifacts ./ + +RUN apt-get update -y && apt-get install -y python3 +RUN ln -s /usr/bin/python3 /usr/bin/python + +ENTRYPOINT ["/xds_interop_server"] diff --git a/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py b/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py index 072b4d5a8fd..e71be526bd8 100644 --- a/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py +++ b/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_client.py @@ -27,6 +27,7 @@ import collections from concurrent import futures import grpc +from grpc_channelz.v1 import channelz from src.proto.grpc.testing import test_pb2 from src.proto.grpc.testing import test_pb2_grpc @@ -180,7 +181,7 @@ def _start_rpc(method: str, metadata: Sequence[Tuple[str, str]], request_id: int, stub: test_pb2_grpc.TestServiceStub, timeout: float, futures: Mapping[int, Tuple[grpc.Future, str]]) -> None: - logger.info(f"Sending {method} request to backend: {request_id}") + logger.debug(f"Sending {method} request to backend: {request_id}") if method == "UnaryCall": future = stub.UnaryCall.future(messages_pb2.SimpleRequest(), metadata=metadata, @@ -223,9 +224,9 @@ def _on_rpc_done(rpc_id: int, future: grpc.Future, method: str, _global_rpcs_failed[method] += 1 if print_response: if future.code() == grpc.StatusCode.OK: - logger.info("Successful response.") + logger.debug("Successful response.") else: - logger.info(f"RPC failed: {call}") + logger.debug(f"RPC failed: {call}") with _global_lock: for watcher in _watchers: watcher.on_rpc_complete(rpc_id, hostname, method) @@ -257,9 +258,9 @@ class _ChannelConfiguration: When accessing any of its members, the lock member should be held. """ - def __init__(self, method: str, metadata: Sequence[Tuple[str, - str]], qps: int, - server: str, rpc_timeout_sec: int, print_response: bool): + def __init__(self, method: str, metadata: Sequence[Tuple[str, str]], + qps: int, server: str, rpc_timeout_sec: int, + print_response: bool, secure_mode: bool): # condition is signalled when a change is made to the config. self.condition = threading.Condition() @@ -269,13 +270,21 @@ class _ChannelConfiguration: self.server = server self.rpc_timeout_sec = rpc_timeout_sec self.print_response = print_response + self.secure_mode = secure_mode def _run_single_channel(config: _ChannelConfiguration) -> None: global _global_rpc_id # pylint: disable=global-statement with config.condition: server = config.server - with grpc.insecure_channel(server) as channel: + channel = None + if config.secure_mode: + fallback_creds = grpc.experimental.insecure_channel_credentials() + channel_creds = grpc.xds_channel_credentials(fallback_creds) + channel = grpc.secure_channel(server, channel_creds) + else: + channel = grpc.insecure_channel(server) + with channel: stub = test_pb2_grpc.TestServiceStub(channel) futures: Dict[int, Tuple[grpc.Future, str]] = {} while not _stop_event.is_set(): @@ -382,7 +391,7 @@ def _run(args: argparse.Namespace, methods: Sequence[str], qps = 0 channel_config = _ChannelConfiguration( method, per_method_metadata.get(method, []), qps, args.server, - args.rpc_timeout_sec, args.print_response) + args.rpc_timeout_sec, args.print_response, args.secure_mode) channel_configs[method] = channel_config method_handles.append(_MethodHandle(args.num_channels, channel_config)) _global_server = grpc.server(futures.ThreadPoolExecutor()) @@ -392,6 +401,7 @@ def _run(args: argparse.Namespace, methods: Sequence[str], test_pb2_grpc.add_XdsUpdateClientConfigureServiceServicer_to_server( _XdsUpdateClientConfigureServicer(channel_configs, args.qps), _global_server) + channelz.add_channelz_servicer(_global_server) _global_server.start() _global_server.wait_for_termination() for method_handle in method_handles: @@ -420,6 +430,15 @@ def parse_rpc_arg(rpc_arg: str) -> Sequence[str]: return methods +def bool_arg(arg: str) -> bool: + if arg.lower() in ("true", "yes", "y"): + return True + elif arg.lower() in ("false", "no", "n"): + return False + else: + raise argparse.ArgumentTypeError(f"Could not parse '{arg}' as a bool.") + + if __name__ == "__main__": parser = argparse.ArgumentParser( description='Run Python XDS interop client.') @@ -429,8 +448,8 @@ if __name__ == "__main__": type=int, help="The number of channels from which to send requests.") parser.add_argument("--print_response", - default=False, - action="store_true", + default="False", + type=bool_arg, help="Write RPC response to STDOUT.") parser.add_argument( "--qps", @@ -449,6 +468,11 @@ if __name__ == "__main__": default=50052, type=int, help="The port on which to expose the peer distribution stats service.") + parser.add_argument( + "--secure_mode", + default="False", + type=bool_arg, + help="If specified, uses xDS credentials to connect to the server.") parser.add_argument('--verbose', help='verbose log output', default=False, diff --git a/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_server.py b/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_server.py new file mode 100644 index 00000000000..b0901b2070a --- /dev/null +++ b/src/python/grpcio_tests/tests_py3_only/interop/xds_interop_server.py @@ -0,0 +1,178 @@ +# Copyright 2021 The gRPC authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import logging +import signal +import threading +import time +import socket +import sys + +from typing import DefaultDict, Dict, List, Mapping, Set, Sequence, Tuple +import collections + +from concurrent import futures + +import grpc +from grpc_channelz.v1 import channelz +from grpc_channelz.v1 import channelz_pb2 +from grpc_health.v1 import health_pb2, health_pb2_grpc +from grpc_health.v1 import health as grpc_health +from grpc_reflection.v1alpha import reflection + +from src.proto.grpc.testing import test_pb2 +from src.proto.grpc.testing import test_pb2_grpc +from src.proto.grpc.testing import messages_pb2 +from src.proto.grpc.testing import empty_pb2 + +# NOTE: This interop server is not fully compatible with all xDS interop tests. +# It currently only implements enough functionality to pass the xDS security +# tests. + +_LISTEN_HOST = "[::]" + +_THREAD_POOL_SIZE = 256 + +logger = logging.getLogger() +console_handler = logging.StreamHandler() +formatter = logging.Formatter(fmt='%(asctime)s: %(levelname)-8s %(message)s') +console_handler.setFormatter(formatter) +logger.addHandler(console_handler) + + +class TestService(test_pb2_grpc.TestServiceServicer): + + def __init__(self, server_id, hostname): + self._server_id = server_id + self._hostname = hostname + + def EmptyCall(self, _: empty_pb2.Empty, + context: grpc.ServicerContext) -> empty_pb2.Empty: + return empty_pb2.Empty() + + def UnaryCall(self, request: messages_pb2.SimpleRequest, + context: grpc.ServicerContext) -> messages_pb2.SimpleResponse: + response = messages_pb2.SimpleResponse() + response.server_id = self._server_id + response.hostname = self._hostname + return response + + +def _configure_maintenance_server(server: grpc.Server, + maintenance_port: int) -> None: + channelz.add_channelz_servicer(server) + listen_address = f"{_LISTEN_HOST}:{maintenance_port}" + server.add_insecure_port(listen_address) + health_servicer = grpc_health.HealthServicer( + experimental_non_blocking=True, + experimental_thread_pool=futures.ThreadPoolExecutor( + max_workers=_THREAD_POOL_SIZE)) + + health_pb2_grpc.add_HealthServicer_to_server(health_servicer, server) + SERVICE_NAMES = ( + test_pb2.DESCRIPTOR.services_by_name["TestService"].full_name, + health_pb2.DESCRIPTOR.services_by_name["Health"].full_name, + channelz_pb2.DESCRIPTOR.services_by_name["Channelz"].full_name, + reflection.SERVICE_NAME, + ) + for service in SERVICE_NAMES: + health_servicer.set(service, health_pb2.HealthCheckResponse.SERVING) + reflection.enable_server_reflection(SERVICE_NAMES, server) + + +def _configure_test_server(server: grpc.Server, port: int, secure_mode: bool, + server_id: str) -> None: + test_pb2_grpc.add_TestServiceServicer_to_server( + TestService(server_id, socket.gethostname()), server) + listen_address = f"{_LISTEN_HOST}:{port}" + if not secure_mode: + server.add_insecure_port(listen_address) + else: + logger.info("Running with xDS Server credentials") + server_fallback_creds = grpc.insecure_server_credentials() + server_creds = grpc.xds_server_credentials(server_fallback_creds) + server.add_secure_port(listen_address, server_creds) + + +def _run(port: int, maintenance_port: int, secure_mode: bool, + server_id: str) -> None: + if port == maintenance_port: + server = grpc.server( + futures.ThreadPoolExecutor(max_workers=_THREAD_POOL_SIZE)) + _configure_test_server(server, port, secure_mode, server_id) + _configure_maintenance_server(server, maintenance_port) + server.start() + logger.info("Test server listening on port %d", port) + logger.info("Maintenance server listening on port %d", maintenance_port) + server.wait_for_termination() + else: + test_server = grpc.server( + futures.ThreadPoolExecutor(max_workers=_THREAD_POOL_SIZE), + xds=secure_mode) + _configure_test_server(test_server, port, secure_mode, server_id) + test_server.start() + logger.info("Test server listening on port %d", port) + maintenance_server = grpc.server( + futures.ThreadPoolExecutor(max_workers=_THREAD_POOL_SIZE)) + _configure_maintenance_server(maintenance_server, maintenance_port) + maintenance_server.start() + logger.info("Maintenance server listening on port %d", maintenance_port) + test_server.wait_for_termination() + maintenance_server.wait_for_termination() + + +def bool_arg(arg: str) -> bool: + if arg.lower() in ("true", "yes", "y"): + return True + elif arg.lower() in ("false", "no", "n"): + return False + else: + raise argparse.ArgumentTypeError(f"Could not parse '{arg}' as a bool.") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Run Python xDS interop server.") + parser.add_argument("--port", + type=int, + default=8080, + help="Port for test server.") + parser.add_argument("--maintenance_port", + type=int, + default=8080, + help="Port for servers besides test server.") + parser.add_argument( + "--secure_mode", + type=bool_arg, + default="False", + help="If specified, uses xDS to retrieve server credentials.") + parser.add_argument("--server_id", + type=str, + default="python_server", + help="The server ID to return in responses..") + parser.add_argument('--verbose', + help='verbose log output', + default=False, + action='store_true') + args = parser.parse_args() + if args.verbose: + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(logging.INFO) + if args.secure_mode and args.port == args.maintenance_port: + raise ValueError( + "--port and --maintenance_port must not be the same when --secure_mode is set." + ) + _run(args.port, args.maintenance_port, args.secure_mode, args.server_id) diff --git a/src/ruby/README.md b/src/ruby/README.md index 8187d7f3b5c..a98f6f034c7 100644 --- a/src/ruby/README.md +++ b/src/ruby/README.md @@ -18,6 +18,11 @@ INSTALLATION gem install grpc ``` +If using a Gemfile and you wish to pull from a git repository or GitHub, make sure to tell bundler to retrieve submodules: +``` +gem 'grpc', github: 'grpc/grpc', submodules: true +``` + BUILD FROM SOURCE --------------------- - Clone this repository diff --git a/src/ruby/bin/math_services_pb.rb b/src/ruby/bin/math_services_pb.rb index 961117ccfaf..c4b908fd0e7 100644 --- a/src/ruby/bin/math_services_pb.rb +++ b/src/ruby/bin/math_services_pb.rb @@ -23,7 +23,7 @@ module Math module Math class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode diff --git a/src/ruby/end2end/grpc_class_init_client.rb b/src/ruby/end2end/grpc_class_init_client.rb index c4a54374b65..44fb031725c 100755 --- a/src/ruby/end2end/grpc_class_init_client.rb +++ b/src/ruby/end2end/grpc_class_init_client.rb @@ -80,6 +80,31 @@ def get_test_proc(grpc_class) return proc do GRPC::Core::ChannelCredentials.new end + when 'xds_channel_credentials' + return proc do + GRPC::Core::XdsChannelCredentials.new(GRPC::Core::ChannelCredentials.new) + end + when 'server_credentials' + return proc do + test_root = File.join(File.dirname(__FILE__), '..', 'spec', 'testdata') + files = ['ca.pem', 'server1.key', 'server1.pem'] + creds = files.map { |f| File.open(File.join(test_root, f)).read } + GRPC::Core::ServerCredentials.new( + creds[0], + [{ private_key: creds[1], cert_chain: creds[2] }], + true) + end + when 'xds_server_credentials' + return proc do + test_root = File.join(File.dirname(__FILE__), '..', 'spec', 'testdata') + files = ['ca.pem', 'server1.key', 'server1.pem'] + creds = files.map { |f| File.open(File.join(test_root, f)).read } + GRPC::Core::XdsServerCredentials.new( + GRPC::Core::ServerCredentials.new( + creds[0], + [{ private_key: creds[1], cert_chain: creds[2] }], + true)) + end when 'call_credentials' return proc do GRPC::Core::CallCredentials.new(proc { |noop| noop }) diff --git a/src/ruby/end2end/grpc_class_init_test.rb b/src/ruby/end2end/grpc_class_init_test.rb index bbcfa5cd27f..7144f65115b 100755 --- a/src/ruby/end2end/grpc_class_init_test.rb +++ b/src/ruby/end2end/grpc_class_init_test.rb @@ -20,6 +20,9 @@ def main native_grpc_classes = %w( channel server channel_credentials + xds_channel_credentials + server_credentials + xds_server_credentials call_credentials compression_options ) diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb index 2d999369238..bb05b53d241 100644 --- a/src/ruby/ext/grpc/extconf.rb +++ b/src/ruby/ext/grpc/extconf.rb @@ -45,8 +45,16 @@ if RUBY_PLATFORM =~ /darwin/ ENV['EMBED_OPENSSL'] = 'true' ENV['EMBED_ZLIB'] = 'true' ENV['EMBED_CARES'] = 'true' + ENV['ARCH_FLAGS'] = RbConfig::CONFIG['ARCH_FLAG'] -ENV['ARCH_FLAGS'] = '-arch i386 -arch x86_64' if RUBY_PLATFORM =~ /darwin/ +if RUBY_PLATFORM =~ /darwin/ + if RUBY_PLATFORM =~ /arm64/ + ENV['ARCH_FLAGS'] = '-arch arm64' + else + ENV['ARCH_FLAGS'] = '-arch i386 -arch x86_64' + end +end + ENV['CPPFLAGS'] = '-DGPR_BACKWARDS_COMPATIBILITY_MODE' output_dir = File.expand_path(RbConfig::CONFIG['topdir']) diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c index 73d8b20a312..6a665b2cc7f 100644 --- a/src/ruby/ext/grpc/rb_channel.c +++ b/src/ruby/ext/grpc/rb_channel.c @@ -34,6 +34,7 @@ #include "rb_completion_queue.h" #include "rb_grpc.h" #include "rb_server.h" +#include "rb_xds_channel_credentials.h" /* id_channel is the name of the hidden ivar that preserves a reference to the * channel on a call, so that calls are not GCed before their channel. */ @@ -242,7 +243,15 @@ static VALUE grpc_rb_channel_init(int argc, VALUE* argv, VALUE self) { ch = grpc_insecure_channel_create(target_chars, &args, NULL); } else { wrapper->credentials = credentials; - creds = grpc_rb_get_wrapped_channel_credentials(credentials); + if (grpc_rb_is_channel_credentials(credentials)) { + creds = grpc_rb_get_wrapped_channel_credentials(credentials); + } else if (grpc_rb_is_xds_channel_credentials(credentials)) { + creds = grpc_rb_get_wrapped_xds_channel_credentials(credentials); + } else { + rb_raise(rb_eTypeError, + "bad creds, want ChannelCredentials or XdsChannelCredentials"); + return Qnil; + } ch = grpc_secure_channel_create(creds, target_chars, &args, NULL); } diff --git a/src/ruby/ext/grpc/rb_channel_credentials.c b/src/ruby/ext/grpc/rb_channel_credentials.c index 60f1605f2c1..d65d049559e 100644 --- a/src/ruby/ext/grpc/rb_channel_credentials.c +++ b/src/ruby/ext/grpc/rb_channel_credentials.c @@ -180,7 +180,11 @@ static VALUE grpc_rb_channel_credentials_init(int argc, VALUE* argv, NULL, NULL); } if (creds == NULL) { - rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); + rb_raise(rb_eRuntimeError, + "the call to grpc_ssl_credentials_create() failed, could not " + "create a credentials, see " + "https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md for " + "debugging tips"); return Qnil; } wrapper->wrapped = creds; @@ -270,7 +274,13 @@ void Init_grpc_channel_credentials() { /* Gets the wrapped grpc_channel_credentials from the ruby wrapper */ grpc_channel_credentials* grpc_rb_get_wrapped_channel_credentials(VALUE v) { grpc_rb_channel_credentials* wrapper = NULL; + Check_TypedStruct(v, &grpc_rb_channel_credentials_data_type); TypedData_Get_Struct(v, grpc_rb_channel_credentials, &grpc_rb_channel_credentials_data_type, wrapper); return wrapper->wrapped; } + +/* Check if v is kind of ChannelCredentials */ +bool grpc_rb_is_channel_credentials(VALUE v) { + return rb_typeddata_is_kind_of(v, &grpc_rb_channel_credentials_data_type); +} diff --git a/src/ruby/ext/grpc/rb_channel_credentials.h b/src/ruby/ext/grpc/rb_channel_credentials.h index 422e746fe22..56856df2bc7 100644 --- a/src/ruby/ext/grpc/rb_channel_credentials.h +++ b/src/ruby/ext/grpc/rb_channel_credentials.h @@ -20,6 +20,7 @@ #define GRPC_RB_CREDENTIALS_H_ #include +#include #include @@ -29,4 +30,7 @@ void Init_grpc_channel_credentials(); /* Gets the wrapped credentials from the ruby wrapper */ grpc_channel_credentials* grpc_rb_get_wrapped_channel_credentials(VALUE v); +/* Check if v is kind of ChannelCredentials */ +bool grpc_rb_is_channel_credentials(VALUE v); + #endif /* GRPC_RB_CREDENTIALS_H_ */ diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index 77cabfca814..8b230ea2764 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -40,6 +40,8 @@ #include "rb_loader.h" #include "rb_server.h" #include "rb_server_credentials.h" +#include "rb_xds_channel_credentials.h" +#include "rb_xds_server_credentials.h" static VALUE grpc_rb_cTimeVal = Qnil; @@ -321,8 +323,10 @@ void Init_grpc_c() { Init_grpc_call(); Init_grpc_call_credentials(); Init_grpc_channel_credentials(); + Init_grpc_xds_channel_credentials(); Init_grpc_server(); Init_grpc_server_credentials(); + Init_grpc_xds_server_credentials(); Init_grpc_time_consts(); Init_grpc_compression_options(); } diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c index 5d5d3e01d8a..8d799baa72d 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c @@ -98,6 +98,7 @@ grpc_resource_quota_ref_type grpc_resource_quota_ref_import; grpc_resource_quota_unref_type grpc_resource_quota_unref_import; grpc_resource_quota_resize_type grpc_resource_quota_resize_import; grpc_resource_quota_set_max_threads_type grpc_resource_quota_set_max_threads_import; +grpc_dump_xds_configs_type grpc_dump_xds_configs_import; grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; grpc_channelz_get_top_channels_type grpc_channelz_get_top_channels_import; grpc_channelz_get_servers_type grpc_channelz_get_servers_import; @@ -382,6 +383,7 @@ void grpc_rb_load_imports(HMODULE library) { grpc_resource_quota_unref_import = (grpc_resource_quota_unref_type) GetProcAddress(library, "grpc_resource_quota_unref"); grpc_resource_quota_resize_import = (grpc_resource_quota_resize_type) GetProcAddress(library, "grpc_resource_quota_resize"); grpc_resource_quota_set_max_threads_import = (grpc_resource_quota_set_max_threads_type) GetProcAddress(library, "grpc_resource_quota_set_max_threads"); + grpc_dump_xds_configs_import = (grpc_dump_xds_configs_type) GetProcAddress(library, "grpc_dump_xds_configs"); grpc_resource_quota_arg_vtable_import = (grpc_resource_quota_arg_vtable_type) GetProcAddress(library, "grpc_resource_quota_arg_vtable"); grpc_channelz_get_top_channels_import = (grpc_channelz_get_top_channels_type) GetProcAddress(library, "grpc_channelz_get_top_channels"); grpc_channelz_get_servers_import = (grpc_channelz_get_servers_type) GetProcAddress(library, "grpc_channelz_get_servers"); diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h index c526b3a7c03..44033ce471a 100644 --- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h +++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h @@ -215,7 +215,7 @@ extern grpc_server_create_type grpc_server_create_import; typedef void(*grpc_server_register_completion_queue_type)(grpc_server* server, grpc_completion_queue* cq, void* reserved); extern grpc_server_register_completion_queue_type grpc_server_register_completion_queue_import; #define grpc_server_register_completion_queue grpc_server_register_completion_queue_import -typedef grpc_server_config_fetcher*(*grpc_server_config_fetcher_xds_create_type)(); +typedef grpc_server_config_fetcher*(*grpc_server_config_fetcher_xds_create_type)(grpc_server_xds_status_notifier notifier, const grpc_channel_args* args); extern grpc_server_config_fetcher_xds_create_type grpc_server_config_fetcher_xds_create_import; #define grpc_server_config_fetcher_xds_create grpc_server_config_fetcher_xds_create_import typedef void(*grpc_server_config_fetcher_destroy_type)(grpc_server_config_fetcher* config_fetcher); @@ -269,6 +269,9 @@ extern grpc_resource_quota_resize_type grpc_resource_quota_resize_import; typedef void(*grpc_resource_quota_set_max_threads_type)(grpc_resource_quota* resource_quota, int new_max_threads); extern grpc_resource_quota_set_max_threads_type grpc_resource_quota_set_max_threads_import; #define grpc_resource_quota_set_max_threads grpc_resource_quota_set_max_threads_import +typedef grpc_slice(*grpc_dump_xds_configs_type)(); +extern grpc_dump_xds_configs_type grpc_dump_xds_configs_import; +#define grpc_dump_xds_configs grpc_dump_xds_configs_import typedef const grpc_arg_pointer_vtable*(*grpc_resource_quota_arg_vtable_type)(void); extern grpc_resource_quota_arg_vtable_type grpc_resource_quota_arg_vtable_import; #define grpc_resource_quota_arg_vtable grpc_resource_quota_arg_vtable_import diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c index 4396de1c335..31434a3706c 100644 --- a/src/ruby/ext/grpc/rb_server.c +++ b/src/ruby/ext/grpc/rb_server.c @@ -31,6 +31,7 @@ #include "rb_completion_queue.h" #include "rb_grpc.h" #include "rb_server_credentials.h" +#include "rb_xds_server_credentials.h" /* grpc_rb_cServer is the ruby class that proxies grpc_server. */ static VALUE grpc_rb_cServer = Qnil; @@ -326,7 +327,18 @@ static VALUE grpc_rb_server_add_http2_port(VALUE self, VALUE port, StringValueCStr(port)); } } else { - creds = grpc_rb_get_wrapped_server_credentials(rb_creds); + // TODO: create a common parent class for all server-side credentials, + // then we can have a single method to retrieve the underlying + // grpc_server_credentials object, and avoid the need for this reflection + if (grpc_rb_is_server_credentials(rb_creds)) { + creds = grpc_rb_get_wrapped_server_credentials(rb_creds); + } else if (grpc_rb_is_xds_server_credentials(rb_creds)) { + creds = grpc_rb_get_wrapped_xds_server_credentials(rb_creds); + } else { + rb_raise(rb_eTypeError, + "failed to create server because credentials parameter has an " + "invalid type, want ServerCredentials or XdsServerCredentials"); + } recvd_port = grpc_server_add_secure_http2_port( s->wrapped, StringValueCStr(port), creds); if (recvd_port == 0) { diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c index 368d5c2fd81..7c68cfd034f 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.c +++ b/src/ruby/ext/grpc/rb_server_credentials.c @@ -42,7 +42,7 @@ typedef struct grpc_rb_server_credentials { } grpc_rb_server_credentials; /* Destroys the server credentials instances. */ -static void grpc_rb_server_credentials_free(void* p) { +static void grpc_rb_server_credentials_free_internal(void* p) { grpc_rb_server_credentials* wrapper = NULL; if (p == NULL) { return; @@ -59,6 +59,12 @@ static void grpc_rb_server_credentials_free(void* p) { xfree(p); } +/* Destroys the server credentials instances. */ +static void grpc_rb_server_credentials_free(void* p) { + grpc_rb_server_credentials_free_internal(p); + grpc_ruby_shutdown(); +} + /* Protects the mark object from GC */ static void grpc_rb_server_credentials_mark(void* p) { grpc_rb_server_credentials* wrapper = NULL; @@ -87,9 +93,9 @@ static const rb_data_type_t grpc_rb_server_credentials_data_type = { }; /* Allocates ServerCredential instances. - Provides safe initial defaults for the instance fields. */ static VALUE grpc_rb_server_credentials_alloc(VALUE cls) { + grpc_ruby_init(); grpc_rb_server_credentials* wrapper = ALLOC(grpc_rb_server_credentials); wrapper->wrapped = NULL; wrapper->mark = Qnil; @@ -202,7 +208,11 @@ static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs, } xfree(key_cert_pairs); if (creds == NULL) { - rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why"); + rb_raise(rb_eRuntimeError, + "the call to grpc_ssl_server_credentials_create_ex() failed, " + "could not create a credentials, see " + "https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md for " + "debugging tips"); return Qnil; } wrapper->wrapped = creds; @@ -237,7 +247,13 @@ void Init_grpc_server_credentials() { /* Gets the wrapped grpc_server_credentials from the ruby wrapper */ grpc_server_credentials* grpc_rb_get_wrapped_server_credentials(VALUE v) { grpc_rb_server_credentials* wrapper = NULL; + Check_TypedStruct(v, &grpc_rb_server_credentials_data_type); TypedData_Get_Struct(v, grpc_rb_server_credentials, &grpc_rb_server_credentials_data_type, wrapper); return wrapper->wrapped; } + +/* Check if v is kind of ServerCredentials */ +bool grpc_rb_is_server_credentials(VALUE v) { + return rb_typeddata_is_kind_of(v, &grpc_rb_server_credentials_data_type); +} diff --git a/src/ruby/ext/grpc/rb_server_credentials.h b/src/ruby/ext/grpc/rb_server_credentials.h index 7df94cf275a..35c2ef0a027 100644 --- a/src/ruby/ext/grpc/rb_server_credentials.h +++ b/src/ruby/ext/grpc/rb_server_credentials.h @@ -20,6 +20,7 @@ #define GRPC_RB_SERVER_CREDENTIALS_H_ #include +#include #include @@ -29,4 +30,7 @@ void Init_grpc_server_credentials(); /* Gets the wrapped server_credentials from the ruby wrapper */ grpc_server_credentials* grpc_rb_get_wrapped_server_credentials(VALUE v); +/* Check if v is kind of ServerCredentials */ +bool grpc_rb_is_server_credentials(VALUE v); + #endif /* GRPC_RB_SERVER_CREDENTIALS_H_ */ diff --git a/src/ruby/ext/grpc/rb_xds_channel_credentials.c b/src/ruby/ext/grpc/rb_xds_channel_credentials.c new file mode 100644 index 00000000000..b65a3e88c96 --- /dev/null +++ b/src/ruby/ext/grpc/rb_xds_channel_credentials.c @@ -0,0 +1,215 @@ +/* + * + * Copyright 2021 gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "rb_call_credentials.h" +#include "rb_channel_credentials.h" +#include "rb_grpc.h" +#include "rb_grpc_imports.generated.h" +#include "rb_xds_channel_credentials.h" + +/* grpc_rb_cXdsChannelCredentials is the ruby class that proxies + grpc_channel_credentials. */ +static VALUE grpc_rb_cXdsChannelCredentials = Qnil; + +/* grpc_rb_xds_channel_credentials wraps a grpc_channel_credentials. It + * provides a mark object that is used to hold references to any objects used to + * create the credentials. */ +typedef struct grpc_rb_xds_channel_credentials { + /* Holder of ruby objects involved in constructing the credentials */ + VALUE mark; + + /* The actual credentials */ + grpc_channel_credentials* wrapped; +} grpc_rb_xds_channel_credentials; + +static void grpc_rb_xds_channel_credentials_free_internal(void* p) { + grpc_rb_xds_channel_credentials* wrapper = NULL; + if (p == NULL) { + return; + }; + wrapper = (grpc_rb_xds_channel_credentials*)p; + grpc_channel_credentials_release(wrapper->wrapped); + wrapper->wrapped = NULL; + + xfree(p); +} + +/* Destroys the credentials instances. */ +static void grpc_rb_xds_channel_credentials_free(void* p) { + grpc_rb_xds_channel_credentials_free_internal(p); + grpc_ruby_shutdown(); +} + +/* Protects the mark object from GC */ +static void grpc_rb_xds_channel_credentials_mark(void* p) { + grpc_rb_xds_channel_credentials* wrapper = NULL; + if (p == NULL) { + return; + } + wrapper = (grpc_rb_xds_channel_credentials*)p; + + if (wrapper->mark != Qnil) { + rb_gc_mark(wrapper->mark); + } +} + +static rb_data_type_t grpc_rb_xds_channel_credentials_data_type = { + "grpc_xds_channel_credentials", + {grpc_rb_xds_channel_credentials_mark, grpc_rb_xds_channel_credentials_free, + GRPC_RB_MEMSIZE_UNAVAILABLE, NULL}, + NULL, + NULL, +#ifdef RUBY_TYPED_FREE_IMMEDIATELY + RUBY_TYPED_FREE_IMMEDIATELY +#endif +}; + +/* Allocates ChannelCredential instances. + Provides safe initial defaults for the instance fields. */ +static VALUE grpc_rb_xds_channel_credentials_alloc(VALUE cls) { + grpc_ruby_init(); + grpc_rb_xds_channel_credentials* wrapper = + ALLOC(grpc_rb_xds_channel_credentials); + wrapper->wrapped = NULL; + wrapper->mark = Qnil; + return TypedData_Wrap_Struct(cls, &grpc_rb_xds_channel_credentials_data_type, + wrapper); +} + +/* Creates a wrapping object for a given channel credentials. This should only + * be called with grpc_channel_credentials objects that are not already + * associated with any Ruby object. */ +VALUE grpc_rb_xds_wrap_channel_credentials(grpc_channel_credentials* c, + VALUE mark) { + grpc_rb_xds_channel_credentials* wrapper; + if (c == NULL) { + return Qnil; + } + VALUE rb_wrapper = + grpc_rb_xds_channel_credentials_alloc(grpc_rb_cXdsChannelCredentials); + TypedData_Get_Struct(rb_wrapper, grpc_rb_xds_channel_credentials, + &grpc_rb_xds_channel_credentials_data_type, wrapper); + wrapper->wrapped = c; + wrapper->mark = mark; + return rb_wrapper; +} + +/* The attribute used on the mark object to hold the fallback creds. */ +static ID id_fallback_creds; + +/* + call-seq: + fallback_creds: (ChannelCredentials) fallback credentials to create + XDS credentials + Initializes Credential instances. */ +static VALUE grpc_rb_xds_channel_credentials_init(VALUE self, + VALUE fallback_creds) { + grpc_rb_xds_channel_credentials* wrapper = NULL; + grpc_channel_credentials* grpc_fallback_creds = + grpc_rb_get_wrapped_channel_credentials(fallback_creds); + grpc_channel_credentials* creds = + grpc_xds_credentials_create(grpc_fallback_creds); + if (creds == NULL) { + rb_raise(rb_eRuntimeError, + "the call to grpc_xds_credentials_create() failed, could not " + "create a credentials, , see " + "https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md for " + "debugging tips"); + return Qnil; + } + + TypedData_Get_Struct(self, grpc_rb_xds_channel_credentials, + &grpc_rb_xds_channel_credentials_data_type, wrapper); + wrapper->wrapped = creds; + + /* Add the input objects as hidden fields to preserve them. */ + rb_ivar_set(self, id_fallback_creds, fallback_creds); + + return self; +} + +// TODO: de-duplicate this code with the similar method in +// rb_channel_credentials.c, after putting ChannelCredentials and +// XdsChannelCredentials under a common parent class +static VALUE grpc_rb_xds_channel_credentials_compose(int argc, VALUE* argv, + VALUE self) { + grpc_channel_credentials* creds; + grpc_call_credentials* other; + grpc_channel_credentials* prev = NULL; + VALUE mark; + if (argc == 0) { + return self; + } + mark = rb_ary_new(); + rb_ary_push(mark, self); + creds = grpc_rb_get_wrapped_xds_channel_credentials(self); + for (int i = 0; i < argc; i++) { + rb_ary_push(mark, argv[i]); + other = grpc_rb_get_wrapped_call_credentials(argv[i]); + creds = grpc_composite_channel_credentials_create(creds, other, NULL); + if (prev != NULL) { + grpc_channel_credentials_release(prev); + } + prev = creds; + + if (creds == NULL) { + rb_raise(rb_eRuntimeError, + "Failed to compose channel and call credentials"); + } + } + return grpc_rb_xds_wrap_channel_credentials(creds, mark); +} + +void Init_grpc_xds_channel_credentials() { + grpc_rb_cXdsChannelCredentials = rb_define_class_under( + grpc_rb_mGrpcCore, "XdsChannelCredentials", rb_cObject); + + /* Allocates an object managed by the ruby runtime */ + rb_define_alloc_func(grpc_rb_cXdsChannelCredentials, + grpc_rb_xds_channel_credentials_alloc); + + /* Provides a ruby constructor and support for dup/clone. */ + rb_define_method(grpc_rb_cXdsChannelCredentials, "initialize", + grpc_rb_xds_channel_credentials_init, 1); + rb_define_method(grpc_rb_cXdsChannelCredentials, "initialize_copy", + grpc_rb_cannot_init_copy, 1); + rb_define_method(grpc_rb_cXdsChannelCredentials, "compose", + grpc_rb_xds_channel_credentials_compose, -1); + + id_fallback_creds = rb_intern("__fallback_creds"); +} + +/* Gets the wrapped grpc_channel_credentials from the ruby wrapper */ +grpc_channel_credentials* grpc_rb_get_wrapped_xds_channel_credentials(VALUE v) { + grpc_rb_xds_channel_credentials* wrapper = NULL; + Check_TypedStruct(v, &grpc_rb_xds_channel_credentials_data_type); + TypedData_Get_Struct(v, grpc_rb_xds_channel_credentials, + &grpc_rb_xds_channel_credentials_data_type, wrapper); + return wrapper->wrapped; +} + +bool grpc_rb_is_xds_channel_credentials(VALUE v) { + return rb_typeddata_is_kind_of(v, &grpc_rb_xds_channel_credentials_data_type); +} diff --git a/src/core/lib/iomgr/poller/eventmanager_interface.h b/src/ruby/ext/grpc/rb_xds_channel_credentials.h similarity index 50% rename from src/core/lib/iomgr/poller/eventmanager_interface.h rename to src/ruby/ext/grpc/rb_xds_channel_credentials.h index b4fbaeb7bbb..2dc655e0b96 100644 --- a/src/core/lib/iomgr/poller/eventmanager_interface.h +++ b/src/ruby/ext/grpc/rb_xds_channel_credentials.h @@ -1,6 +1,6 @@ /* * - * Copyright 2019 gRPC authors. + * Copyright 2021 gRPC authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,20 +16,20 @@ * */ -#ifndef GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_INTERFACE_H -#define GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_INTERFACE_H +#ifndef GRPC_RB_XDS_CHANNEL_CREDENTIALS_H_ +#define GRPC_RB_XDS_CHANNEL_CREDENTIALS_H_ -namespace grpc { -namespace experimental { +#include +#include +#include -class BaseEventManagerInterface { - public: - virtual ~BaseEventManagerInterface() {} -}; +/* Initializes the ruby ChannelCredentials class. */ +void Init_grpc_xds_channel_credentials(); -class EpollEventManagerInterface : public BaseEventManagerInterface {}; +/* Gets the wrapped credentials from the ruby wrapper */ +grpc_channel_credentials* grpc_rb_get_wrapped_xds_channel_credentials(VALUE v); -} // namespace experimental -} // namespace grpc +/* Check if v is kind of XdsChannelCredentials */ +bool grpc_rb_is_xds_channel_credentials(VALUE v); -#endif /* GRPC_CORE_LIB_IOMGR_POLLER_EVENTMANAGER_INTERFACE_H */ +#endif /* GRPC_RB_XDS_CHANNEL_CREDENTIALS_H_ */ diff --git a/src/ruby/ext/grpc/rb_xds_server_credentials.c b/src/ruby/ext/grpc/rb_xds_server_credentials.c new file mode 100644 index 00000000000..54f1ecbaab1 --- /dev/null +++ b/src/ruby/ext/grpc/rb_xds_server_credentials.c @@ -0,0 +1,169 @@ +/* + * + * Copyright 2021 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 "rb_xds_server_credentials.h" + +#include +#include +#include +#include + +#include "rb_grpc.h" +#include "rb_grpc_imports.generated.h" +#include "rb_server_credentials.h" + +/* grpc_rb_cXdsServerCredentials is the ruby class that proxies + grpc_server_credentials. */ +static VALUE grpc_rb_cXdsServerCredentials = Qnil; + +/* grpc_rb_xds_server_credentials wraps a grpc_server_credentials. It provides + a peer ruby object, 'mark' to hold references to objects involved in + constructing the server credentials. */ +typedef struct grpc_rb_xds_server_credentials { + /* Holder of ruby objects involved in constructing the server credentials */ + VALUE mark; + /* The actual server credentials */ + grpc_server_credentials* wrapped; +} grpc_rb_xds_server_credentials; + +/* Destroys the server credentials instances. */ +static void grpc_rb_xds_server_credentials_free_internal(void* p) { + grpc_rb_xds_server_credentials* wrapper = NULL; + if (p == NULL) { + return; + }; + wrapper = (grpc_rb_xds_server_credentials*)p; + + /* Delete the wrapped object if the mark object is Qnil, which indicates that + no other object is the actual owner. */ + if (wrapper->wrapped != NULL && wrapper->mark == Qnil) { + grpc_server_credentials_release(wrapper->wrapped); + wrapper->wrapped = NULL; + } + + xfree(p); +} + +/* Destroys the server credentials instances. */ +static void grpc_rb_xds_server_credentials_free(void* p) { + grpc_rb_xds_server_credentials_free_internal(p); + grpc_ruby_shutdown(); +} + +/* Protects the mark object from GC */ +static void grpc_rb_xds_server_credentials_mark(void* p) { + if (p == NULL) { + return; + } + grpc_rb_xds_server_credentials* wrapper = (grpc_rb_xds_server_credentials*)p; + + /* If it's not already cleaned up, mark the mark object */ + if (wrapper->mark != Qnil) { + rb_gc_mark(wrapper->mark); + } +} + +static const rb_data_type_t grpc_rb_xds_server_credentials_data_type = { + "grpc_xds_server_credentials", + {grpc_rb_xds_server_credentials_mark, grpc_rb_xds_server_credentials_free, + GRPC_RB_MEMSIZE_UNAVAILABLE, NULL}, + NULL, + NULL, +#ifdef RUBY_TYPED_FREE_IMMEDIATELY + RUBY_TYPED_FREE_IMMEDIATELY +#endif +}; + +/* Allocates ServerCredential instances. + Provides safe initial defaults for the instance fields. */ +static VALUE grpc_rb_xds_server_credentials_alloc(VALUE cls) { + grpc_ruby_init(); + grpc_rb_xds_server_credentials* wrapper = + ALLOC(grpc_rb_xds_server_credentials); + wrapper->wrapped = NULL; + wrapper->mark = Qnil; + return TypedData_Wrap_Struct(cls, &grpc_rb_xds_server_credentials_data_type, + wrapper); +} + +/* The attribute used on the mark object to preserve the fallback_creds. */ +static ID id_fallback_creds; + +/* + call-seq: + creds = ServerCredentials.new(fallback_creds) + fallback_creds: (ServerCredentials) fallback credentials to create + XDS credentials. + Initializes ServerCredential instances. */ +static VALUE grpc_rb_xds_server_credentials_init(VALUE self, + VALUE fallback_creds) { + grpc_rb_xds_server_credentials* wrapper = NULL; + grpc_server_credentials* creds = NULL; + + grpc_server_credentials* grpc_fallback_creds = + grpc_rb_get_wrapped_server_credentials(fallback_creds); + creds = grpc_xds_server_credentials_create(grpc_fallback_creds); + + if (creds == NULL) { + rb_raise(rb_eRuntimeError, + "the call to grpc_xds_server_credentials_create() failed, could " + "not create a credentials, see " + "https://github.com/grpc/grpc/blob/master/TROUBLESHOOTING.md for " + "debugging tips"); + return Qnil; + } + TypedData_Get_Struct(self, grpc_rb_xds_server_credentials, + &grpc_rb_xds_server_credentials_data_type, wrapper); + wrapper->wrapped = creds; + + /* Add the input objects as hidden fields to preserve them. */ + rb_ivar_set(self, id_fallback_creds, fallback_creds); + + return self; +} + +void Init_grpc_xds_server_credentials() { + grpc_rb_cXdsServerCredentials = rb_define_class_under( + grpc_rb_mGrpcCore, "XdsServerCredentials", rb_cObject); + + /* Allocates an object managed by the ruby runtime */ + rb_define_alloc_func(grpc_rb_cXdsServerCredentials, + grpc_rb_xds_server_credentials_alloc); + + /* Provides a ruby constructor and support for dup/clone. */ + rb_define_method(grpc_rb_cXdsServerCredentials, "initialize", + grpc_rb_xds_server_credentials_init, 1); + rb_define_method(grpc_rb_cXdsServerCredentials, "initialize_copy", + grpc_rb_cannot_init_copy, 1); + + id_fallback_creds = rb_intern("__fallback_creds"); +} + +/* Gets the wrapped grpc_server_credentials from the ruby wrapper */ +grpc_server_credentials* grpc_rb_get_wrapped_xds_server_credentials(VALUE v) { + grpc_rb_xds_server_credentials* wrapper = NULL; + Check_TypedStruct(v, &grpc_rb_xds_server_credentials_data_type); + TypedData_Get_Struct(v, grpc_rb_xds_server_credentials, + &grpc_rb_xds_server_credentials_data_type, wrapper); + return wrapper->wrapped; +} + +/* Check if v is kind of ServerCredentials */ +bool grpc_rb_is_xds_server_credentials(VALUE v) { + return rb_typeddata_is_kind_of(v, &grpc_rb_xds_server_credentials_data_type); +} diff --git a/src/ruby/ext/grpc/rb_xds_server_credentials.h b/src/ruby/ext/grpc/rb_xds_server_credentials.h new file mode 100644 index 00000000000..398ab47f1e4 --- /dev/null +++ b/src/ruby/ext/grpc/rb_xds_server_credentials.h @@ -0,0 +1,35 @@ +/* + * + * Copyright 2021 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_RB_XDS_SERVER_CREDENTIALS_H_ +#define GRPC_RB_XDS_SERVER_CREDENTIALS_H_ + +#include +#include +#include + +/* Initializes the ruby XdsServerCredentials class. */ +void Init_grpc_xds_server_credentials(); + +/* Gets the wrapped server_credentials from the ruby wrapper */ +grpc_server_credentials* grpc_rb_get_wrapped_xds_server_credentials(VALUE v); + +/* Check if v is kind of XdsServerCredentials */ +bool grpc_rb_is_xds_server_credentials(VALUE v); + +#endif /* GRPC_RB_XDS_SERVER_CREDENTIALS_H_ */ diff --git a/src/ruby/lib/grpc/generic/client_stub.rb b/src/ruby/lib/grpc/generic/client_stub.rb index 1884dcba246..0b86f0dca75 100644 --- a/src/ruby/lib/grpc/generic/client_stub.rb +++ b/src/ruby/lib/grpc/generic/client_stub.rb @@ -41,8 +41,10 @@ module GRPC channel_args['grpc.primary_user_agent'] += ' ' end channel_args['grpc.primary_user_agent'] += "grpc-ruby/#{VERSION}" - unless creds.is_a?(Core::ChannelCredentials) || creds.is_a?(Symbol) - fail(TypeError, '!ChannelCredentials or Symbol') + unless creds.is_a?(Core::ChannelCredentials) || + creds.is_a?(Core::XdsChannelCredentials) || + creds.is_a?(Symbol) + fail(TypeError, 'creds is not a ChannelCredentials, XdsChannelCredentials, or Symbol') end Core::Channel.new(host, channel_args, creds) end diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb index 2511f8cda6e..716062695af 100644 --- a/src/ruby/lib/grpc/version.rb +++ b/src/ruby/lib/grpc/version.rb @@ -14,5 +14,5 @@ # GRPC contains the General RPC module. module GRPC - VERSION = '1.37.0.dev' + VERSION = '1.38.0.dev' end diff --git a/src/ruby/pb/grpc/health/v1/health_services_pb.rb b/src/ruby/pb/grpc/health/v1/health_services_pb.rb index 351e7e150a5..9ddc0ac7a96 100644 --- a/src/ruby/pb/grpc/health/v1/health_services_pb.rb +++ b/src/ruby/pb/grpc/health/v1/health_services_pb.rb @@ -28,7 +28,7 @@ module Grpc module Health class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode diff --git a/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb index 19e6df7c724..55837a6dcff 100644 --- a/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb +++ b/src/ruby/pb/src/proto/grpc/testing/test_services_pb.rb @@ -29,7 +29,7 @@ module Grpc # performance with various types of payload. class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode @@ -70,7 +70,7 @@ module Grpc # that case. class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode @@ -86,7 +86,7 @@ module Grpc # A service used to control reconnect server. class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode @@ -102,7 +102,7 @@ module Grpc # A service used to obtain stats for verifying LB behavior. class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode @@ -120,7 +120,7 @@ module Grpc # A service to remotely control health status of an xDS test server. class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode @@ -136,7 +136,7 @@ module Grpc # A service to dynamically update the configuration of an xDS test client. class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode diff --git a/src/ruby/pb/test/xds_client.rb b/src/ruby/pb/test/xds_client.rb index 49d12b66cff..ed111b0d106 100755 --- a/src/ruby/pb/test/xds_client.rb +++ b/src/ruby/pb/test/xds_client.rb @@ -114,7 +114,7 @@ class ConfigureTarget < Grpc::Testing::XdsUpdateClientConfigureService::Service def configure(req, _call) metadata_to_send = {} - req['metadata'].each do |m| + req.metadata.each do |m| rpc = m.type if !metadata_to_send.key?(rpc) metadata_to_send[rpc] = {} @@ -283,9 +283,7 @@ def run_test_loop(stub, target_seconds_between_rpcs, fail_on_failed_rpcs) raise "Unsupported rpc #{rpc}" end rpc_stats_key = rpc.to_s - if metadata.key?('rpc-behavior') and - ((metadata['rpc-behavior'] == 'keep-open') or - (metadata['rpc-behavior'].start_with?('sleep'))) + if metadata.key?('rpc-behavior') or metadata.key?('fi_testcase') keep_open_threads << execute_rpc_in_thread(op, rpc_stats_key) else results[rpc] = execute_rpc(op, fail_on_failed_rpcs, rpc_stats_key) diff --git a/src/ruby/qps/src/proto/grpc/testing/benchmark_service_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/benchmark_service_services_pb.rb index 63e2d5d20fa..9439fe50293 100644 --- a/src/ruby/qps/src/proto/grpc/testing/benchmark_service_services_pb.rb +++ b/src/ruby/qps/src/proto/grpc/testing/benchmark_service_services_pb.rb @@ -26,7 +26,7 @@ module Grpc module BenchmarkService class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode diff --git a/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_services_pb.rb index 5e41cfeead1..5f50fb18fbf 100644 --- a/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_services_pb.rb +++ b/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_services_pb.rb @@ -26,7 +26,7 @@ module Grpc module ReportQpsScenarioService class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode diff --git a/src/ruby/qps/src/proto/grpc/testing/worker_service_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/worker_service_services_pb.rb index 049db477789..f5584c65d38 100644 --- a/src/ruby/qps/src/proto/grpc/testing/worker_service_services_pb.rb +++ b/src/ruby/qps/src/proto/grpc/testing/worker_service_services_pb.rb @@ -26,7 +26,7 @@ module Grpc module WorkerService class Service - include GRPC::GenericService + include ::GRPC::GenericService self.marshal_class_method = :encode self.unmarshal_class_method = :decode diff --git a/src/ruby/spec/channel_credentials_spec.rb b/src/ruby/spec/channel_credentials_spec.rb index b7453d051a7..af97e6b03df 100644 --- a/src/ruby/spec/channel_credentials_spec.rb +++ b/src/ruby/spec/channel_credentials_spec.rb @@ -60,6 +60,38 @@ describe GRPC::Core::ChannelCredentials do blk = proc { GRPC::Core::ChannelCredentials.new(nil, '', nil) } expect(&blk).to raise_error end + + it 'can be constructed with a fallback credential' do + blk = proc { + fallback = GRPC::Core::ChannelCredentials.new + GRPC::Core::XdsChannelCredentials.new(fallback) + } + expect(&blk).not_to raise_error + end + + it 'fails gracefully constructed with nil' do + blk = proc { + GRPC::Core::XdsChannelCredentials.new(nil) + } + expect(&blk).to raise_error TypeError, /expected grpc_channel_credentials/ + end + + it 'fails gracefully constructed with a non-C-extension object' do + blk = proc { + not_a_fallback = 100 + GRPC::Core::XdsChannelCredentials.new(not_a_fallback) + } + expect(&blk).to raise_error TypeError, /expected grpc_channel_credentials/ + end + + it 'fails gracefully constructed with a non-ChannelCredentials object' do + blk = proc { + not_a_fallback = GRPC::Core::Channel.new('dummy_host', nil, + :this_channel_is_insecure) + GRPC::Core::XdsChannelCredentials.new(not_a_fallback) + } + expect(&blk).to raise_error TypeError, /expected grpc_channel_credentials/ + end end describe '#compose' do diff --git a/src/ruby/spec/channel_spec.rb b/src/ruby/spec/channel_spec.rb index a4d2d4b427a..11bbdd40d2a 100644 --- a/src/ruby/spec/channel_spec.rb +++ b/src/ruby/spec/channel_spec.rb @@ -130,6 +130,17 @@ describe GRPC::Core::Channel do end end + describe '#new for XDS channels' do + it_behaves_like '#new' + + def construct_with_args(a) + proc do + xds_creds = GRPC::Core::XdsChannelCredentials.new(create_test_cert) + GRPC::Core::Channel.new('dummy_host', a, xds_creds) + end + end + end + describe '#create_call' do it 'creates a call OK' do ch = GRPC::Core::Channel.new(fake_host, nil, :this_channel_is_insecure) diff --git a/src/ruby/spec/client_auth_spec.rb b/src/ruby/spec/client_auth_spec.rb index 5d2e6d24ec8..0e921c603a0 100644 --- a/src/ruby/spec/client_auth_spec.rb +++ b/src/ruby/spec/client_auth_spec.rb @@ -85,7 +85,10 @@ describe 'client-server auth' do poll_period: 1 } @srv = new_rpc_server_for_testing(**server_opts) - port = @srv.add_http2_port('0.0.0.0:0', create_server_creds) + ssl_creds = create_server_creds + xds_creds = GRPC::Core::XdsServerCredentials.new(ssl_creds) + port = @srv.add_http2_port('0.0.0.0:0', ssl_creds) + xds_port = @srv.add_http2_port('0.0.0.0:0', xds_creds) @srv.handle(SslTestService) @srv_thd = Thread.new { @srv.run } @srv.wait_till_running @@ -98,6 +101,11 @@ describe 'client-server auth' do @stub = SslTestServiceStub.new("localhost:#{port}", create_channel_creds, **client_opts) + # auth should success as the fallback creds wil be used + xds_channel_creds = GRPC::Core::XdsChannelCredentials.new(create_channel_creds) + @xds_stub = SslTestServiceStub.new("localhost:#{xds_port}", + xds_channel_creds, + **client_opts) end after(:all) do @@ -123,4 +131,22 @@ describe 'client-server auth' do responses = @stub.a_bidi_rpc([EchoMsg.new, EchoMsg.new]) responses.each { |r| GRPC.logger.info(r) } end + + it 'xds_client-xds_server ssl fallback auth with unary RPCs' do + @xds_stub.an_rpc(EchoMsg.new) + end + + it 'xds_client-xds_server ssl fallback auth with client streaming RPCs' do + @xds_stub.a_client_streaming_rpc([EchoMsg.new, EchoMsg.new]) + end + + it 'xds_client-xds_server ssl fallback auth with server streaming RPCs' do + responses = @xds_stub.a_server_streaming_rpc(EchoMsg.new) + responses.each { |r| GRPC.logger.info(r) } + end + + it 'xds_client-xds_server ssl fallback auth with bidi RPCs' do + responses = @xds_stub.a_bidi_rpc([EchoMsg.new, EchoMsg.new]) + responses.each { |r| GRPC.logger.info(r) } + end end diff --git a/src/ruby/spec/server_credentials_spec.rb b/src/ruby/spec/server_credentials_spec.rb index f773a5f701b..3a6e2115f2d 100644 --- a/src/ruby/spec/server_credentials_spec.rb +++ b/src/ruby/spec/server_credentials_spec.rb @@ -23,6 +23,7 @@ end describe GRPC::Core::ServerCredentials do Creds = GRPC::Core::ServerCredentials + XdsCreds = GRPC::Core::XdsServerCredentials describe '#new' do it 'can be constructed from a fake CA PEM, server PEM and a server key' do @@ -75,5 +76,29 @@ describe GRPC::Core::ServerCredentials do blk = proc { Creds.new(nil, cert_pairs, false) } expect(&blk).to_not raise_error end + + it 'can be constructed with a fallback credential' do + _, cert_pairs, _ = load_test_certs + fallback = Creds.new(nil, cert_pairs, false) + blk = proc { XdsCreds.new(fallback) } + expect(&blk).to_not raise_error + end + + it 'cannot be constructed with nil' do + blk = proc { XdsCreds.new(nil) } + expect(&blk).to raise_error TypeError, /expected grpc_server_credentials/ + end + + it 'cannot be constructed with a non-C-extension object' do + not_a_fallback = 100 + blk = proc { XdsCreds.new(not_a_fallback) } + expect(&blk).to raise_error TypeError, /expected grpc_server_credentials/ + end + + it 'cannot be constructed with a non-ServerCredentials object' do + not_a_fallback = GRPC::Core::ChannelCredentials.new + blk = proc { XdsCreds.new(not_a_fallback) } + expect(&blk).to raise_error TypeError, /expected grpc_server_credentials/ + end end end diff --git a/src/ruby/spec/server_spec.rb b/src/ruby/spec/server_spec.rb index 76038d8b8b5..796e5e709a4 100644 --- a/src/ruby/spec/server_spec.rb +++ b/src/ruby/spec/server_spec.rb @@ -139,6 +139,28 @@ describe Server do expect(&blk).to raise_error(RuntimeError) end end + + describe 'for xds servers' do + let(:cert) { create_test_cert } + let(:xds) { GRPC::Core::XdsServerCredentials.new(cert) } + it 'runs without failing' do + blk = proc do + s = new_core_server_for_testing(nil) + s.add_http2_port('localhost:0', xds) + s.shutdown_and_notify(nil) + s.close + end + expect(&blk).to_not raise_error + end + + it 'fails if the server is closed' do + s = new_core_server_for_testing(nil) + s.shutdown_and_notify(nil) + s.close + blk = proc { s.add_http2_port('localhost:0', xds) } + expect(&blk).to raise_error(RuntimeError) + end + end end shared_examples '#new' do diff --git a/src/ruby/tools/platform_check.rb b/src/ruby/tools/platform_check.rb index 52237fee82f..f2cfb68ea94 100644 --- a/src/ruby/tools/platform_check.rb +++ b/src/ruby/tools/platform_check.rb @@ -29,7 +29,12 @@ module PLATFORM end def PLATFORM.architecture - case RbConfig::CONFIG['host_cpu'] + host_cpu = RbConfig::CONFIG['host_cpu'] + + # When we're on arm in macOS, we can rely on Rosetta and use the x86_64 binary + return 'x86_64' if RbConfig::CONFIG['host_os'] =~ /darwin/ && host_cpu =~ /arm/ + + case host_cpu when /x86_64/ 'x86_64' else diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb index fdb351b3ab3..2aaf4e1a5f1 100644 --- a/src/ruby/tools/version.rb +++ b/src/ruby/tools/version.rb @@ -14,6 +14,6 @@ module GRPC module Tools - VERSION = '1.37.0.dev' + VERSION = '1.38.0.dev' end end diff --git a/src/upb/gen_build_yaml.py b/src/upb/gen_build_yaml.py index c2ceb9792d5..b556c3dea89 100755 --- a/src/upb/gen_build_yaml.py +++ b/src/upb/gen_build_yaml.py @@ -33,8 +33,6 @@ try: "third_party/upb/upb/decode.c", "third_party/upb/upb/def.c", "third_party/upb/upb/encode.c", - "third_party/upb/upb/json_decode.c", - "third_party/upb/upb/json_encode.c", "third_party/upb/upb/msg.c", "third_party/upb/upb/reflection.c", "third_party/upb/upb/table.c", @@ -50,8 +48,6 @@ try: "third_party/upb/upb/def.h", "third_party/upb/upb/def.hpp", "third_party/upb/upb/encode.h", - "third_party/upb/upb/json_decode.h", - "third_party/upb/upb/json_encode.h", "third_party/upb/upb/msg.h", "third_party/upb/upb/port_def.inc", "third_party/upb/upb/port_undef.inc", diff --git a/templates/BUILD.gn.template b/templates/BUILD.gn.template index 660bf53d641..e92f1199d22 100644 --- a/templates/BUILD.gn.template +++ b/templates/BUILD.gn.template @@ -35,8 +35,6 @@ <%! def get_deps(target_dict): deps = [] - if target_dict.get("secure", False): - deps = ["//third_party/boringssl"] if target_dict.get("build", None) == "protoc": deps.append("//third_party/protobuf:protoc_lib") name = target_dict.get("name", None) @@ -45,7 +43,9 @@ elif name in ("grpc", "grpc_unsecure"): deps.append("//third_party/zlib") for d in target_dict.get("deps", []): - if d.startswith(("//", ":")): + if d == "libssl": + deps.append("//third_party/boringssl") + elif d.startswith(("//", ":")): deps.append(d) else: deps.append(":%s" % d) diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template index 7fe97eeb1a5..cef2534cbd1 100644 --- a/templates/CMakeLists.txt.template +++ b/templates/CMakeLists.txt.template @@ -39,13 +39,20 @@ def get_absl_dep(lib_name): return lib_map[lib_name].cmake_target - def list_absl_lib_files_for(lib_name): - ret = [] - lib = lib_map[lib_name] - for dep in lib.transitive_deps: - if is_absl_lib(dep) and len(lib_map[dep].src) > 0: - ret.append(get_absl_dep(dep).replace("::", "_")) - return ret + def lib_and_transitive_deps(lib): + return list(sorted(set({lib} | set(lib_map[lib].transitive_deps)))) + + def list_abseil_pkg_targets(lib): + # This returns a list of abseil pkg targets which the given lib and + # its non-abseil transitive dependencies depend on. + # As a result, internal abseil libraries are excluded from the result. + absl_specs = set() + for lib_name in lib_and_transitive_deps(lib): + if is_absl_lib(lib_name): continue + for dep in lib_map[lib_name].deps: + if is_absl_lib(dep): + absl_specs.add(get_absl_dep(dep).replace("::", "_")) + return list(sorted(absl_specs)) def is_shared_only_lib(lib_name): """Returns True if only shared library should be generated.""" @@ -53,15 +60,12 @@ # only makes sense as a shared lib. return lib_name in ['grpc_csharp_ext'] - def get_deps(target_dict): deps = [] if target_dict.get('baselib', False) or target_dict['name'] == 'address_sorting': deps.append("${_gRPC_BASELIB_LIBRARIES}") if target_dict.get('build', None) in ['protoc']: deps.append("${_gRPC_PROTOBUF_PROTOC_LIBRARIES}") - if target_dict.get('secure', False): - deps.append("${_gRPC_SSL_LIBRARIES}") if target_dict.language == 'c++': deps.append("${_gRPC_PROTOBUF_LIBRARIES}") if target_dict['name'] in ['grpc', 'grpc_cronet', 'grpc_unsecure']: @@ -74,6 +78,8 @@ for d in target_dict.get('deps', []): if d == 'benchmark': deps.append("${_gRPC_BENCHMARK_LIBRARIES}") + elif d == 'libssl': + deps.append("${_gRPC_SSL_LIBRARIES}") elif is_absl_lib(d): deps.append(get_absl_dep(d)) else: @@ -145,9 +151,9 @@ set(gRPC_CORE_VERSION "${settings.core_version}") set(gRPC_CORE_SOVERSION "${settings.core_version.major}") set(gRPC_CPP_VERSION "${settings.cpp_version}") - set(gRPC_CPP_SOVERSION "${settings.cpp_version.major}") + set(gRPC_CPP_SOVERSION "${settings.cpp_version.major}.${settings.cpp_version.minor}") set(gRPC_CSHARP_VERSION "${settings.csharp_version}") - set(gRPC_CSHARP_SOVERSION "${settings.csharp_version.major}") + set(gRPC_CSHARP_SOVERSION "${settings.csharp_version.major}.${settings.csharp_version.minor}") set(PACKAGE_STRING "<%text>${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_TARNAME "<%text>${PACKAGE_NAME}-${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/") @@ -320,6 +326,7 @@ include(cmake/re2.cmake) include(cmake/ssl.cmake) include(cmake/upb.cmake) + include(cmake/xxhash.cmake) include(cmake/zlib.cmake) if(_gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_IOS) @@ -460,7 +467,7 @@ for lib in libs: if lib.build not in ["all", "protoc", "tool", "test", "private"] or lib.boringssl: continue if lib.get('build_system', []) and 'cmake' not in lib.get('build_system', []): continue - if lib.name in ['ares', 'benchmark', 're2', 'z']: continue # we build these using CMake instead + if lib.name in ['ares', 'benchmark', 're2', 'xxhash', 'z']: continue # we build these using CMake instead if is_absl_lib(lib.name): continue # we build these using CMake instead cmake_libs.append(lib) %> @@ -573,6 +580,7 @@ <%text>${_gRPC_UPB_GENERATED_DIR} <%text>${_gRPC_UPB_GRPC_GENERATED_DIR} <%text>${_gRPC_UPB_INCLUDE_DIR} + <%text>${_gRPC_XXHASH_INCLUDE_DIR} <%text>${_gRPC_ZLIB_INCLUDE_DIR} % if lib.build in ['test', 'private'] and lib.language == 'c++': third_party/googletest/googletest/include @@ -653,6 +661,7 @@ <%text>${_gRPC_UPB_GENERATED_DIR} <%text>${_gRPC_UPB_GRPC_GENERATED_DIR} <%text>${_gRPC_UPB_INCLUDE_DIR} + <%text>${_gRPC_XXHASH_INCLUDE_DIR} <%text>${_gRPC_ZLIB_INCLUDE_DIR} % if tgt.build in ['test', 'private'] and tgt.language == 'c++': third_party/googletest/googletest/include @@ -676,7 +685,13 @@ <%def name="cc_install(tgt)"> + % if tgt.name == 'grpcpp_channelz': + # grpcpp_channelz doesn't build with protobuf-lite, so no install required + # See https://github.com/grpc/grpc/issues/22826 + if(gRPC_INSTALL AND NOT gRPC_USE_PROTO_LITE) + % else: if(gRPC_INSTALL) + % endif install(TARGETS ${tgt.name} EXPORT gRPCTargets RUNTIME DESTINATION <%text>${gRPC_INSTALL_BINDIR} LIBRARY DESTINATION <%text>${gRPC_INSTALL_LIBDIR} @@ -736,8 +751,8 @@ "gpr" "gRPC platform support library" "<%text>${gRPC_CORE_VERSION}" - "" - "${" ".join(("-l" + l) for l in ["gpr",] + list_absl_lib_files_for("gpr"))}" + "${" ".join(list_abseil_pkg_targets("gpr"))}" + "${" ".join(("-l" + l) for l in ["gpr"])}" "" "gpr.pc") @@ -746,8 +761,8 @@ "gRPC" "high performance general RPC framework" "<%text>${gRPC_CORE_VERSION}" - "gpr openssl" - "${" ".join(("-l" + l) for l in ["grpc", "address_sorting", "re2", "upb", "cares", "z"] + list_absl_lib_files_for("grpc"))}" + "${" ".join(["gpr", "openssl"] + list_abseil_pkg_targets("grpc"))}" + "${" ".join(("-l" + l) for l in ["grpc", "address_sorting", "re2", "upb", "cares", "z"])}" "" "grpc.pc") @@ -756,8 +771,8 @@ "gRPC unsecure" "high performance general RPC framework without SSL" "<%text>${gRPC_CORE_VERSION}" - "gpr" - "${" ".join(("-l" + l) for l in ["grpc_unsecure",] + list_absl_lib_files_for("grpc_unsecure"))}" + "${" ".join(["gpr"] + list_abseil_pkg_targets("grpc_unsecure"))}" + "${" ".join(("-l" + l) for l in ["grpc_unsecure"])}" "" "grpc_unsecure.pc") @@ -766,8 +781,8 @@ "gRPC++" "C++ wrapper for gRPC" "<%text>${gRPC_CPP_VERSION}" - "grpc" - "${" ".join(("-l" + l) for l in ["grpc++",] + list_absl_lib_files_for("grpc++"))}" + "${" ".join(["grpc"] + list_abseil_pkg_targets("grpc++"))}" + "${" ".join(("-l" + l) for l in ["grpc++"])}" "" "grpc++.pc") @@ -776,7 +791,7 @@ "gRPC++ unsecure" "C++ wrapper for gRPC without SSL" "<%text>${gRPC_CPP_VERSION}" - "grpc_unsecure" - "${" ".join(("-l" + l) for l in ["grpc++_unsecure",] + list_absl_lib_files_for("grpc++_unsecure"))}" + "${" ".join(["grpc_unsecure"] + list_abseil_pkg_targets("grpc++_unsecure"))}" + "${" ".join(("-l" + l) for l in ["grpc++_unsecure"])}" "" "grpc++_unsecure.pc") diff --git a/templates/Makefile.template b/templates/Makefile.template index b91ec449f37..5afb36ce6a4 100644 --- a/templates/Makefile.template +++ b/templates/Makefile.template @@ -860,7 +860,6 @@ "defaults": "abseil", "src": sorted(used_abseil_srcs), "hdr": sorted(used_abseil_hdrs), - "secure": False, }) %> ${makelib(grpc_abseil_lib)} @@ -897,7 +896,7 @@ % endif ## If the library requires OpenSSL, let's add some restrictions. - % if lib.get('secure', 'check') == True or lib.get('secure', 'check') == 'check': + % if 'libssl' in lib.get('deps', []): ifeq ($(NO_SECURE),true) # You can't build secure libraries if you don't have OpenSSL. @@ -932,7 +931,7 @@ $(ADDRESS_SORTING_MERGE_OBJS) \ $(RE2_MERGE_OBJS) \ $(UPB_MERGE_OBJS) \ - % if lib.get('secure', 'check') == True: + % if 'libssl' in lib.get('deps', []): $(OPENSSL_MERGE_OBJS) \ % endif % endif @@ -949,7 +948,7 @@ $(ADDRESS_SORTING_MERGE_OBJS) \ $(RE2_MERGE_OBJS) \ $(UPB_MERGE_OBJS) \ - % if lib.get('secure', 'check') == True: + % if 'libssl' in lib.get('deps', []): $(OPENSSL_MERGE_OBJS) \ % endif % endif @@ -972,12 +971,13 @@ mingw_lib_deps = ' $(ZLIB_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(RE2_DEP) $(UPB_DEP) $(GRPC_ABSEIL_DEP)' for dep in lib.get('deps', []): if is_absl_lib(dep): continue + if 'libssl' == dep: continue lib_archive = '$(LIBDIR)/$(CONFIG)/lib' + dep + '.a' common = common + ' ' + lib_archive lib_deps = lib_deps + ' ' + lib_archive mingw_lib_deps = mingw_lib_deps + ' ' + lib_archive - security = lib.get('secure', 'check') + security = 'libssl' in lib.get('deps', []) if security == True: common = common + ' $(OPENSSL_MERGE_LIBS) $(LDLIBS_SECURE)' common = common + ' $(ZLIB_MERGE_LIBS) $(CARES_MERGE_LIBS) $(ADDRESS_SORTING_MERGE_LIBS) $(RE2_MERGE_LIBS) $(UPB_MERGE_LIBS) $(GRPC_ABSEIL_MERGE_LIBS)' @@ -989,7 +989,7 @@ for src in lib.src: sources_that_don_t_need_openssl.add(src) - if lib.get('secure', 'check') == True or lib.get('secure', 'check') == 'check': + if 'libssl' in lib.get('deps', []): lib_deps = lib_deps + ' $(OPENSSL_DEP)' mingw_lib_deps = mingw_lib_deps + ' $(OPENSSL_DEP)' @@ -1019,20 +1019,20 @@ endif endif % endif - % if lib.get('secure', 'check') == True or lib.get('secure', 'check') == 'check': + % if 'libssl' in lib.get('deps', []): ## If the lib was secure, we have to close the Makefile's if that tested ## the presence of OpenSSL. endif % endif - % if lib.get('secure', 'check') == True or lib.get('secure', 'check') == 'check': + % if 'libssl' in lib.get('deps', []): ifneq ($(NO_SECURE),true) % endif ifneq ($(NO_DEPS),true) -include $(LIB${lib.name.upper()}_OBJS:.o=.dep) endif - % if lib.get('secure', 'check') == True or lib.get('secure', 'check') == 'check': + % if 'libssl' in lib.get('deps', []): endif % endif # end of build recipe for library "${lib.name}" diff --git a/templates/README.md b/templates/README.md index 936ba4108d7..9c4626f5eb5 100644 --- a/templates/README.md +++ b/templates/README.md @@ -76,7 +76,6 @@ language: "...", # the language tag; "c" or "c++" public_headers: # list of public headers to install headers: # list of headers used by that target src: # list of files to compile -secure: boolean, # see below baselib: boolean, # this is a low level library that has system # dependencies filegroups: # list of filegroups to merge to that project @@ -99,16 +98,6 @@ All of the targets should always be present in the generated project file, if possible and applicable. But the build tag is what should group the targets together in a single build command. - -## The `"secure"` tag - -This means this target requires OpenSSL one way or another. The values can be -`"yes"`, `"no"` and `"check"`. The default value is `"check"`. It means that -the target requires OpenSSL, but that since the target depends on another one -that is supposed to also import OpenSSL, the import should then be implicitely -transitive. `"check"` should then only disable that target if OpenSSL hasn't -been found or is unavailable. - ## The `"baselib"` boolean This means this is a library that will provide most of the features for gRPC. diff --git a/templates/config.m4.template b/templates/config.m4.template index 1e074a7ba2b..edd103c4130 100644 --- a/templates/config.m4.template +++ b/templates/config.m4.template @@ -16,6 +16,7 @@ PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl-with-bazel/src/include) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/re2) PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/upb) + PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/xxhash) LIBS="-lpthread $LIBS" diff --git a/templates/config.w32.template b/templates/config.w32.template index 4b5e04e4531..f4afa1d0690 100644 --- a/templates/config.w32.template +++ b/templates/config.w32.template @@ -37,6 +37,7 @@ "/I"+configure_module_dirname+"\\third_party\\boringssl-with-bazel\\src\\include "+ "/I"+configure_module_dirname+"\\third_party\\re2 "+ "/I"+configure_module_dirname+"\\third_party\\upb "+ + "/I"+configure_module_dirname+"\\third_party\\xxhash "+ "/I"+configure_module_dirname+"\\third_party\\zlib "); <% dirs = sorted(set(src[:src.rfind('/')] for src in srcs)) diff --git a/templates/gRPC-C++.podspec.template b/templates/gRPC-C++.podspec.template index fa0498e056e..24f176b208d 100644 --- a/templates/gRPC-C++.podspec.template +++ b/templates/gRPC-C++.podspec.template @@ -165,7 +165,7 @@ ss.header_mappings_dir = '.' ss.dependency "#{s.name}/Interface", version ss.dependency 'gRPC-Core', version - abseil_version = '1.20200923.3' + abseil_version = '1.20210324.0' % for abseil_spec in grpcpp_abseil_specs: ss.dependency '${abseil_spec}', abseil_version % endfor @@ -211,5 +211,8 @@ find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/util/\\1"\\\n#else\\\n #include "util/\\1"\\\n#endif;g' find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g' find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm + find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n #include "third_party/xxhash/xxhash.h"\\\n#else\\\n #include "xxhash.h"\\\n#endif;g' + find third_party/xxhash -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g' + find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm END_OF_COMMAND end diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template index fa23e58c272..95609e787c3 100644 --- a/templates/gRPC-Core.podspec.template +++ b/templates/gRPC-Core.podspec.template @@ -59,13 +59,29 @@ files.update(lib.get(field, [])) return list(sorted(files)) + # Wrapped languages don't need to access EventEngine APIs. + event_engine_files = [ + file + for file in list_lib_files("grpc", ("public_headers", "headers", "src")) + if '/event_engine/' in file + ] + # ObjectiveC doesn't use c-ares so we don't need address_sorting files at all address_sorting_unwanted_files = list_lib_files("address_sorting", ("public_headers", "headers", "src")) # ObjectiveC needs to obtain re2 explicitly unlike other languages; TODO @donnadionne make ObjC more consistent with others - grpc_private_files = list(sorted((set(list_lib_files("grpc", ("headers", "src"))) - set(address_sorting_unwanted_files)) | set(list_lib_files("re2", ("headers", "src"))))) - grpc_public_headers = list(sorted((set(list_lib_files("grpc", ("public_headers",))) - set(address_sorting_unwanted_files)) | set(list_lib_files("re2", ("public_headers",))))) - grpc_private_headers = list(sorted((set(list_lib_files("grpc", ("headers",))) - set(address_sorting_unwanted_files)) | set(list_lib_files("re2", ("headers",))))) + grpc_private_files = list( + sorted((set(list_lib_files("grpc", ("headers", "src"))) - + set(address_sorting_unwanted_files) - set(event_engine_files)) + | set(list_lib_files("re2", ("headers", "src"))))) + grpc_public_headers = list( + sorted((set(list_lib_files("grpc", ("public_headers", ))) - + set(address_sorting_unwanted_files)) - set(event_engine_files) + | set(list_lib_files("re2", ("public_headers", ))))) + grpc_private_headers = list( + sorted((set(list_lib_files("grpc", ("headers", ))) - + set(address_sorting_unwanted_files)) - set(event_engine_files) + | set(list_lib_files("re2", ("headers", ))))) grpc_abseil_specs = list_abseil_specs("grpc") grpc_tests_abseil_specs = list(sorted(set(list_abseil_specs("end2end_tests")) - set(grpc_abseil_specs))) @@ -91,6 +107,7 @@ set(list_lib_files("end2end_tests", ("src", "headers"))) - set(grpc_private_files) - set(address_sorting_unwanted_files) + - set(event_engine_files) - set([ # Subprocess is not supported in tvOS and not needed by our tests. "test/core/util/subprocess_posix.cc", @@ -123,7 +140,7 @@ s.requires_arc = false name = 'grpc' - abseil_version = '1.20200923.3' + abseil_version = '1.20210324.0' # When creating a dynamic framework, name it grpc.framework instead of gRPC-Core.framework. # This lets users write their includes like `#include ` as opposed to `#include @@ -196,7 +213,7 @@ ss.header_mappings_dir = '.' ss.libraries = 'z' ss.dependency "#{s.name}/Interface", version - ss.dependency 'BoringSSL-GRPC', '0.0.17' + ss.dependency 'BoringSSL-GRPC', '0.0.18' % for abseil_spec in grpc_abseil_specs: ss.dependency '${abseil_spec}', abseil_version % endfor @@ -250,5 +267,8 @@ find third_party/re2/re2/ third_party/re2/util/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g;s;#include "util/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/util/\\1"\\\n#else\\\n #include "util/\\1"\\\n#endif;g' find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "re2/(.*)";#if COCOAPODS==1\\\n #include "third_party/re2/re2/\\1"\\\n#else\\\n #include "re2/\\1"\\\n#endif;g' find src/core/ third_party/re2/ -type f -name '*.grpc_back' -print0 | xargs -0 rm + find src/core/ -type f \\( -name '*.h' -or -name '*.cc' \\) -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;#include "xxhash.h";#if COCOAPODS==1\\\n #include "third_party/xxhash/xxhash.h"\\\n#else\\\n #include "xxhash.h"\\\n#endif;g' + find third_party/xxhash -type f -name xxhash.h -print0 | xargs -0 -L1 sed -E -i'.grpc_back' 's;@param([^,]*),;@param\\1 ,;g' + find src/core/ third_party/xxhash/ -type f -name '*.grpc_back' -print0 | xargs -0 rm END_OF_COMMAND end diff --git a/templates/grpc.gyp.template b/templates/grpc.gyp.template index 49ce883ef8f..3437c178c3b 100644 --- a/templates/grpc.gyp.template +++ b/templates/grpc.gyp.template @@ -145,7 +145,9 @@ 'type': 'static_library', 'dependencies': [ % for dep in getattr(lib, 'deps', []): + % if dep != 'libssl': '${dep}', + % endif % endfor ], 'sources': [ diff --git a/templates/include/grpc/module.modulemap.template b/templates/include/grpc/module.modulemap.template index e18bc3de50d..83f1ec5dc17 100644 --- a/templates/include/grpc/module.modulemap.template +++ b/templates/include/grpc/module.modulemap.template @@ -1,8 +1,8 @@ %YAML 1.2 --- | - <%! + <% # TODO (mxyan): Make this list from build.yaml - textual_headers = ["include/grpc/support/atm_gcc_atomic.h", + textual_headers = {"include/grpc/support/atm_gcc_atomic.h", "include/grpc/support/atm_gcc_sync.h", "include/grpc/support/atm_windows.h", "include/grpc/support/sync_custom.h", @@ -16,28 +16,19 @@ "include/grpc/impl/codegen/atm_windows.h", "include/grpc/impl/codegen/sync_custom.h", "include/grpc/impl/codegen/sync_posix.h", - "include/grpc/impl/codegen/sync_windows.h"] - - def grpc_public_headers_no_dir(libs): - out = [] - for lib in libs: - if lib.name in ("grpc", "gpr"): - out += lib.get('public_headers', []) - out = [f for f in out if f not in textual_headers] - out = [hdr.split('/', 2)[2] for hdr in out] - return out - - # Generate the list of platform-specific headers as textual headers so that - # they are not built when the module is built but only when they are named by - # an #include directive. - def grpc_public_textual_headers_no_dir(libs): - out = [] - for lib in libs: - if lib.name in ("grpc", "gpr"): - out += lib.get('public_headers', []) - out = [f for f in out if f in textual_headers] - out = [hdr.split('/', 2)[2] for hdr in out] - return out + "include/grpc/impl/codegen/sync_windows.h"} + + grpc_public_headers = { + file for lib in libs for file in lib.get('public_headers', []) + if lib.name in ("grpc", "gpr") + } + + event_engine_files = { + file for file in grpc_public_headers if 'event_engine' in file + } + + def un_dir(files): + return {f.split ('/', 2)[2] for f in files} def header_lines(files): return ('\n ').join('header "%s"' % f for f in files) @@ -48,9 +39,13 @@ framework module grpc { umbrella header "grpc.h" - ${header_lines(grpc_public_headers_no_dir(libs))} + ${header_lines( + sorted(un_dir(grpc_public_headers - event_engine_files - + textual_headers)))} - ${textual_header_lines(grpc_public_textual_headers_no_dir(libs))} + ${textual_header_lines( + sorted(un_dir(grpc_public_headers.intersection(textual_headers) - + event_engine_files)))} export * module * { export * } diff --git a/templates/src/core/lib/surface/version.cc.template b/templates/src/core/lib/surface/version.cc.template index 0cb31547258..4e9f2c36ad7 100644 --- a/templates/src/core/lib/surface/version.cc.template +++ b/templates/src/core/lib/surface/version.cc.template @@ -27,4 +27,6 @@ const char* grpc_version_string(void) { return "${settings.core_version}"; } - const char* grpc_g_stands_for(void) { return "${settings.g_stands_for}"; } + const char* grpc_g_stands_for(void) { + return "${settings.g_stands_for}"; + } diff --git a/templates/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs.template b/templates/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs.template index 4feba1097da..ee7525f01fc 100644 --- a/templates/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs.template +++ b/templates/src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs.template @@ -77,6 +77,13 @@ % endfor } + public NativeMethods(DllImportsFromSharedLib_arm64 unusedInstance) + { + % for method in get_native_methods(): + this.${method['name']} = DllImportsFromSharedLib_arm64.${method['name']}; + % endfor + } + public NativeMethods(DllImportsFromSharedLib_x86_dll unusedInstance) { % for method in get_native_methods(): @@ -153,6 +160,19 @@ % endfor } + /// + /// grpc_csharp_ext used as a shared library (with arm64 suffix) + /// + internal class DllImportsFromSharedLib_arm64 + { + private const string ImportName = "grpc_csharp_ext.arm64"; + % for method in get_native_methods(): + + [DllImport(ImportName)] + public static extern ${method['returntype']} ${method['name']}(${method['params']}); + % endfor + } + /// /// grpc_csharp_ext used as a shared library (with x86.dll suffix) /// diff --git a/templates/src/objective-c/BoringSSL-GRPC.podspec.template b/templates/src/objective-c/BoringSSL-GRPC.podspec.template index b949e707309..c927fb95cc8 100644 --- a/templates/src/objective-c/BoringSSL-GRPC.podspec.template +++ b/templates/src/objective-c/BoringSSL-GRPC.podspec.template @@ -69,7 +69,7 @@ Pod::Spec.new do |s| s.name = 'BoringSSL-GRPC' - version = '0.0.17' + version = '0.0.18' s.version = version s.summary = 'BoringSSL is a fork of OpenSSL that is designed to meet Google\'s needs.' # Adapted from the homepage: diff --git a/templates/src/python/grpcio_admin/grpc_version.py.template b/templates/src/python/grpcio_admin/grpc_version.py.template new file mode 100644 index 00000000000..45a4fbc631c --- /dev/null +++ b/templates/src/python/grpcio_admin/grpc_version.py.template @@ -0,0 +1,19 @@ +%YAML 1.2 +--- | + # Copyright 2021 The gRPC Authors + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_admin/grpc_version.py.template`!!! + + VERSION = '${settings.python_version.pep440()}' diff --git a/templates/src/python/grpcio_csds/grpc_version.py.template b/templates/src/python/grpcio_csds/grpc_version.py.template new file mode 100644 index 00000000000..b4a497a5ec9 --- /dev/null +++ b/templates/src/python/grpcio_csds/grpc_version.py.template @@ -0,0 +1,19 @@ +%YAML 1.2 +--- | + # Copyright 2021 The gRPC Authors + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_csds/grpc_version.py.template`!!! + + VERSION = '${settings.python_version.pep440()}' diff --git a/templates/test/core/surface/public_headers_must_be_c89.c.template b/templates/test/core/surface/public_headers_must_be_c89.c.template index 2932d7a2dc2..5cadf576020 100644 --- a/templates/test/core/surface/public_headers_must_be_c89.c.template +++ b/templates/test/core/surface/public_headers_must_be_c89.c.template @@ -27,6 +27,8 @@ return False def is_cronet_header(hdr): return "cronet" in hdr + def is_event_engine_header(hdr): + return "/event_engine/" in hdr hdrs = set() pfx = 'include/' for lib in libs: @@ -34,6 +36,7 @@ for hdr in lib.get('public_headers', []): if is_platform_header(hdr): continue if is_cronet_header(hdr): continue + if is_event_engine_header(hdr): continue assert(hdr[0:len(pfx)] == pfx) hdrs.add(hdr[len(pfx):]) hdrs = sorted(list(hdrs)) diff --git a/templates/tools/dockerfile/apt_get_python_27.include b/templates/tools/dockerfile/apt_get_python_27.include index c6fd8a831ce..363bc5067dd 100644 --- a/templates/tools/dockerfile/apt_get_python_27.include +++ b/templates/tools/dockerfile/apt_get_python_27.include @@ -1,3 +1,3 @@ # Install Python 2.7 RUN apt-get update && apt-get install -y python2.7 python-all-dev -RUN curl https://bootstrap.pypa.io/2.7/get-pip.py | python2.7 +RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7 diff --git a/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template b/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template index 9216235c924..e800038b2fc 100644 --- a/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template +++ b/templates/tools/dockerfile/grpc_clang_format/Dockerfile.template @@ -14,14 +14,11 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM debian:10 - - # Add buster-backports for more recent clang packages - RUN echo "deb http://deb.debian.org/debian buster-backports main" | tee /etc/apt/sources.list.d/buster-backports.list + FROM debian:bullseye # Install clang-format - RUN apt-get update && apt-get install -y clang-format-8 - ENV CLANG_FORMAT=clang-format-8 + RUN apt-get update && apt-get install -y clang-format-11 + ENV CLANG_FORMAT=clang-format-11 ADD clang_format_all_the_things.sh / diff --git a/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template b/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template index b3a363606ea..ee3c4b61a01 100644 --- a/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template +++ b/templates/tools/dockerfile/grpc_clang_tidy/Dockerfile.template @@ -14,14 +14,11 @@ # See the License for the specific language governing permissions and # limitations under the License. - <%include file="../python_debian10.include"/> + FROM debian:bullseye - # Add buster-backports for more recent clang packages - RUN echo "deb http://deb.debian.org/debian buster-backports main" | tee /etc/apt/sources.list.d/buster-backports.list - - # Install clang-tidy 7 - RUN apt-get update && apt-get install -y clang-tidy-8 jq - ENV CLANG_TIDY=clang-tidy-8 + # Install clang-tidy 11 + RUN apt-get update && apt-get install -y clang-tidy-11 jq + ENV CLANG_TIDY=clang-tidy-11 ADD clang_tidy_all_the_things.sh / diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile.template index c908a638edc..292eaa828dd 100644 --- a/templates/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile.template +++ b/templates/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile.template @@ -1,6 +1,6 @@ %YAML 1.2 --- | - # Copyright 2015 gRPC authors. + # Copyright 2021 The gRPC Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - FROM golang:1.11 + FROM golang:1.16 <%include file="../../go_path.include"/> <%include file="../../python_deps.include"/> diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_go1.16/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.16/Dockerfile.template new file mode 100644 index 00000000000..292eaa828dd --- /dev/null +++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.16/Dockerfile.template @@ -0,0 +1,23 @@ +%YAML 1.2 +--- | + # Copyright 2021 The gRPC Authors + # + # Licensed under the Apache License, Version 2.0 (the "License"); + # you may not use this file except in compliance with the License. + # You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, software + # distributed under the License is distributed on an "AS IS" BASIS, + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + # See the License for the specific language governing permissions and + # limitations under the License. + + FROM golang:1.16 + + <%include file="../../go_path.include"/> + <%include file="../../python_deps.include"/> + # Define the default command. + CMD ["bash"] + diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_go1.16/build_interop.sh.template b/templates/tools/dockerfile/interoptest/grpc_interop_go1.16/build_interop.sh.template new file mode 100644 index 00000000000..a08798b1d6b --- /dev/null +++ b/templates/tools/dockerfile/interoptest/grpc_interop_go1.16/build_interop.sh.template @@ -0,0 +1,3 @@ +%YAML 1.2 +--- | + <%include file="../../go_build_interop.sh.include"/> diff --git a/templates/tools/dockerfile/python_debian10.include b/templates/tools/dockerfile/python_debian10.include deleted file mode 100644 index f65c9ff78ac..00000000000 --- a/templates/tools/dockerfile/python_debian10.include +++ /dev/null @@ -1,6 +0,0 @@ -FROM debian:10 - -<%include file="./apt_get_basic.include"/> -<%include file="./apt_get_python_27.include"/> -<%include file="./gcp_api_libraries.include"/> -<%include file="./run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/python_debian11.include b/templates/tools/dockerfile/python_debian11.include new file mode 100644 index 00000000000..8fe602da69e --- /dev/null +++ b/templates/tools/dockerfile/python_debian11.include @@ -0,0 +1,53 @@ +FROM debian:bullseye + +# Install Git and basic packages. +RUN apt-get update && apt-get install -y ${'\\'} + autoconf ${'\\'} + autotools-dev ${'\\'} + build-essential ${'\\'} + bzip2 ${'\\'} + ccache ${'\\'} + curl ${'\\'} + dnsutils ${'\\'} + gcc ${'\\'} + gcc-multilib ${'\\'} + git ${'\\'} + golang ${'\\'} + gyp ${'\\'} + lcov ${'\\'} + libc6 ${'\\'} + libc6-dbg ${'\\'} + libc6-dev ${'\\'} + libgtest-dev ${'\\'} + libtool ${'\\'} + make ${'\\'} + perl ${'\\'} + strace ${'\\'} + telnet ${'\\'} + unzip ${'\\'} + wget ${'\\'} + zip && apt-get clean + +#================ +# Build profiling +RUN apt-get update && apt-get install -y time && apt-get clean + +# Install Python 3.7 from source (and installed as a default python3) +# (Bullseye comes with Python 3.9 which isn't supported by pytype yet) +RUN apt update && apt install -y build-essential zlib1g-dev libncurses5-dev libgdbm-dev ${'\\'} + libnss3-dev libssl-dev libreadline-dev libffi-dev +RUN curl -O https://www.python.org/ftp/python/3.7.9/Python-3.7.9.tar.xz && ${'\\'} + tar -xf Python-3.7.9.tar.xz && ${'\\'} + cd Python-3.7.9 && ${'\\'} + ./configure && ${'\\'} + make -j 4 && ${'\\'} + make install +RUN curl https://bootstrap.pypa.io/get-pip.py | python3 + +# Install Python 2.7 +RUN apt-get update && apt-get install -y python2 python2-dev +RUN ln -s /usr/bin/python2 /usr/bin/python +RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2 + +<%include file="./gcp_api_libraries.include"/> +<%include file="./run_tests_addons.include"/> diff --git a/templates/tools/dockerfile/python_deps.include b/templates/tools/dockerfile/python_deps.include index 07c8b2389e1..e05e6a1aae0 100644 --- a/templates/tools/dockerfile/python_deps.include +++ b/templates/tools/dockerfile/python_deps.include @@ -9,7 +9,7 @@ RUN apt-get update && apt-get install -y ${'\\'} python-setuptools # Install Python packages from PyPI -RUN curl https://bootstrap.pypa.io/2.7/get-pip.py | python2.7 +RUN curl https://bootstrap.pypa.io/pip/2.7/get-pip.py | python2.7 RUN pip install --upgrade pip==19.3.1 RUN pip install virtualenv==16.7.9 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.15.0 twisted==17.5.0 diff --git a/templates/tools/dockerfile/test/python_stretch_3.5_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_stretch_3.5_x64/Dockerfile.template index 6250cdf000a..8dfb0cd1c29 100644 --- a/templates/tools/dockerfile/test/python_stretch_3.5_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/python_stretch_3.5_x64/Dockerfile.template @@ -17,4 +17,4 @@ <%include file="../../python_stretch.include"/> RUN apt-get update && apt-get install -y python3.5 python3-all-dev - RUN curl https://bootstrap.pypa.io/3.5/get-pip.py | python3.5 + RUN curl https://bootstrap.pypa.io/pip/3.5/get-pip.py | python3.5 diff --git a/templates/tools/dockerfile/test/python_stretch_default_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_stretch_default_x64/Dockerfile.template index 3d20ac8bb50..f12c0a0c7f6 100644 --- a/templates/tools/dockerfile/test/python_stretch_default_x64/Dockerfile.template +++ b/templates/tools/dockerfile/test/python_stretch_default_x64/Dockerfile.template @@ -19,7 +19,7 @@ <%include file="../../compile_python_38.include"/> RUN apt-get update && apt-get install -y python3.5 python3.5-dev - RUN curl https://bootstrap.pypa.io/3.5/get-pip.py | python3.5 + RUN curl https://bootstrap.pypa.io/pip/3.5/get-pip.py | python3.5 RUN apt-get update && apt-get -t buster install -y python3.7 python3-all-dev RUN curl https://bootstrap.pypa.io/get-pip.py | python3.7 diff --git a/templates/tools/dockerfile/test/sanity/Dockerfile.template b/templates/tools/dockerfile/test/sanity/Dockerfile.template index cd4aab5317d..66e5e4cbe47 100644 --- a/templates/tools/dockerfile/test/sanity/Dockerfile.template +++ b/templates/tools/dockerfile/test/sanity/Dockerfile.template @@ -14,16 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. - <%include file="../../python_debian10.include"/> + <%include file="../../python_debian11.include"/> <%include file="../../cxx_deps.include"/> #======================== # Sanity test dependencies - RUN apt-get update && apt-get -t buster install -y python3.7 python3-all-dev - RUN curl https://bootstrap.pypa.io/get-pip.py | python3.7 - # Make Python 3.7 the default Python 3 version - RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 1 RUN apt-get update && apt-get install -y ${"\\"} autoconf ${"\\"} automake ${"\\"} @@ -34,15 +30,13 @@ RUN python3 -m pip install simplejson mako virtualenv==16.7.9 lxml six # Upgrade Python's YAML library + RUN python2 -m pip install --upgrade --ignore-installed PyYAML==5.4.1 --user RUN python3 -m pip install --upgrade --ignore-installed PyYAML==5.4.1 --user - # Add buster-backports for more recent clang packages - RUN echo "deb http://deb.debian.org/debian buster-backports main" | tee /etc/apt/sources.list.d/buster-backports.list - # Install clang, clang-format, and clang-tidy - RUN apt-get update && apt-get install -y clang clang-format-8 clang-tidy-8 jq - ENV CLANG_FORMAT=clang-format-8 - ENV CLANG_TIDY=clang-tidy-8 + RUN apt-get update && apt-get install -y clang clang-format-11 clang-tidy-11 jq + ENV CLANG_FORMAT=clang-format-11 + ENV CLANG_TIDY=clang-tidy-11 <%include file="../../bazel.include"/> diff --git a/test/core/iomgr/poller/BUILD b/test/core/address_utils/BUILD similarity index 54% rename from test/core/iomgr/poller/BUILD rename to test/core/address_utils/BUILD index e5998f3546c..a01a0331b09 100644 --- a/test/core/iomgr/poller/BUILD +++ b/test/core/address_utils/BUILD @@ -1,4 +1,4 @@ -# Copyright 2019 gRPC authors. +# 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. @@ -17,26 +17,44 @@ load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_package") licenses(["notice"]) grpc_package( - name = "test/core/iomgr/poller", - visibility = "public", -) # Used to test IO poller implementations. + name = "test/core/address_utils", + visibility = "private", +) grpc_cc_test( - name = "eventmanager_libuv_test", - srcs = ["eventmanager_libuv_test.cc"], + name = "sockaddr_utils_test", + srcs = ["sockaddr_utils_test.cc"], external_deps = [ "gtest", ], language = "C++", - tags = [ - # TSAN has a false-positive for ShutdownRefAsync - # https://github.com/grpc/grpc/issues/24242 - "notsan", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "parse_address_test", + srcs = ["parse_address_test.cc"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", ], +) + +grpc_cc_test( + name = "parse_address_with_named_scope_id_test", + srcs = ["parse_address_with_named_scope_id_test.cc"], + language = "C++", + tags = ["no_windows"], uses_polling = False, deps = [ - "//:eventmanager_libuv", - "//:grpc_base_c", + "//:gpr", + "//:grpc", "//test/core/util:grpc_test_util", ], ) diff --git a/test/core/iomgr/parse_address_test.cc b/test/core/address_utils/parse_address_test.cc similarity index 97% rename from test/core/iomgr/parse_address_test.cc rename to test/core/address_utils/parse_address_test.cc index d61ff5d5984..a1730fff892 100644 --- a/test/core/iomgr/parse_address_test.cc +++ b/test/core/address_utils/parse_address_test.cc @@ -16,9 +16,9 @@ * */ -#include "src/core/lib/iomgr/parse_address.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/socket_utils.h" #include #ifdef GRPC_HAVE_UNIX_SOCKET diff --git a/test/core/iomgr/parse_address_with_named_scope_id_test.cc b/test/core/address_utils/parse_address_with_named_scope_id_test.cc similarity index 97% rename from test/core/iomgr/parse_address_with_named_scope_id_test.cc rename to test/core/address_utils/parse_address_with_named_scope_id_test.cc index e7b987845e9..cd4f1a5fed2 100644 --- a/test/core/iomgr/parse_address_with_named_scope_id_test.cc +++ b/test/core/address_utils/parse_address_with_named_scope_id_test.cc @@ -16,9 +16,9 @@ * */ -#include "src/core/lib/iomgr/parse_address.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/socket_utils.h" #include #include diff --git a/test/core/address_utils/sockaddr_utils_test.cc b/test/core/address_utils/sockaddr_utils_test.cc new file mode 100644 index 00000000000..208fb22d1c8 --- /dev/null +++ b/test/core/address_utils/sockaddr_utils_test.cc @@ -0,0 +1,289 @@ +// +// 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. +// + +// With the addition of a libuv endpoint, sockaddr.h now includes uv.h when +// using that endpoint. Because of various transitive includes in uv.h, +// including windows.h on Windows, uv.h must be included before other system +// headers. Therefore, sockaddr.h must always be included first +#include "src/core/lib/address_utils/sockaddr_utils.h" +#include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/iomgr/socket_utils.h" + +#include +#include + +#include + +#include +#include +#include +#include "test/core/util/test_config.h" + +namespace { + +grpc_resolved_address MakeAddr4(const uint8_t* data, size_t data_len) { + grpc_resolved_address resolved_addr4; + grpc_sockaddr_in* addr4 = + reinterpret_cast(resolved_addr4.addr); + memset(&resolved_addr4, 0, sizeof(resolved_addr4)); + addr4->sin_family = GRPC_AF_INET; + GPR_ASSERT(data_len == sizeof(addr4->sin_addr.s_addr)); + memcpy(&addr4->sin_addr.s_addr, data, data_len); + addr4->sin_port = grpc_htons(12345); + resolved_addr4.len = static_cast(sizeof(grpc_sockaddr_in)); + return resolved_addr4; +} + +grpc_resolved_address MakeAddr6(const uint8_t* data, size_t data_len) { + grpc_resolved_address resolved_addr6; + grpc_sockaddr_in6* addr6 = + reinterpret_cast(resolved_addr6.addr); + memset(&resolved_addr6, 0, sizeof(resolved_addr6)); + addr6->sin6_family = GRPC_AF_INET6; + GPR_ASSERT(data_len == sizeof(addr6->sin6_addr.s6_addr)); + memcpy(&addr6->sin6_addr.s6_addr, data, data_len); + addr6->sin6_port = grpc_htons(12345); + resolved_addr6.len = static_cast(sizeof(grpc_sockaddr_in6)); + return resolved_addr6; +} + +void SetIPv6ScopeId(grpc_resolved_address* addr, uint32_t scope_id) { + grpc_sockaddr_in6* addr6 = reinterpret_cast(addr->addr); + ASSERT_EQ(addr6->sin6_family, GRPC_AF_INET6); + addr6->sin6_scope_id = scope_id; +} + +const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0xff, 0xff, 192, 0, 2, 1}; + +const uint8_t kNotQuiteMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0xff, 0xfe, 192, 0, 2, 99}; +const uint8_t kIPv4[] = {192, 0, 2, 1}; + +const uint8_t kIPv6[] = {0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1}; + +TEST(SockAddrUtilsTest, SockAddrIsV4Mapped) { + // v4mapped input should succeed. + grpc_resolved_address input6 = MakeAddr6(kMapped, sizeof(kMapped)); + ASSERT_TRUE(grpc_sockaddr_is_v4mapped(&input6, nullptr)); + grpc_resolved_address output4; + ASSERT_TRUE(grpc_sockaddr_is_v4mapped(&input6, &output4)); + grpc_resolved_address expect4 = MakeAddr4(kIPv4, sizeof(kIPv4)); + ASSERT_EQ(memcmp(&expect4, &output4, sizeof(expect4)), 0); + + // Non-v4mapped input should fail. + input6 = MakeAddr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); + ASSERT_FALSE(grpc_sockaddr_is_v4mapped(&input6, nullptr)); + ASSERT_FALSE(grpc_sockaddr_is_v4mapped(&input6, &output4)); + // Output is unchanged. + ASSERT_EQ(memcmp(&expect4, &output4, sizeof(expect4)), 0); + + // Plain IPv4 input should also fail. + grpc_resolved_address input4 = MakeAddr4(kIPv4, sizeof(kIPv4)); + ASSERT_FALSE(grpc_sockaddr_is_v4mapped(&input4, nullptr)); +} + +TEST(SockAddrUtilsTest, SockAddrToV4Mapped) { + // IPv4 input should succeed. + grpc_resolved_address input4 = MakeAddr4(kIPv4, sizeof(kIPv4)); + grpc_resolved_address output6; + ASSERT_TRUE(grpc_sockaddr_to_v4mapped(&input4, &output6)); + grpc_resolved_address expect6 = MakeAddr6(kMapped, sizeof(kMapped)); + ASSERT_EQ(memcmp(&expect6, &output6, sizeof(output6)), 0); + + // IPv6 input should fail. + grpc_resolved_address input6 = MakeAddr6(kIPv6, sizeof(kIPv6)); + ASSERT_TRUE(!grpc_sockaddr_to_v4mapped(&input6, &output6)); + // Output is unchanged. + ASSERT_EQ(memcmp(&expect6, &output6, sizeof(output6)), 0); + + // Already-v4mapped input should also fail. + input6 = MakeAddr6(kMapped, sizeof(kMapped)); + ASSERT_TRUE(!grpc_sockaddr_to_v4mapped(&input6, &output6)); +} + +TEST(SockAddrUtilsTest, SockAddrIsWildCard) { + // Generate wildcards. + grpc_resolved_address wild4; + grpc_resolved_address wild6; + grpc_sockaddr_make_wildcards(555, &wild4, &wild6); + grpc_resolved_address wild_mapped; + ASSERT_TRUE(grpc_sockaddr_to_v4mapped(&wild4, &wild_mapped)); + + // Test 0.0.0.0:555 + int port = -1; + ASSERT_TRUE(grpc_sockaddr_is_wildcard(&wild4, &port)); + ASSERT_TRUE(port == 555); + grpc_sockaddr_in* wild4_addr = + reinterpret_cast(&wild4.addr); + memset(&wild4_addr->sin_addr.s_addr, 0xbd, 1); + ASSERT_FALSE(grpc_sockaddr_is_wildcard(&wild4, &port)); + + // Test [::]:555 + port = -1; + ASSERT_TRUE(grpc_sockaddr_is_wildcard(&wild6, &port)); + ASSERT_EQ(port, 555); + grpc_sockaddr_in6* wild6_addr = + reinterpret_cast(&wild6.addr); + memset(&wild6_addr->sin6_addr.s6_addr, 0xbd, 1); + ASSERT_FALSE(grpc_sockaddr_is_wildcard(&wild6, &port)); + + // Test [::ffff:0.0.0.0]:555 + port = -1; + ASSERT_TRUE(grpc_sockaddr_is_wildcard(&wild_mapped, &port)); + ASSERT_EQ(port, 555); + grpc_sockaddr_in6* wild_mapped_addr = + reinterpret_cast(&wild_mapped.addr); + memset(&wild_mapped_addr->sin6_addr.s6_addr, 0xbd, 1); + ASSERT_FALSE(grpc_sockaddr_is_wildcard(&wild_mapped, &port)); + + // Test AF_UNSPEC. + port = -1; + grpc_resolved_address phony; + memset(&phony, 0, sizeof(phony)); + ASSERT_FALSE(grpc_sockaddr_is_wildcard(&phony, &port)); + ASSERT_EQ(port, -1); +} + +TEST(SockAddrUtilsTest, SockAddrToString) { + errno = 0x7EADBEEF; + + grpc_resolved_address input4 = MakeAddr4(kIPv4, sizeof(kIPv4)); + EXPECT_EQ(grpc_sockaddr_to_string(&input4, false), "192.0.2.1:12345"); + EXPECT_EQ(grpc_sockaddr_to_string(&input4, true), "192.0.2.1:12345"); + EXPECT_EQ(grpc_sockaddr_to_uri(&input4), "ipv4:192.0.2.1:12345"); + + grpc_resolved_address input6 = MakeAddr6(kIPv6, sizeof(kIPv6)); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, false), "[2001:db8::1]:12345"); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, true), "[2001:db8::1]:12345"); + EXPECT_EQ(grpc_sockaddr_to_uri(&input6), "ipv6:[2001:db8::1]:12345"); + + SetIPv6ScopeId(&input6, 2); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, false), "[2001:db8::1%252]:12345"); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, true), "[2001:db8::1%252]:12345"); + EXPECT_EQ(grpc_sockaddr_to_uri(&input6), "ipv6:[2001:db8::1%252]:12345"); + + SetIPv6ScopeId(&input6, 101); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, false), + "[2001:db8::1%25101]:12345"); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, true), + "[2001:db8::1%25101]:12345"); + EXPECT_EQ(grpc_sockaddr_to_uri(&input6), "ipv6:[2001:db8::1%25101]:12345"); + + input6 = MakeAddr6(kMapped, sizeof(kMapped)); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, false), + "[::ffff:192.0.2.1]:12345"); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, true), "192.0.2.1:12345"); + EXPECT_EQ(grpc_sockaddr_to_uri(&input6), "ipv4:192.0.2.1:12345"); + + input6 = MakeAddr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, false), "[::fffe:c000:263]:12345"); + EXPECT_EQ(grpc_sockaddr_to_string(&input6, true), "[::fffe:c000:263]:12345"); + EXPECT_EQ(grpc_sockaddr_to_uri(&input6), "ipv6:[::fffe:c000:263]:12345"); + + grpc_resolved_address phony; + memset(&phony, 0, sizeof(phony)); + grpc_sockaddr* phony_addr = reinterpret_cast(phony.addr); + phony_addr->sa_family = 123; + EXPECT_EQ(grpc_sockaddr_to_string(&phony, false), "(sockaddr family=123)"); + EXPECT_EQ(grpc_sockaddr_to_string(&phony, true), "(sockaddr family=123)"); + EXPECT_TRUE(grpc_sockaddr_to_uri(&phony).empty()); +} + +TEST(SockAddrUtilsTest, SockAddrSetGetPort) { + grpc_resolved_address input4 = MakeAddr4(kIPv4, sizeof(kIPv4)); + ASSERT_EQ(grpc_sockaddr_get_port(&input4), 12345); + ASSERT_TRUE(grpc_sockaddr_set_port(&input4, 54321)); + ASSERT_EQ(grpc_sockaddr_get_port(&input4), 54321); + + grpc_resolved_address input6 = MakeAddr6(kIPv6, sizeof(kIPv6)); + ASSERT_EQ(grpc_sockaddr_get_port(&input6), 12345); + ASSERT_TRUE(grpc_sockaddr_set_port(&input6, 54321)); + ASSERT_EQ(grpc_sockaddr_get_port(&input6), 54321); + + grpc_resolved_address phony; + memset(&phony, 0, sizeof(phony)); + grpc_sockaddr* phony_addr = reinterpret_cast(phony.addr); + phony_addr->sa_family = 123; + ASSERT_EQ(grpc_sockaddr_get_port(&phony), false); + ASSERT_EQ(grpc_sockaddr_set_port(&phony, 1234), false); +} + +void VerifySocketAddressMatch(const std::string& ip_address, + const std::string& subnet, uint32_t mask_bits, + bool success) { + grpc_resolved_address addr; + ASSERT_EQ(grpc_string_to_sockaddr(&addr, ip_address.c_str(), false), + GRPC_ERROR_NONE); + // Setting the port has no effect on the match. + grpc_sockaddr_set_port(&addr, 12345); + grpc_resolved_address subnet_addr; + ASSERT_EQ(grpc_string_to_sockaddr(&subnet_addr, subnet.c_str(), false), + GRPC_ERROR_NONE); + grpc_sockaddr_mask_bits(&subnet_addr, mask_bits); + EXPECT_EQ(grpc_sockaddr_match_subnet(&addr, &subnet_addr, mask_bits), success) + << "IP=" << ip_address << " Subnet=" << subnet << " Mask=" << mask_bits; +} + +void VerifySocketAddressMatchSuccess(const std::string& ip_address, + const std::string& subnet, + uint32_t mask_bits) { + // If the IP address matches the subnet for a particular length, then it would + // match for all lengths [0, mask_bits] + for (uint32_t i = 0; i <= mask_bits; i++) { + VerifySocketAddressMatch(ip_address, subnet, i, true); + } +} + +void VerifySocketAddressMatchFailure(const std::string& ip_address, + const std::string& subnet, + uint32_t mask_bits) { + // If the IP address fails matching the subnet for a particular length, then + // it would also fail for all lengths [mask_bits, 128] + for (auto i = mask_bits; i <= 128; i++) { + VerifySocketAddressMatch(ip_address, subnet, i, false); + } +} + +TEST(SockAddrUtilsTest, SockAddrMatchSubnet) { + // IPv4 Tests + VerifySocketAddressMatchSuccess("192.168.1.1", "192.168.1.1", 32); + VerifySocketAddressMatchSuccess("255.255.255.255", "255.255.255.255", 32); + VerifySocketAddressMatchFailure("192.168.1.1", "192.168.1.2", 31); + VerifySocketAddressMatchFailure("192.168.1.1", "191.0.0.0", 8); + VerifySocketAddressMatchFailure("192.168.1.1", "0.0.0.0", 1); + // IPv6 Tests + VerifySocketAddressMatchSuccess("2001:db8::", "2001::", 16); + VerifySocketAddressMatchSuccess("2001:db8:cfe:134:3ab:3456:78:9", + "2001:db8:cfe:134:3ab:3456:78:9", 128); + VerifySocketAddressMatchSuccess("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", + "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", + 128); + VerifySocketAddressMatchFailure("2001:db8:cfe:134:3ab:3456:78:9", + "3001:2:3:4:5:6:7:8", 4); + VerifySocketAddressMatchFailure("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF", + "::", 1); +} + +} // namespace + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + int retval = RUN_ALL_TESTS(); + return retval; +} diff --git a/test/core/bad_client/bad_client.cc b/test/core/bad_client/bad_client.cc index 000215edf2d..c3a61ed4e2e 100644 --- a/test/core/bad_client/bad_client.cc +++ b/test/core/bad_client/bad_client.cc @@ -57,7 +57,7 @@ static void thd_func(void* arg) { } /* Sets the done_write event */ -static void set_done_write(void* arg, grpc_error* /*error*/) { +static void set_done_write(void* arg, grpc_error_handle /*error*/) { gpr_event* done_write = static_cast(arg); gpr_event_set(done_write, reinterpret_cast(1)); } @@ -70,7 +70,7 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { } /* Sets the read_done event */ -static void set_read_done(void* arg, grpc_error* /*error*/) { +static void set_read_done(void* arg, grpc_error_handle /*error*/) { gpr_event* read_done = static_cast(arg); gpr_event_set(read_done, reinterpret_cast(1)); } @@ -212,7 +212,7 @@ void grpc_run_bad_client_test( grpc_server_start(a.server); transport = grpc_create_chttp2_transport(nullptr, sfd.server, false); server_setup_transport(&a, transport); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); /* Bind fds to pollsets */ grpc_endpoint_add_to_pollset(sfd.client, grpc_cq_pollset(client_cq)); @@ -263,10 +263,7 @@ bool client_connection_preface_validator(grpc_slice_buffer* incoming, } const uint8_t* p = GRPC_SLICE_START_PTR(slice); /* Check the frame type (SETTINGS) */ - if (*(p + 3) != 4) { - return false; - } - return true; + return *(p + 3) == 4; } /* connection preface and settings frame to be sent by the client */ diff --git a/test/core/bad_connection/close_fd_test.cc b/test/core/bad_connection/close_fd_test.cc index 1c89ee72c11..2be36fcc61d 100644 --- a/test/core/bad_connection/close_fd_test.cc +++ b/test/core/bad_connection/close_fd_test.cc @@ -99,7 +99,7 @@ static void init_client() { transport = grpc_create_chttp2_transport(nullptr, g_ctx.ep->client, true); client_setup_transport(transport); GPR_ASSERT(g_ctx.client); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } static void init_server() { @@ -111,7 +111,7 @@ static void init_server() { grpc_server_start(g_ctx.server); transport = grpc_create_chttp2_transport(nullptr, g_ctx.ep->server, false); server_setup_transport(transport); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } static void test_init() { diff --git a/test/core/channel/channel_stack_builder_test.cc b/test/core/channel/channel_stack_builder_test.cc index b154ad205f0..409e91389e3 100644 --- a/test/core/channel/channel_stack_builder_test.cc +++ b/test/core/channel/channel_stack_builder_test.cc @@ -29,13 +29,13 @@ #include "src/core/lib/surface/channel_init.h" #include "test/core/util/test_config.h" -static grpc_error* channel_init_func(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +static grpc_error_handle channel_init_func( + grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } -static grpc_error* call_init_func(grpc_call_element* /*elem*/, - const grpc_call_element_args* /*args*/) { +static grpc_error_handle call_init_func( + grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { return GRPC_ERROR_NONE; } diff --git a/test/core/channel/channel_stack_test.cc b/test/core/channel/channel_stack_test.cc index 58f854b12fe..8c872c153f8 100644 --- a/test/core/channel/channel_stack_test.cc +++ b/test/core/channel/channel_stack_test.cc @@ -27,8 +27,8 @@ #include "src/core/lib/slice/slice_internal.h" #include "test/core/util/test_config.h" -static grpc_error* channel_init_func(grpc_channel_element* elem, - grpc_channel_element_args* args) { +static grpc_error_handle channel_init_func(grpc_channel_element* elem, + grpc_channel_element_args* args) { GPR_ASSERT(args->channel_args->num_args == 1); GPR_ASSERT(args->channel_args->args[0].type == GRPC_ARG_INTEGER); GPR_ASSERT(0 == strcmp(args->channel_args->args[0].key, "test_key")); @@ -39,8 +39,8 @@ static grpc_error* channel_init_func(grpc_channel_element* elem, return GRPC_ERROR_NONE; } -static grpc_error* call_init_func(grpc_call_element* elem, - const grpc_call_element_args* /*args*/) { +static grpc_error_handle call_init_func( + grpc_call_element* elem, const grpc_call_element_args* /*args*/) { ++*static_cast(elem->channel_data); *static_cast(elem->call_data) = 0; return GRPC_ERROR_NONE; @@ -64,12 +64,12 @@ static void channel_func(grpc_channel_element* elem, ++*static_cast(elem->channel_data); } -static void free_channel(void* arg, grpc_error* /*error*/) { +static void free_channel(void* arg, grpc_error_handle /*error*/) { grpc_channel_stack_destroy(static_cast(arg)); gpr_free(arg); } -static void free_call(void* arg, grpc_error* /*error*/) { +static void free_call(void* arg, grpc_error_handle /*error*/) { grpc_call_stack_destroy(static_cast(arg), nullptr, nullptr); gpr_free(arg); } @@ -127,7 +127,7 @@ static void test_create_channel_stack(void) { nullptr, /* arena */ nullptr, /* call_combiner */ }; - grpc_error* error = + grpc_error_handle error = grpc_call_stack_init(channel_stack, 1, free_call, call_stack, &args); GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(call_stack->count == 1); diff --git a/test/core/channel/channelz_test.cc b/test/core/channel/channelz_test.cc index fa8e6603931..cc17a333b6a 100644 --- a/test/core/channel/channelz_test.cc +++ b/test/core/channel/channelz_test.cc @@ -105,9 +105,9 @@ void ValidateGetTopChannels(size_t expected_channels) { std::string json_str = ChannelzRegistry::GetTopChannels(0); grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation( json_str.c_str()); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); // This check will naturally have to change when we support pagination. // tracked: https://github.com/grpc/grpc/issues/16019. @@ -125,9 +125,9 @@ void ValidateGetServers(size_t expected_servers) { std::string json_str = ChannelzRegistry::GetServers(0); grpc::testing::ValidateGetServersResponseProtoJsonTranslation( json_str.c_str()); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); // This check will naturally have to change when we support pagination. // tracked: https://github.com/grpc/grpc/issues/16019. @@ -207,9 +207,9 @@ void ValidateChildInteger(const Json::Object& object, const std::string& key, void ValidateCounters(const std::string& json_str, const ValidateChannelDataArgs& args) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(json.type(), Json::Type::OBJECT); Json::Object* object = json.mutable_object(); Json& data = (*object)["data"]; @@ -365,9 +365,9 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsPagination) { std::string json_str = ChannelzRegistry::GetTopChannels(0); grpc::testing::ValidateGetTopChannelsResponseProtoJsonTranslation( json_str.c_str()); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); // 100 is the pagination limit. ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 100); @@ -378,7 +378,7 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsPagination) { json_str.c_str()); error = GRPC_ERROR_NONE; parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); ValidateJsonArraySize((*parsed_json.mutable_object())["channel"], 50); ValidateJsonEnd(parsed_json, true); @@ -390,9 +390,9 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidCheck) { ChannelFixture channels[kNumChannels]; (void)channels; // suppress unused variable error std::string json_str = ChannelzRegistry::GetTopChannels(0); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); Json& array = (*parsed_json.mutable_object())["channel"]; ValidateJsonArraySize(array, kNumChannels); @@ -410,9 +410,9 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMiddleUuidCheck) { (void)channels; // suppress unused variable error // Only query for the end of the channels. std::string json_str = ChannelzRegistry::GetTopChannels(kMidQuery); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); Json& array = (*parsed_json.mutable_object())["channel"]; ValidateJsonArraySize(array, kNumChannels - kMidQuery + 1); @@ -432,9 +432,9 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsNoHitUuid) { (void)channels; // suppress unused variable error // Query in the middle of the server channels. std::string json_str = ChannelzRegistry::GetTopChannels(45); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); Json& array = (*parsed_json.mutable_object())["channel"]; ValidateJsonArraySize(array, 10); @@ -453,9 +453,9 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMoreGaps) { ChannelFixture channel_with_uuid5; // Current state of list: [1, NULL, 3, NULL, 5] std::string json_str = ChannelzRegistry::GetTopChannels(2); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); Json array = (*parsed_json.mutable_object())["channel"]; ValidateJsonArraySize(array, 2); @@ -465,7 +465,7 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsMoreGaps) { json_str = ChannelzRegistry::GetTopChannels(4); error = GRPC_ERROR_NONE; parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); array = (*parsed_json.mutable_object())["channel"]; ValidateJsonArraySize(array, 1); @@ -486,9 +486,9 @@ TEST_F(ChannelzRegistryBasedTest, GetTopChannelsUuidAfterCompaction) { } } std::string json_str = ChannelzRegistry::GetTopChannels(0); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json parsed_json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), Json::Type::OBJECT); Json& array = (*parsed_json.mutable_object())["channel"]; ValidateJsonArraySize(array, kLoopIterations); diff --git a/test/core/client_channel/certificate_provider_registry_test.cc b/test/core/client_channel/certificate_provider_registry_test.cc index 0c6b6d03a5c..ef33b14b69e 100644 --- a/test/core/client_channel/certificate_provider_registry_test.cc +++ b/test/core/client_channel/certificate_provider_registry_test.cc @@ -33,7 +33,7 @@ class FakeCertificateProviderFactory1 : public CertificateProviderFactory { const char* name() const override { return "fake1"; } RefCountedPtr CreateCertificateProviderConfig( - const Json& /*config_json*/, grpc_error** /*error*/) override { + const Json& /*config_json*/, grpc_error_handle* /*error*/) override { return nullptr; } @@ -48,7 +48,7 @@ class FakeCertificateProviderFactory2 : public CertificateProviderFactory { const char* name() const override { return "fake2"; } RefCountedPtr CreateCertificateProviderConfig( - const Json& /*config_json*/, grpc_error** /*error*/) override { + const Json& /*config_json*/, grpc_error_handle* /*error*/) override { return nullptr; } diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc index f79031dd55a..d82d92d459f 100644 --- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.cc @@ -41,7 +41,7 @@ static void my_resolve_address(const char* addr, const char* /*default_port*/, grpc_resolved_addresses** addrs) { gpr_mu_lock(&g_mu); GPR_ASSERT(0 == strcmp("test", addr)); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (g_fail_resolution) { g_fail_resolution = false; gpr_mu_unlock(&g_mu); @@ -69,7 +69,7 @@ static grpc_ares_request* my_dns_lookup_ares_locked( std::shared_ptr /*combiner*/) { // NOLINT gpr_mu_lock(&g_mu); GPR_ASSERT(0 == strcmp("test", addr)); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (g_fail_resolution) { g_fail_resolution = false; gpr_mu_unlock(&g_mu); @@ -113,7 +113,7 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler { public: struct ResolverOutput { grpc_core::Resolver::Result result; - grpc_error* error = nullptr; + grpc_error_handle error = GRPC_ERROR_NONE; gpr_event ev; ResolverOutput() { gpr_event_init(&ev); } @@ -133,7 +133,7 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler { gpr_event_set(&output->ev, reinterpret_cast(1)); } - void ReturnError(grpc_error* error) override { + void ReturnError(grpc_error_handle error) override { ResolverOutput* output = reinterpret_cast(gpr_atm_acq_load(&output_)); GPR_ASSERT(output != nullptr); diff --git a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc index cfedceba0df..ed5402216ad 100644 --- a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc @@ -24,9 +24,9 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/memory.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/work_serializer.h" #include "test/core/util/test_config.h" @@ -86,7 +86,7 @@ static void test_resolve_address_impl(const char* name, grpc_core::ExecCtx::Get()->InvalidateNow(); } -static grpc_error* test_blocking_resolve_address_impl( +static grpc_error_handle test_blocking_resolve_address_impl( const char* name, const char* default_port, grpc_resolved_addresses** addresses) { return default_resolve_address->blocking_resolve_address(name, default_port, @@ -136,7 +136,7 @@ static gpr_timespec test_deadline(void) { return grpc_timeout_seconds_to_deadline(100); } -static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} +static void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} static void iomgr_args_init(iomgr_args* args) { gpr_event_init(&args->ev); @@ -212,8 +212,9 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler { cb(state); } - void ReturnError(grpc_error* error) override { - gpr_log(GPR_ERROR, "resolver returned error: %s", grpc_error_string(error)); + void ReturnError(grpc_error_handle error) override { + gpr_log(GPR_ERROR, "resolver returned error: %s", + grpc_error_std_string(error).c_str()); GPR_ASSERT(false); } diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc index 6aa6371b938..7bc867eb541 100644 --- a/test/core/client_channel/resolvers/dns_resolver_test.cc +++ b/test/core/client_channel/resolvers/dns_resolver_test.cc @@ -32,7 +32,7 @@ static std::shared_ptr* g_work_serializer; class TestResultHandler : public grpc_core::Resolver::ResultHandler { void ReturnResult(grpc_core::Resolver::Result /*result*/) override {} - void ReturnError(grpc_error* /*error*/) override {} + void ReturnError(grpc_error_handle /*error*/) override {} }; static void test_succeeds(grpc_core::ResolverFactory* factory, diff --git a/test/core/client_channel/resolvers/fake_resolver_test.cc b/test/core/client_channel/resolvers/fake_resolver_test.cc index 5dde6bea07b..0d208440306 100644 --- a/test/core/client_channel/resolvers/fake_resolver_test.cc +++ b/test/core/client_channel/resolvers/fake_resolver_test.cc @@ -28,9 +28,9 @@ #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" @@ -58,7 +58,7 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler { ev_ = nullptr; } - void ReturnError(grpc_error* /*error*/) override {} + void ReturnError(grpc_error_handle /*error*/) override {} private: grpc_core::Resolver::Result expected_; diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.cc b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc index 9dfd883ef77..8b0692503f3 100644 --- a/test/core/client_channel/resolvers/sockaddr_resolver_test.cc +++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.cc @@ -34,7 +34,9 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler { public: void ReturnResult(grpc_core::Resolver::Result /*result*/) override {} - void ReturnError(grpc_error* error) override { GRPC_ERROR_UNREF(error); } + void ReturnError(grpc_error_handle error) override { + GRPC_ERROR_UNREF(error); + } }; static void test_succeeds(grpc_core::ResolverFactory* factory, diff --git a/test/core/client_channel/service_config_test.cc b/test/core/client_channel/service_config_test.cc index cc170c008e9..fb5e554f8c5 100644 --- a/test/core/client_channel/service_config_test.cc +++ b/test/core/client_channel/service_config_test.cc @@ -23,6 +23,7 @@ #include #include "src/core/ext/filters/client_channel/resolver_result_parsing.h" +#include "src/core/ext/filters/client_channel/retry_service_config.h" #include "src/core/ext/filters/client_channel/service_config.h" #include "src/core/ext/filters/client_channel/service_config_parser.h" #include "src/core/ext/filters/message_size/message_size_filter.h" @@ -33,6 +34,10 @@ namespace grpc_core { namespace testing { +// +// ServiceConfig tests +// + // Set this channel arg to true to disable parsing. #define GRPC_ARG_DISABLE_PARSING "disable_parsing" @@ -50,7 +55,7 @@ class TestParser1 : public ServiceConfigParser::Parser { public: std::unique_ptr ParseGlobalParams( const grpc_channel_args* args, const Json& json, - grpc_error** error) override { + grpc_error_handle* error) override { GPR_DEBUG_ASSERT(error != nullptr); if (grpc_channel_args_find_bool(args, GRPC_ARG_DISABLE_PARSING, false)) { return nullptr; @@ -86,7 +91,7 @@ class TestParser2 : public ServiceConfigParser::Parser { public: std::unique_ptr ParsePerMethodParams( const grpc_channel_args* args, const Json& json, - grpc_error** error) override { + grpc_error_handle* error) override { GPR_DEBUG_ASSERT(error != nullptr); if (grpc_channel_args_find_bool(args, GRPC_ARG_DISABLE_PARSING, false)) { return nullptr; @@ -123,7 +128,7 @@ class ErrorParser : public ServiceConfigParser::Parser { public: std::unique_ptr ParsePerMethodParams( const grpc_channel_args* /*arg*/, const Json& /*json*/, - grpc_error** error) override { + grpc_error_handle* error) override { GPR_DEBUG_ASSERT(error != nullptr); *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(MethodError()); return nullptr; @@ -131,7 +136,7 @@ class ErrorParser : public ServiceConfigParser::Parser { std::unique_ptr ParseGlobalParams( const grpc_channel_args* /*arg*/, const Json& /*json*/, - grpc_error** error) override { + grpc_error_handle* error) override { GPR_DEBUG_ASSERT(error != nullptr); *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(GlobalError()); return nullptr; @@ -158,18 +163,18 @@ class ServiceConfigTest : public ::testing::Test { TEST_F(ServiceConfigTest, ErrorCheck1) { const char* test_json = ""; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex("JSON parse error")); GRPC_ERROR_UNREF(error); } TEST_F(ServiceConfigTest, BasicTest1) { const char* test_json = "{}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); } TEST_F(ServiceConfigTest, SkipMethodConfigWithNoNameOrEmptyName) { @@ -179,9 +184,9 @@ TEST_F(ServiceConfigTest, SkipMethodConfigWithNoNameOrEmptyName) { " {\"name\":[], \"method_param\":1}," " {\"name\":[{\"service\":\"TestServ\"}], \"method_param\":2}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector( grpc_slice_from_static_string("/TestServ/TestMethod")); ASSERT_NE(vector_ptr, nullptr); @@ -195,10 +200,10 @@ TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNames) { " {\"name\":[{\"service\":\"TestServ\"}]}," " {\"name\":[{\"service\":\"TestServ\"}]}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("Service config parsing error.*referenced_errors" ".*Method Params.*referenced_errors" ".*methodConfig.*referenced_errors" @@ -212,10 +217,10 @@ TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithNullMethod) { " {\"name\":[{\"service\":\"TestServ\",\"method\":null}]}," " {\"name\":[{\"service\":\"TestServ\"}]}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("Service config parsing error.*referenced_errors" ".*Method Params.*referenced_errors" ".*methodConfig.*referenced_errors" @@ -229,10 +234,10 @@ TEST_F(ServiceConfigTest, ErrorDuplicateMethodConfigNamesWithEmptyMethod) { " {\"name\":[{\"service\":\"TestServ\",\"method\":\"\"}]}," " {\"name\":[{\"service\":\"TestServ\"}]}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("Service config parsing error.*referenced_errors" ".*Method Params.*referenced_errors" ".*methodConfig.*referenced_errors" @@ -246,10 +251,10 @@ TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigs) { " {\"name\":[{}]}," " {\"name\":[{}]}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("Service config parsing error.*referenced_errors" ".*Method Params.*referenced_errors" ".*methodConfig.*referenced_errors" @@ -263,10 +268,10 @@ TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithNullService) { " {\"name\":[{\"service\":null}]}," " {\"name\":[{}]}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("Service config parsing error.*referenced_errors" ".*Method Params.*referenced_errors" ".*methodConfig.*referenced_errors" @@ -280,10 +285,10 @@ TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithEmptyService) { " {\"name\":[{\"service\":\"\"}]}," " {\"name\":[{}]}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("Service config parsing error.*referenced_errors" ".*Method Params.*referenced_errors" ".*methodConfig.*referenced_errors" @@ -294,16 +299,16 @@ TEST_F(ServiceConfigTest, ErrorDuplicateDefaultMethodConfigsWithEmptyService) { TEST_F(ServiceConfigTest, ValidMethodConfig) { const char* test_json = "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}]}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); } TEST_F(ServiceConfigTest, Parser1BasicTest1) { const char* test_json = "{\"global_param\":5}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ((static_cast(svc_cfg->GetGlobalParsedConfig(0))) ->value(), 5); @@ -314,9 +319,9 @@ TEST_F(ServiceConfigTest, Parser1BasicTest1) { TEST_F(ServiceConfigTest, Parser1BasicTest2) { const char* test_json = "{\"global_param\":1000}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ((static_cast(svc_cfg->GetGlobalParsedConfig(0))) ->value(), 1000); @@ -327,17 +332,17 @@ TEST_F(ServiceConfigTest, Parser1DisabledViaChannelArg) { const_cast(GRPC_ARG_DISABLE_PARSING), 1); grpc_channel_args args = {1, &arg}; const char* test_json = "{\"global_param\":5}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(&args, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(svc_cfg->GetGlobalParsedConfig(0), nullptr); } TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) { const char* test_json = "{\"global_param\":\"5\"}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex(absl::StrCat( "Service config parsing error.*referenced_errors.*" "Global Params.*referenced_errors.*", @@ -347,9 +352,9 @@ TEST_F(ServiceConfigTest, Parser1ErrorInvalidType) { TEST_F(ServiceConfigTest, Parser1ErrorInvalidValue) { const char* test_json = "{\"global_param\":-5}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex(absl::StrCat( "Service config parsing error.*referenced_errors.*" "Global Params.*referenced_errors.*", @@ -361,9 +366,9 @@ TEST_F(ServiceConfigTest, Parser2BasicTest) { const char* test_json = "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " "\"method_param\":5}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector( grpc_slice_from_static_string("/TestServ/TestMethod")); ASSERT_NE(vector_ptr, nullptr); @@ -378,9 +383,9 @@ TEST_F(ServiceConfigTest, Parser2DisabledViaChannelArg) { const char* test_json = "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " "\"method_param\":5}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(&args, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector( grpc_slice_from_static_string("/TestServ/TestMethod")); ASSERT_NE(vector_ptr, nullptr); @@ -392,9 +397,9 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidType) { const char* test_json = "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " "\"method_param\":\"5\"}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex(absl::StrCat( "Service config parsing error.*referenced_errors\":\\[.*" "Method Params.*referenced_errors.*methodConfig.*" @@ -407,9 +412,9 @@ TEST_F(ServiceConfigTest, Parser2ErrorInvalidValue) { const char* test_json = "{\"methodConfig\": [{\"name\":[{\"service\":\"TestServ\"}], " "\"method_param\":-5}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex(absl::StrCat( "Service config parsing error.*referenced_errors\":\\[.*" "Method Params.*referenced_errors.*methodConfig.*" @@ -435,10 +440,10 @@ class ErroredParsersScopingTest : public ::testing::Test { TEST_F(ErroredParsersScopingTest, GlobalParams) { const char* test_json = "{}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex(absl::StrCat( "Service config parsing error.*referenced_errors\":\\[.*" "Global Params.*referenced_errors.*", @@ -448,10 +453,10 @@ TEST_F(ErroredParsersScopingTest, GlobalParams) { TEST_F(ErroredParsersScopingTest, MethodParams) { const char* test_json = "{\"methodConfig\": [{}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex(absl::StrCat( "Service config parsing error.*referenced_errors\":\\[.*" "Global Params.*referenced_errors.*", @@ -462,6 +467,10 @@ TEST_F(ErroredParsersScopingTest, MethodParams) { GRPC_ERROR_UNREF(error); } +// +// client_channel parser tests +// + class ClientChannelParserTest : public ::testing::Test { protected: void SetUp() override { @@ -476,9 +485,9 @@ class ClientChannelParserTest : public ::testing::Test { TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigPickFirst) { const char* test_json = "{\"loadBalancingConfig\": [{\"pick_first\":{}}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* parsed_config = static_cast( svc_cfg->GetGlobalParsedConfig(0)); @@ -489,9 +498,9 @@ TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigPickFirst) { TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigRoundRobin) { const char* test_json = "{\"loadBalancingConfig\": [{\"round_robin\":{}}, {}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto parsed_config = static_cast( svc_cfg->GetGlobalParsedConfig(0)); @@ -503,9 +512,9 @@ TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigGrpclb) { const char* test_json = "{\"loadBalancingConfig\": " "[{\"grpclb\":{\"childPolicy\":[{\"pick_first\":{}}]}}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* parsed_config = static_cast( svc_cfg->GetGlobalParsedConfig(0)); @@ -526,9 +535,9 @@ TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigXds) { " } }\n" " ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* parsed_config = static_cast( svc_cfg->GetGlobalParsedConfig(0)); @@ -538,9 +547,9 @@ TEST_F(ClientChannelParserTest, ValidLoadBalancingConfigXds) { TEST_F(ClientChannelParserTest, UnknownLoadBalancingConfig) { const char* test_json = "{\"loadBalancingConfig\": [{\"unknown\":{}}]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Global Params.*referenced_errors.*" @@ -556,9 +565,9 @@ TEST_F(ClientChannelParserTest, InvalidGrpclbLoadBalancingConfig) { " {\"grpclb\":{\"childPolicy\":1}}," " {\"round_robin\":{}}" "]}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Global Params.*referenced_errors.*" @@ -572,9 +581,9 @@ TEST_F(ClientChannelParserTest, InvalidGrpclbLoadBalancingConfig) { TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicy) { const char* test_json = "{\"loadBalancingPolicy\":\"pick_first\"}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* parsed_config = static_cast( svc_cfg->GetGlobalParsedConfig(0)); @@ -583,9 +592,9 @@ TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicy) { TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicyAllCaps) { const char* test_json = "{\"loadBalancingPolicy\":\"PICK_FIRST\"}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* parsed_config = static_cast( svc_cfg->GetGlobalParsedConfig(0)); @@ -594,9 +603,9 @@ TEST_F(ClientChannelParserTest, ValidLoadBalancingPolicyAllCaps) { TEST_F(ClientChannelParserTest, UnknownLoadBalancingPolicy) { const char* test_json = "{\"loadBalancingPolicy\":\"unknown\"}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Global Params.*referenced_errors.*" @@ -608,9 +617,9 @@ TEST_F(ClientChannelParserTest, UnknownLoadBalancingPolicy) { TEST_F(ClientChannelParserTest, LoadBalancingPolicyXdsNotAllowed) { const char* test_json = "{\"loadBalancingPolicy\":\"xds_cluster_resolver_experimental\"}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Global Params.*referenced_errors.*" @@ -621,84 +630,6 @@ TEST_F(ClientChannelParserTest, LoadBalancingPolicyXdsNotAllowed) { GRPC_ERROR_UNREF(error); } -TEST_F(ClientChannelParserTest, ValidRetryThrottling) { - const char* test_json = - "{\n" - " \"retryThrottling\": {\n" - " \"maxTokens\": 2,\n" - " \"tokenRatio\": 1.0\n" - " }\n" - "}"; - grpc_error* error = GRPC_ERROR_NONE; - auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); - const auto* parsed_config = - static_cast( - svc_cfg->GetGlobalParsedConfig(0)); - const auto retryThrottling = parsed_config->retry_throttling(); - ASSERT_TRUE(retryThrottling.has_value()); - EXPECT_EQ(retryThrottling.value().max_milli_tokens, 2000); - EXPECT_EQ(retryThrottling.value().milli_token_ratio, 1000); -} - -TEST_F(ClientChannelParserTest, RetryThrottlingMissingFields) { - const char* test_json = - "{\n" - " \"retryThrottling\": {\n" - " }\n" - "}"; - grpc_error* error = GRPC_ERROR_NONE; - auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), - ::testing::ContainsRegex( - "Service config parsing error.*referenced_errors.*" - "Global Params.*referenced_errors.*" - "Client channel global parser.*referenced_errors.*" - "field:retryThrottling field:maxTokens error:Not found.*" - "field:retryThrottling field:tokenRatio error:Not found")); - GRPC_ERROR_UNREF(error); -} - -TEST_F(ClientChannelParserTest, InvalidRetryThrottlingNegativeMaxTokens) { - const char* test_json = - "{\n" - " \"retryThrottling\": {\n" - " \"maxTokens\": -2,\n" - " \"tokenRatio\": 1.0\n" - " }\n" - "}"; - grpc_error* error = GRPC_ERROR_NONE; - auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), - ::testing::ContainsRegex( - "Service config parsing error.*referenced_errors.*" - "Global Params.*referenced_errors.*" - "Client channel global parser.*referenced_errors.*" - "field:retryThrottling field:maxTokens error:should " - "be greater than zero")); - GRPC_ERROR_UNREF(error); -} - -TEST_F(ClientChannelParserTest, InvalidRetryThrottlingInvalidTokenRatio) { - const char* test_json = - "{\n" - " \"retryThrottling\": {\n" - " \"maxTokens\": 2,\n" - " \"tokenRatio\": -1\n" - " }\n" - "}"; - grpc_error* error = GRPC_ERROR_NONE; - auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), - ::testing::ContainsRegex( - "Service config parsing error.*referenced_errors.*" - "Global Params.*referenced_errors.*" - "Client channel global parser.*referenced_errors.*" - "field:retryThrottling field:tokenRatio " - "error:Failed parsing")); - GRPC_ERROR_UNREF(error); -} - TEST_F(ClientChannelParserTest, ValidTimeout) { const char* test_json = "{\n" @@ -709,9 +640,9 @@ TEST_F(ClientChannelParserTest, ValidTimeout) { " \"timeout\": \"5s\"\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector( grpc_slice_from_static_string("/TestServ/TestMethod")); ASSERT_NE(vector_ptr, nullptr); @@ -732,9 +663,9 @@ TEST_F(ClientChannelParserTest, InvalidTimeout) { " \"timeout\": \"5sec\"\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" @@ -755,9 +686,9 @@ TEST_F(ClientChannelParserTest, ValidWaitForReady) { " \"waitForReady\": true\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector( grpc_slice_from_static_string("/TestServ/TestMethod")); ASSERT_NE(vector_ptr, nullptr); @@ -784,9 +715,9 @@ TEST_F(ClientChannelParserTest, InvalidWaitForReady) { " \"waitForReady\": \"true\"\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" @@ -796,7 +727,136 @@ TEST_F(ClientChannelParserTest, InvalidWaitForReady) { GRPC_ERROR_UNREF(error); } -TEST_F(ClientChannelParserTest, ValidRetryPolicy) { +TEST_F(ClientChannelParserTest, ValidHealthCheck) { + const char* test_json = + "{\n" + " \"healthCheckConfig\": {\n" + " \"serviceName\": \"health_check_service_name\"\n" + " }\n" + "}"; + grpc_error_handle error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); + const auto* parsed_config = + static_cast( + svc_cfg->GetGlobalParsedConfig(0)); + ASSERT_NE(parsed_config, nullptr); + EXPECT_EQ(parsed_config->health_check_service_name(), + "health_check_service_name"); +} + +TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) { + const char* test_json = + "{\n" + " \"healthCheckConfig\": {\n" + " \"serviceName\": \"health_check_service_name\"\n" + " },\n" + " \"healthCheckConfig\": {\n" + " \"serviceName\": \"health_check_service_name1\"\n" + " }\n" + "}"; + grpc_error_handle error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); + EXPECT_THAT(grpc_error_std_string(error), + ::testing::ContainsRegex( + "JSON parsing failed.*referenced_errors.*" + "duplicate key \"healthCheckConfig\" at index 104")); + GRPC_ERROR_UNREF(error); +} + +// +// retry parser tests +// + +class RetryParserTest : public ::testing::Test { + protected: + void SetUp() override { + ServiceConfigParser::Shutdown(); + ServiceConfigParser::Init(); + EXPECT_EQ(ServiceConfigParser::RegisterParser( + absl::make_unique()), + 0); + } +}; + +TEST_F(RetryParserTest, ValidRetryThrottling) { + const char* test_json = + "{\n" + " \"retryThrottling\": {\n" + " \"maxTokens\": 2,\n" + " \"tokenRatio\": 1.0\n" + " }\n" + "}"; + grpc_error_handle error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); + const auto* parsed_config = + static_cast( + svc_cfg->GetGlobalParsedConfig(0)); + ASSERT_NE(parsed_config, nullptr); + EXPECT_EQ(parsed_config->max_milli_tokens(), 2000); + EXPECT_EQ(parsed_config->milli_token_ratio(), 1000); +} + +TEST_F(RetryParserTest, RetryThrottlingMissingFields) { + const char* test_json = + "{\n" + " \"retryThrottling\": {\n" + " }\n" + "}"; + grpc_error_handle error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); + EXPECT_THAT(grpc_error_std_string(error), + ::testing::ContainsRegex( + "Service config parsing error.*referenced_errors.*" + "Global Params.*referenced_errors.*" + "retryThrottling.*referenced_errors.*" + "field:retryThrottling field:maxTokens error:Not found.*" + "field:retryThrottling field:tokenRatio error:Not found")); + GRPC_ERROR_UNREF(error); +} + +TEST_F(RetryParserTest, InvalidRetryThrottlingNegativeMaxTokens) { + const char* test_json = + "{\n" + " \"retryThrottling\": {\n" + " \"maxTokens\": -2,\n" + " \"tokenRatio\": 1.0\n" + " }\n" + "}"; + grpc_error_handle error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); + EXPECT_THAT(grpc_error_std_string(error), + ::testing::ContainsRegex( + "Service config parsing error.*referenced_errors.*" + "Global Params.*referenced_errors.*" + "retryThrottling.*referenced_errors.*" + "field:retryThrottling field:maxTokens error:should " + "be greater than zero")); + GRPC_ERROR_UNREF(error); +} + +TEST_F(RetryParserTest, InvalidRetryThrottlingInvalidTokenRatio) { + const char* test_json = + "{\n" + " \"retryThrottling\": {\n" + " \"maxTokens\": 2,\n" + " \"tokenRatio\": -1\n" + " }\n" + "}"; + grpc_error_handle error = GRPC_ERROR_NONE; + auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); + EXPECT_THAT(grpc_error_std_string(error), + ::testing::ContainsRegex( + "Service config parsing error.*referenced_errors.*" + "Global Params.*referenced_errors.*" + "retryThrottling.*referenced_errors.*" + "field:retryThrottling field:tokenRatio " + "error:Failed parsing")); + GRPC_ERROR_UNREF(error); +} + +TEST_F(RetryParserTest, ValidRetryPolicy) { const char* test_json = "{\n" " \"methodConfig\": [ {\n" @@ -812,25 +872,25 @@ TEST_F(ClientChannelParserTest, ValidRetryPolicy) { " }\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector( grpc_slice_from_static_string("/TestServ/TestMethod")); ASSERT_NE(vector_ptr, nullptr); const auto* parsed_config = - static_cast( + static_cast( ((*vector_ptr)[0]).get()); - ASSERT_NE(parsed_config->retry_policy(), nullptr); - EXPECT_EQ(parsed_config->retry_policy()->max_attempts, 3); - EXPECT_EQ(parsed_config->retry_policy()->initial_backoff, 1000); - EXPECT_EQ(parsed_config->retry_policy()->max_backoff, 120000); - EXPECT_EQ(parsed_config->retry_policy()->backoff_multiplier, 1.6f); - EXPECT_TRUE(parsed_config->retry_policy()->retryable_status_codes.Contains( - GRPC_STATUS_ABORTED)); + ASSERT_NE(parsed_config, nullptr); + EXPECT_EQ(parsed_config->max_attempts(), 3); + EXPECT_EQ(parsed_config->initial_backoff(), 1000); + EXPECT_EQ(parsed_config->max_backoff(), 120000); + EXPECT_EQ(parsed_config->backoff_multiplier(), 1.6f); + EXPECT_TRUE( + parsed_config->retryable_status_codes().Contains(GRPC_STATUS_ABORTED)); } -TEST_F(ClientChannelParserTest, InvalidRetryPolicyMaxAttempts) { +TEST_F(RetryParserTest, InvalidRetryPolicyMaxAttempts) { const char* test_json = "{\n" " \"methodConfig\": [ {\n" @@ -846,20 +906,19 @@ TEST_F(ClientChannelParserTest, InvalidRetryPolicyMaxAttempts) { " }\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" "methodConfig.*referenced_errors.*" - "Client channel parser.*referenced_errors.*" "retryPolicy.*referenced_errors.*" "field:maxAttempts error:should be at least 2")); GRPC_ERROR_UNREF(error); } -TEST_F(ClientChannelParserTest, InvalidRetryPolicyInitialBackoff) { +TEST_F(RetryParserTest, InvalidRetryPolicyInitialBackoff) { const char* test_json = "{\n" " \"methodConfig\": [ {\n" @@ -875,21 +934,20 @@ TEST_F(ClientChannelParserTest, InvalidRetryPolicyInitialBackoff) { " }\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" "methodConfig.*referenced_errors.*" - "Client channel parser.*referenced_errors.*" "retryPolicy.*referenced_errors.*" "field:initialBackoff error:type should be STRING of the " "form given by google.proto.Duration")); GRPC_ERROR_UNREF(error); } -TEST_F(ClientChannelParserTest, InvalidRetryPolicyMaxBackoff) { +TEST_F(RetryParserTest, InvalidRetryPolicyMaxBackoff) { const char* test_json = "{\n" " \"methodConfig\": [ {\n" @@ -905,21 +963,20 @@ TEST_F(ClientChannelParserTest, InvalidRetryPolicyMaxBackoff) { " }\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" "methodConfig.*referenced_errors.*" - "Client channel parser.*referenced_errors.*" "retryPolicy.*referenced_errors.*" "field:maxBackoff error:type should be STRING of the form " "given by google.proto.Duration")); GRPC_ERROR_UNREF(error); } -TEST_F(ClientChannelParserTest, InvalidRetryPolicyBackoffMultiplier) { +TEST_F(RetryParserTest, InvalidRetryPolicyBackoffMultiplier) { const char* test_json = "{\n" " \"methodConfig\": [ {\n" @@ -935,20 +992,19 @@ TEST_F(ClientChannelParserTest, InvalidRetryPolicyBackoffMultiplier) { " }\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" "methodConfig.*referenced_errors.*" - "Client channel parser.*referenced_errors.*" "retryPolicy.*referenced_errors.*" "field:backoffMultiplier error:should be of type number")); GRPC_ERROR_UNREF(error); } -TEST_F(ClientChannelParserTest, InvalidRetryPolicyRetryableStatusCodes) { +TEST_F(RetryParserTest, InvalidRetryPolicyRetryableStatusCodes) { const char* test_json = "{\n" " \"methodConfig\": [ {\n" @@ -964,55 +1020,21 @@ TEST_F(ClientChannelParserTest, InvalidRetryPolicyRetryableStatusCodes) { " }\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" "methodConfig.*referenced_errors.*" - "Client channel parser.*referenced_errors.*" "retryPolicy.*referenced_errors.*" "field:retryableStatusCodes error:should be non-empty")); GRPC_ERROR_UNREF(error); } -TEST_F(ClientChannelParserTest, ValidHealthCheck) { - const char* test_json = - "{\n" - " \"healthCheckConfig\": {\n" - " \"serviceName\": \"health_check_service_name\"\n" - " }\n" - "}"; - grpc_error* error = GRPC_ERROR_NONE; - auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); - const auto* parsed_config = - static_cast( - svc_cfg->GetGlobalParsedConfig(0)); - ASSERT_NE(parsed_config, nullptr); - EXPECT_EQ(parsed_config->health_check_service_name(), - "health_check_service_name"); -} - -TEST_F(ClientChannelParserTest, InvalidHealthCheckMultipleEntries) { - const char* test_json = - "{\n" - " \"healthCheckConfig\": {\n" - " \"serviceName\": \"health_check_service_name\"\n" - " },\n" - " \"healthCheckConfig\": {\n" - " \"serviceName\": \"health_check_service_name1\"\n" - " }\n" - "}"; - grpc_error* error = GRPC_ERROR_NONE; - auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), - ::testing::ContainsRegex( - "JSON parsing failed.*referenced_errors.*" - "duplicate key \"healthCheckConfig\" at index 104")); - GRPC_ERROR_UNREF(error); -} +// +// message_size parser tests +// class MessageSizeParserTest : public ::testing::Test { protected: @@ -1036,9 +1058,9 @@ TEST_F(MessageSizeParserTest, Valid) { " \"maxResponseMessageBytes\": 1024\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); const auto* vector_ptr = svc_cfg->GetMethodParsedConfigVector( grpc_slice_from_static_string("/TestServ/TestMethod")); ASSERT_NE(vector_ptr, nullptr); @@ -1059,9 +1081,9 @@ TEST_F(MessageSizeParserTest, InvalidMaxRequestMessageBytes) { " \"maxRequestMessageBytes\": -1024\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" @@ -1081,9 +1103,9 @@ TEST_F(MessageSizeParserTest, InvalidMaxResponseMessageBytes) { " \"maxResponseMessageBytes\": {}\n" " } ]\n" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; auto svc_cfg = ServiceConfig::Create(nullptr, test_json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "Service config parsing error.*referenced_errors.*" "Method Params.*referenced_errors.*" diff --git a/test/core/end2end/bad_server_response_test.cc b/test/core/end2end/bad_server_response_test.cc index cb5427fe837..b4e27075d7d 100644 --- a/test/core/end2end/bad_server_response_test.cc +++ b/test/core/end2end/bad_server_response_test.cc @@ -95,12 +95,13 @@ static grpc_closure on_write; static void* tag(intptr_t t) { return reinterpret_cast(t); } -static void done_write(void* /*arg*/, grpc_error* error) { +static void done_write(void* /*arg*/, grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); gpr_atm_rel_store(&state.done_atm, 1); } -static void done_writing_settings_frame(void* /* arg */, grpc_error* error) { +static void done_writing_settings_frame(void* /* arg */, + grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); grpc_endpoint_read(state.tcp, &state.temp_incoming_buffer, &on_read, /*urgent=*/false); @@ -115,9 +116,10 @@ static void handle_write() { grpc_endpoint_write(state.tcp, &state.outgoing_buffer, &on_write, nullptr); } -static void handle_read(void* /*arg*/, grpc_error* error) { +static void handle_read(void* /*arg*/, grpc_error_handle error) { if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "handle_read error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "handle_read error: %s", + grpc_error_std_string(error).c_str()); return; } state.incoming_data_length += state.temp_incoming_buffer.length; diff --git a/test/core/end2end/dualstack_socket_test.cc b/test/core/end2end/dualstack_socket_test.cc index 2b332dca30c..2307843585c 100644 --- a/test/core/end2end/dualstack_socket_test.cc +++ b/test/core/end2end/dualstack_socket_test.cc @@ -35,11 +35,11 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils_posix.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "test/core/end2end/cq_verifier.h" @@ -60,7 +60,7 @@ static void drain_cq(grpc_completion_queue* cq) { static void log_resolved_addrs(const char* label, const char* hostname) { grpc_resolved_addresses* res = nullptr; - grpc_error* error = grpc_blocking_resolve_address(hostname, "80", &res); + grpc_error_handle error = grpc_blocking_resolve_address(hostname, "80", &res); if (error != GRPC_ERROR_NONE || res == nullptr) { GRPC_LOG_IF_ERROR(hostname, error); return; @@ -277,7 +277,7 @@ void test_connect(const char* server_host, const char* client_host, int port, int external_dns_works(const char* host) { grpc_resolved_addresses* res = nullptr; - grpc_error* error = grpc_blocking_resolve_address(host, "80", &res); + grpc_error_handle error = grpc_blocking_resolve_address(host, "80", &res); GRPC_ERROR_UNREF(error); if (res != nullptr) { grpc_resolved_addresses_destroy(res); diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc index 62ef4bb4938..958b1b73f8f 100644 --- a/test/core/end2end/end2end_nosec_tests.cc +++ b/test/core/end2end/end2end_nosec_tests.cc @@ -125,6 +125,8 @@ extern void resource_quota_server(grpc_end2end_test_config config); extern void resource_quota_server_pre_init(void); extern void retry(grpc_end2end_test_config config); extern void retry_pre_init(void); +extern void retry_cancel_during_delay(grpc_end2end_test_config config); +extern void retry_cancel_during_delay_pre_init(void); extern void retry_cancellation(grpc_end2end_test_config config); extern void retry_cancellation_pre_init(void); extern void retry_disabled(grpc_end2end_test_config config); @@ -133,6 +135,8 @@ extern void retry_exceeds_buffer_size_in_initial_batch(grpc_end2end_test_config extern void retry_exceeds_buffer_size_in_initial_batch_pre_init(void); extern void retry_exceeds_buffer_size_in_subsequent_batch(grpc_end2end_test_config config); extern void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void); +extern void retry_lb_drop(grpc_end2end_test_config config); +extern void retry_lb_drop_pre_init(void); extern void retry_non_retriable_status(grpc_end2end_test_config config); extern void retry_non_retriable_status_pre_init(void); extern void retry_non_retriable_status_before_recv_trailing_metadata_started(grpc_end2end_test_config config); @@ -239,10 +243,12 @@ void grpc_end2end_tests_pre_init(void) { request_with_payload_pre_init(); resource_quota_server_pre_init(); retry_pre_init(); + retry_cancel_during_delay_pre_init(); retry_cancellation_pre_init(); retry_disabled_pre_init(); retry_exceeds_buffer_size_in_initial_batch_pre_init(); retry_exceeds_buffer_size_in_subsequent_batch_pre_init(); + retry_lb_drop_pre_init(); retry_non_retriable_status_pre_init(); retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(); retry_recv_initial_metadata_pre_init(); @@ -327,10 +333,12 @@ void grpc_end2end_tests(int argc, char **argv, request_with_payload(config); resource_quota_server(config); retry(config); + retry_cancel_during_delay(config); retry_cancellation(config); retry_disabled(config); retry_exceeds_buffer_size_in_initial_batch(config); retry_exceeds_buffer_size_in_subsequent_batch(config); + retry_lb_drop(config); retry_non_retriable_status(config); retry_non_retriable_status_before_recv_trailing_metadata_started(config); retry_recv_initial_metadata(config); @@ -554,6 +562,10 @@ void grpc_end2end_tests(int argc, char **argv, retry(config); continue; } + if (0 == strcmp("retry_cancel_during_delay", argv[i])) { + retry_cancel_during_delay(config); + continue; + } if (0 == strcmp("retry_cancellation", argv[i])) { retry_cancellation(config); continue; @@ -570,6 +582,10 @@ void grpc_end2end_tests(int argc, char **argv, retry_exceeds_buffer_size_in_subsequent_batch(config); continue; } + if (0 == strcmp("retry_lb_drop", argv[i])) { + retry_lb_drop(config); + continue; + } if (0 == strcmp("retry_non_retriable_status", argv[i])) { retry_non_retriable_status(config); continue; diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc index 0641fc6926b..d3603b3886f 100644 --- a/test/core/end2end/end2end_tests.cc +++ b/test/core/end2end/end2end_tests.cc @@ -127,6 +127,8 @@ extern void resource_quota_server(grpc_end2end_test_config config); extern void resource_quota_server_pre_init(void); extern void retry(grpc_end2end_test_config config); extern void retry_pre_init(void); +extern void retry_cancel_during_delay(grpc_end2end_test_config config); +extern void retry_cancel_during_delay_pre_init(void); extern void retry_cancellation(grpc_end2end_test_config config); extern void retry_cancellation_pre_init(void); extern void retry_disabled(grpc_end2end_test_config config); @@ -135,6 +137,8 @@ extern void retry_exceeds_buffer_size_in_initial_batch(grpc_end2end_test_config extern void retry_exceeds_buffer_size_in_initial_batch_pre_init(void); extern void retry_exceeds_buffer_size_in_subsequent_batch(grpc_end2end_test_config config); extern void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void); +extern void retry_lb_drop(grpc_end2end_test_config config); +extern void retry_lb_drop_pre_init(void); extern void retry_non_retriable_status(grpc_end2end_test_config config); extern void retry_non_retriable_status_pre_init(void); extern void retry_non_retriable_status_before_recv_trailing_metadata_started(grpc_end2end_test_config config); @@ -242,10 +246,12 @@ void grpc_end2end_tests_pre_init(void) { request_with_payload_pre_init(); resource_quota_server_pre_init(); retry_pre_init(); + retry_cancel_during_delay_pre_init(); retry_cancellation_pre_init(); retry_disabled_pre_init(); retry_exceeds_buffer_size_in_initial_batch_pre_init(); retry_exceeds_buffer_size_in_subsequent_batch_pre_init(); + retry_lb_drop_pre_init(); retry_non_retriable_status_pre_init(); retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(); retry_recv_initial_metadata_pre_init(); @@ -331,10 +337,12 @@ void grpc_end2end_tests(int argc, char **argv, request_with_payload(config); resource_quota_server(config); retry(config); + retry_cancel_during_delay(config); retry_cancellation(config); retry_disabled(config); retry_exceeds_buffer_size_in_initial_batch(config); retry_exceeds_buffer_size_in_subsequent_batch(config); + retry_lb_drop(config); retry_non_retriable_status(config); retry_non_retriable_status_before_recv_trailing_metadata_started(config); retry_recv_initial_metadata(config); @@ -562,6 +570,10 @@ void grpc_end2end_tests(int argc, char **argv, retry(config); continue; } + if (0 == strcmp("retry_cancel_during_delay", argv[i])) { + retry_cancel_during_delay(config); + continue; + } if (0 == strcmp("retry_cancellation", argv[i])) { retry_cancellation(config); continue; @@ -578,6 +590,10 @@ void grpc_end2end_tests(int argc, char **argv, retry_exceeds_buffer_size_in_subsequent_batch(config); continue; } + if (0 == strcmp("retry_lb_drop", argv[i])) { + retry_lb_drop(config); + continue; + } if (0 == strcmp("retry_non_retriable_status", argv[i])) { retry_non_retriable_status(config); continue; diff --git a/test/core/end2end/fixtures/h2_proxy.cc b/test/core/end2end/fixtures/h2_proxy.cc index f0ada89d14d..c6fd2ec79e6 100644 --- a/test/core/end2end/fixtures/h2_proxy.cc +++ b/test/core/end2end/fixtures/h2_proxy.cc @@ -48,12 +48,9 @@ static grpc_server* create_proxy_server(const char* port, static grpc_channel* create_proxy_client(const char* target, grpc_channel_args* client_args) { // Disable retries in proxy client. - grpc_arg arg; - arg.type = GRPC_ARG_INTEGER; - arg.key = const_cast(GRPC_ARG_ENABLE_RETRIES); - arg.value.integer = 0; + const char* args_to_remove = GRPC_ARG_ENABLE_RETRIES; grpc_channel_args* new_args = - grpc_channel_args_copy_and_add(client_args, &arg, 1); + grpc_channel_args_copy_and_remove(client_args, &args_to_remove, 1); grpc_channel* channel = grpc_insecure_channel_create(target, new_args, nullptr); grpc_channel_args_destroy(new_args); diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc index 97fe368348d..67ac6feec93 100644 --- a/test/core/end2end/fixtures/h2_sockpair+trace.cc +++ b/test/core/end2end/fixtures/h2_sockpair+trace.cc @@ -52,10 +52,10 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { grpc_core::ExecCtx exec_ctx; grpc_endpoint_pair* sfd = static_cast(f->fixture_data); grpc_endpoint_add_to_pollset(sfd->server, grpc_cq_pollset(f->cq)); - grpc_error* error = f->server->core_server->SetupTransport( + grpc_error_handle error = f->server->core_server->SetupTransport( transport, nullptr, f->server->core_server->channel_args(), nullptr); if (error == GRPC_ERROR_NONE) { - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } else { GRPC_ERROR_UNREF(error); grpc_transport_destroy(transport); @@ -74,13 +74,13 @@ static void client_setup_transport(void* ts, grpc_transport* transport) { const_cast("test-authority")); grpc_channel_args* args = grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; cs->f->client = grpc_channel_create("socketpair-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport, nullptr, &error); grpc_channel_args_destroy(args); if (cs->f->client != nullptr) { - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } else { intptr_t integer; grpc_status_code status = GRPC_STATUS_INTERNAL; diff --git a/test/core/end2end/fixtures/h2_sockpair.cc b/test/core/end2end/fixtures/h2_sockpair.cc index d92305a2ff6..5d5fb0bd3df 100644 --- a/test/core/end2end/fixtures/h2_sockpair.cc +++ b/test/core/end2end/fixtures/h2_sockpair.cc @@ -46,10 +46,10 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { grpc_core::ExecCtx exec_ctx; grpc_endpoint_pair* sfd = static_cast(f->fixture_data); grpc_endpoint_add_to_pollset(sfd->server, grpc_cq_pollset(f->cq)); - grpc_error* error = f->server->core_server->SetupTransport( + grpc_error_handle error = f->server->core_server->SetupTransport( transport, nullptr, f->server->core_server->channel_args(), nullptr); if (error == GRPC_ERROR_NONE) { - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } else { GRPC_ERROR_UNREF(error); grpc_transport_destroy(transport); @@ -69,13 +69,13 @@ static void client_setup_transport(void* ts, grpc_transport* transport) { const_cast("test-authority")); grpc_channel_args* args = grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; cs->f->client = grpc_channel_create("socketpair-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport, nullptr, &error); grpc_channel_args_destroy(args); if (cs->f->client != nullptr) { - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } else { intptr_t integer; grpc_status_code status = GRPC_STATUS_INTERNAL; diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.cc b/test/core/end2end/fixtures/h2_sockpair_1byte.cc index 6b161dbcc4c..434a614e53b 100644 --- a/test/core/end2end/fixtures/h2_sockpair_1byte.cc +++ b/test/core/end2end/fixtures/h2_sockpair_1byte.cc @@ -46,10 +46,10 @@ static void server_setup_transport(void* ts, grpc_transport* transport) { grpc_core::ExecCtx exec_ctx; grpc_endpoint_pair* sfd = static_cast(f->fixture_data); grpc_endpoint_add_to_pollset(sfd->server, grpc_cq_pollset(f->cq)); - grpc_error* error = f->server->core_server->SetupTransport( + grpc_error_handle error = f->server->core_server->SetupTransport( transport, nullptr, f->server->core_server->channel_args(), nullptr); if (error == GRPC_ERROR_NONE) { - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } else { GRPC_ERROR_UNREF(error); grpc_transport_destroy(transport); @@ -69,13 +69,13 @@ static void client_setup_transport(void* ts, grpc_transport* transport) { const_cast("test-authority")); grpc_channel_args* args = grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; cs->f->client = grpc_channel_create("socketpair-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport, nullptr, &error); grpc_channel_args_destroy(args); if (cs->f->client != nullptr) { - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } else { intptr_t integer; grpc_status_code status = GRPC_STATUS_INTERNAL; diff --git a/test/core/end2end/fixtures/http_proxy_fixture.cc b/test/core/end2end/fixtures/http_proxy_fixture.cc index a5c3353ea2f..83db10b0219 100644 --- a/test/core/end2end/fixtures/http_proxy_fixture.cc +++ b/test/core/end2end/fixtures/http_proxy_fixture.cc @@ -31,6 +31,7 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/host_port.h" @@ -44,7 +45,6 @@ #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/timer.h" @@ -154,25 +154,25 @@ enum failure_type { }; // Forward declarations -static void on_client_write_done(void* arg, grpc_error* error); -static void on_server_write_done(void* arg, grpc_error* error); -static void on_client_read_done(void* arg, grpc_error* error); -static void on_server_read_done(void* arg, grpc_error* error); -static void on_server_connect_done(void* arg, grpc_error* error); -static void on_read_request_done(void* arg, grpc_error* error); - -static void on_client_write_done_locked(void* arg, grpc_error* error); -static void on_server_write_done_locked(void* arg, grpc_error* error); -static void on_client_read_done_locked(void* arg, grpc_error* error); -static void on_server_read_done_locked(void* arg, grpc_error* error); -static void on_server_connect_done_locked(void* arg, grpc_error* error); -static void on_read_request_done_locked(void* arg, grpc_error* error); +static void on_client_write_done(void* arg, grpc_error_handle error); +static void on_server_write_done(void* arg, grpc_error_handle error); +static void on_client_read_done(void* arg, grpc_error_handle error); +static void on_server_read_done(void* arg, grpc_error_handle error); +static void on_server_connect_done(void* arg, grpc_error_handle error); +static void on_read_request_done(void* arg, grpc_error_handle error); + +static void on_client_write_done_locked(void* arg, grpc_error_handle error); +static void on_server_write_done_locked(void* arg, grpc_error_handle error); +static void on_client_read_done_locked(void* arg, grpc_error_handle error); +static void on_server_read_done_locked(void* arg, grpc_error_handle error); +static void on_server_connect_done_locked(void* arg, grpc_error_handle error); +static void on_read_request_done_locked(void* arg, grpc_error_handle error); // Helper function to shut down the proxy connection. static void proxy_connection_failed(proxy_connection* conn, failure_type failure, const char* prefix, - grpc_error* error) { - gpr_log(GPR_INFO, "%s: %s", prefix, grpc_error_string(error)); + grpc_error_handle error) { + gpr_log(GPR_INFO, "%s: %s", prefix, grpc_error_std_string(error).c_str()); // Decide whether we should shut down the client and server. bool shutdown_client = false; bool shutdown_server = false; @@ -207,7 +207,7 @@ static void proxy_connection_failed(proxy_connection* conn, } // Callback for writing proxy data to the client. -static void on_client_write_done_locked(void* arg, grpc_error* error) { +static void on_client_write_done_locked(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); conn->client_is_writing = false; if (error != GRPC_ERROR_NONE) { @@ -233,7 +233,7 @@ static void on_client_write_done_locked(void* arg, grpc_error* error) { } } -static void on_client_write_done(void* arg, grpc_error* error) { +static void on_client_write_done(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); GRPC_CLOSURE_INIT(&conn->on_client_write_done, on_client_write_done_locked, conn, nullptr); @@ -242,7 +242,7 @@ static void on_client_write_done(void* arg, grpc_error* error) { } // Callback for writing proxy data to the backend server. -static void on_server_write_done_locked(void* arg, grpc_error* error) { +static void on_server_write_done_locked(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); conn->server_is_writing = false; if (error != GRPC_ERROR_NONE) { @@ -268,7 +268,7 @@ static void on_server_write_done_locked(void* arg, grpc_error* error) { } } -static void on_server_write_done(void* arg, grpc_error* error) { +static void on_server_write_done(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); GRPC_CLOSURE_INIT(&conn->on_server_write_done, on_server_write_done_locked, conn, nullptr); @@ -278,7 +278,7 @@ static void on_server_write_done(void* arg, grpc_error* error) { // Callback for reading data from the client, which will be proxied to // the backend server. -static void on_client_read_done_locked(void* arg, grpc_error* error) { +static void on_client_read_done_locked(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); if (error != GRPC_ERROR_NONE) { proxy_connection_failed(conn, CLIENT_READ_FAILED, "HTTP proxy client read", @@ -311,7 +311,7 @@ static void on_client_read_done_locked(void* arg, grpc_error* error) { &conn->on_client_read_done, /*urgent=*/false); } -static void on_client_read_done(void* arg, grpc_error* error) { +static void on_client_read_done(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); GRPC_CLOSURE_INIT(&conn->on_client_read_done, on_client_read_done_locked, conn, nullptr); @@ -320,7 +320,7 @@ static void on_client_read_done(void* arg, grpc_error* error) { // Callback for reading data from the backend server, which will be // proxied to the client. -static void on_server_read_done_locked(void* arg, grpc_error* error) { +static void on_server_read_done_locked(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); if (error != GRPC_ERROR_NONE) { proxy_connection_failed(conn, SERVER_READ_FAILED, "HTTP proxy server read", @@ -353,7 +353,7 @@ static void on_server_read_done_locked(void* arg, grpc_error* error) { &conn->on_server_read_done, /*urgent=*/false); } -static void on_server_read_done(void* arg, grpc_error* error) { +static void on_server_read_done(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); GRPC_CLOSURE_INIT(&conn->on_server_read_done, on_server_read_done_locked, conn, nullptr); @@ -361,7 +361,7 @@ static void on_server_read_done(void* arg, grpc_error* error) { } // Callback to write the HTTP response for the CONNECT request. -static void on_write_response_done_locked(void* arg, grpc_error* error) { +static void on_write_response_done_locked(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); conn->client_is_writing = false; if (error != GRPC_ERROR_NONE) { @@ -387,7 +387,7 @@ static void on_write_response_done_locked(void* arg, grpc_error* error) { &conn->on_server_read_done, /*urgent=*/false); } -static void on_write_response_done(void* arg, grpc_error* error) { +static void on_write_response_done(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); GRPC_CLOSURE_INIT(&conn->on_write_response_done, on_write_response_done_locked, conn, nullptr); @@ -397,7 +397,7 @@ static void on_write_response_done(void* arg, grpc_error* error) { // Callback to connect to the backend server specified by the HTTP // CONNECT request. -static void on_server_connect_done_locked(void* arg, grpc_error* error) { +static void on_server_connect_done_locked(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); if (error != GRPC_ERROR_NONE) { // TODO(roth): Technically, in this case, we should handle the error @@ -422,7 +422,7 @@ static void on_server_connect_done_locked(void* arg, grpc_error* error) { &conn->on_write_response_done, nullptr); } -static void on_server_connect_done(void* arg, grpc_error* error) { +static void on_server_connect_done(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); GRPC_CLOSURE_INIT(&conn->on_server_connect_done, on_server_connect_done_locked, conn, nullptr); @@ -456,10 +456,10 @@ static bool proxy_auth_header_matches(char* proxy_auth_header_val, // the client indicating that the request failed. However, for the purposes // of this test code, it's fine to pretend this is a client-side error, // which will cause the client connection to be dropped. -static void on_read_request_done_locked(void* arg, grpc_error* error) { +static void on_read_request_done_locked(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); gpr_log(GPR_DEBUG, "on_read_request_done: %p %s", conn, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); if (error != GRPC_ERROR_NONE) { proxy_connection_failed(conn, SETUP_FAILED, "HTTP proxy read request", GRPC_ERROR_REF(error)); @@ -543,7 +543,7 @@ static void on_read_request_done_locked(void* arg, grpc_error* error) { grpc_resolved_addresses_destroy(resolved_addresses); } -static void on_read_request_done(void* arg, grpc_error* error) { +static void on_read_request_done(void* arg, grpc_error_handle error) { proxy_connection* conn = static_cast(arg); GRPC_CLOSURE_INIT(&conn->on_read_request_done, on_read_request_done_locked, conn, nullptr); @@ -612,7 +612,7 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create( gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name.c_str()); // Create TCP server. proxy->channel_args = grpc_channel_args_copy(args); - grpc_error* error = + grpc_error_handle error = grpc_tcp_server_create(nullptr, proxy->channel_args, &proxy->server); GPR_ASSERT(error == GRPC_ERROR_NONE); // Bind to port. @@ -638,7 +638,7 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create( return proxy; } -static void destroy_pollset(void* arg, grpc_error* /*error*/) { +static void destroy_pollset(void* arg, grpc_error_handle /*error*/) { grpc_pollset* pollset = static_cast(arg); grpc_pollset_destroy(pollset); gpr_free(pollset); diff --git a/test/core/end2end/fuzzers/client_fuzzer.cc b/test/core/end2end/fuzzers/client_fuzzer.cc index 3d55bffd814..31ec46666f6 100644 --- a/test/core/end2end/fuzzers/client_fuzzer.cc +++ b/test/core/end2end/fuzzers/client_fuzzer.cc @@ -54,7 +54,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); grpc_transport* transport = grpc_create_chttp2_transport(nullptr, mock_endpoint, true); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); grpc_arg authority_arg = grpc_channel_arg_string_create( const_cast(GRPC_ARG_DEFAULT_AUTHORITY), diff --git a/test/core/end2end/fuzzers/server_fuzzer.cc b/test/core/end2end/fuzzers/server_fuzzer.cc index 1f1b40ed7d0..8651b2ed3db 100644 --- a/test/core/end2end/fuzzers/server_fuzzer.cc +++ b/test/core/end2end/fuzzers/server_fuzzer.cc @@ -58,7 +58,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { grpc_transport* transport = grpc_create_chttp2_transport(nullptr, mock_endpoint, false); server->core_server->SetupTransport(transport, nullptr, nullptr, nullptr); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); grpc_call* call1 = nullptr; grpc_call_details call_details1; diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index f812e65e22b..58aae8f0020 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -281,6 +281,10 @@ END2END_TESTS = { needs_client_channel = True, proxyable = False, ), + "retry_cancel_during_delay": _test_options( + needs_client_channel = True, + proxyable = False, + ), "retry_disabled": _test_options(needs_client_channel = True, proxyable = False), "retry_exceeds_buffer_size_in_initial_batch": _test_options( needs_client_channel = True, @@ -296,6 +300,10 @@ END2END_TESTS = { # See b/151617965 short_name = "retry_exceeds_buffer_size_in_subseq", ), + "retry_lb_drop": _test_options( + needs_client_channel = True, + proxyable = False, + ), "retry_non_retriable_status": _test_options( needs_client_channel = True, proxyable = False, @@ -422,12 +430,14 @@ def grpc_end2end_tests(): "end2end_tests.h", ], language = "C++", + testonly = 1, deps = [ ":cq_verifier", ":ssl_test_data", ":http_proxy", ":proxy", ":local_util", + "//test/core/util:test_lb_policies", ], ) @@ -436,6 +446,7 @@ def grpc_end2end_tests(): name = "%s_test" % f, srcs = ["fixtures/%s.cc" % f], language = "C++", + testonly = 1, data = [ "//src/core/tsi/test_creds:ca.pem", "//src/core/tsi/test_creds:server1.key", @@ -497,12 +508,14 @@ def grpc_end2end_nosec_tests(): "end2end_tests.h", ], language = "C++", + testonly = 1, deps = [ ":cq_verifier", ":ssl_test_data", ":http_proxy", ":proxy", ":local_util", + "//test/core/util:test_lb_policies", ], ) @@ -513,6 +526,7 @@ def grpc_end2end_nosec_tests(): name = "%s_nosec_test" % f, srcs = ["fixtures/%s.cc" % f], language = "C++", + testonly = 1, data = [ "//src/core/tsi/test_creds:ca.pem", "//src/core/tsi/test_creds:server1.key", diff --git a/test/core/end2end/goaway_server_test.cc b/test/core/end2end/goaway_server_test.cc index d0ca2196e05..679000d7059 100644 --- a/test/core/end2end/goaway_server_test.cc +++ b/test/core/end2end/goaway_server_test.cc @@ -75,7 +75,7 @@ static void my_resolve_address(const char* addr, const char* default_port, return; } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; gpr_mu_lock(&g_mu); if (g_resolve_port < 0) { gpr_mu_unlock(&g_mu); @@ -97,7 +97,7 @@ static void my_resolve_address(const char* addr, const char* default_port, grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_done, error); } -static grpc_error* my_blocking_resolve_address( +static grpc_error_handle my_blocking_resolve_address( const char* name, const char* default_port, grpc_resolved_addresses** addresses) { return default_resolver->blocking_resolve_address(name, default_port, @@ -121,7 +121,7 @@ static grpc_ares_request* my_dns_lookup_ares_locked( std::move(work_serializer)); } - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; gpr_mu_lock(&g_mu); if (g_resolve_port < 0) { gpr_mu_unlock(&g_mu); diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc index fb1af999699..f7471c1038e 100644 --- a/test/core/end2end/tests/filter_causes_close.cc +++ b/test/core/end2end/tests/filter_causes_close.cc @@ -195,7 +195,7 @@ typedef struct { uint8_t unused; } channel_data; -static void recv_im_ready(void* arg, grpc_error* error) { +static void recv_im_ready(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast(arg); call_data* calld = static_cast(elem->call_data); grpc_core::Closure::Run( @@ -218,8 +218,8 @@ static void start_transport_stream_op_batch( grpc_call_next_op(elem, op); } -static grpc_error* init_call_elem(grpc_call_element* /*elem*/, - const grpc_call_element_args* /*args*/) { +static grpc_error_handle init_call_elem( + grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -227,8 +227,8 @@ static void destroy_call_elem(grpc_call_element* /*elem*/, const grpc_call_final_info* /*final_info*/, grpc_closure* /*ignored*/) {} -static grpc_error* init_channel_elem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +static grpc_error_handle init_channel_elem( + grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } diff --git a/test/core/end2end/tests/filter_context.cc b/test/core/end2end/tests/filter_context.cc index 5b02e067d08..0b97dc47d0a 100644 --- a/test/core/end2end/tests/filter_context.cc +++ b/test/core/end2end/tests/filter_context.cc @@ -225,8 +225,8 @@ struct call_data { grpc_call_context_element* context; }; -static grpc_error* init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { +static grpc_error_handle init_call_elem(grpc_call_element* elem, + const grpc_call_element_args* args) { call_data* calld = static_cast(elem->call_data); calld->context = args->context; gpr_log(GPR_INFO, "init_call_elem(): context=%p", args->context); @@ -251,8 +251,8 @@ static void destroy_call_elem(grpc_call_element* /*elem*/, const grpc_call_final_info* /*final_info*/, grpc_closure* /*ignored*/) {} -static grpc_error* init_channel_elem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +static grpc_error_handle init_channel_elem( + grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } diff --git a/test/core/end2end/tests/filter_init_fails.cc b/test/core/end2end/tests/filter_init_fails.cc index 1ab361acd5e..43da6900e8c 100644 --- a/test/core/end2end/tests/filter_init_fails.cc +++ b/test/core/end2end/tests/filter_init_fails.cc @@ -169,7 +169,7 @@ static void test_server_channel_filter(grpc_end2end_test_config config) { CQ_EXPECT_COMPLETION(cqv, tag(1), 1); cq_verify(cqv); - if (g_channel_filter_init_failure == true) { + if (g_channel_filter_init_failure) { // Inproc channel returns invalid_argument and other clients return // unavailable. // Windows with sockpair returns unknown. @@ -416,8 +416,8 @@ static void test_client_subchannel_filter(grpc_end2end_test_config config) { * Test filter - always fails to initialize a call */ -static grpc_error* init_call_elem(grpc_call_element* /*elem*/, - const grpc_call_element_args* /*args*/) { +static grpc_error_handle init_call_elem( + grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { return grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("access denied"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_PERMISSION_DENIED); @@ -427,8 +427,8 @@ static void destroy_call_elem(grpc_call_element* /*elem*/, const grpc_call_final_info* /*final_info*/, grpc_closure* /*ignored*/) {} -static grpc_error* init_channel_elem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +static grpc_error_handle init_channel_elem( + grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { if (g_channel_filter_init_failure) { return grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test channel filter init error"), diff --git a/test/core/end2end/tests/filter_latency.cc b/test/core/end2end/tests/filter_latency.cc index 1a8091e86ed..6b94d941ff0 100644 --- a/test/core/end2end/tests/filter_latency.cc +++ b/test/core/end2end/tests/filter_latency.cc @@ -247,8 +247,8 @@ static void test_request(grpc_end2end_test_config config) { * Test latency filter */ -static grpc_error* init_call_elem(grpc_call_element* /*elem*/, - const grpc_call_element_args* /*args*/) { +static grpc_error_handle init_call_elem( + grpc_call_element* /*elem*/, const grpc_call_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -268,8 +268,8 @@ static void server_destroy_call_elem(grpc_call_element* /*elem*/, gpr_mu_unlock(&g_mu); } -static grpc_error* init_channel_elem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +static grpc_error_handle init_channel_elem( + grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc index 061166fa111..6359980b5ce 100644 --- a/test/core/end2end/tests/filter_status_code.cc +++ b/test/core/end2end/tests/filter_status_code.cc @@ -275,8 +275,8 @@ static void server_start_transport_stream_op_batch( grpc_call_next_op(elem, op); } -static grpc_error* init_call_elem(grpc_call_element* elem, - const grpc_call_element_args* args) { +static grpc_error_handle init_call_elem(grpc_call_element* elem, + const grpc_call_element_args* args) { final_status_data* data = static_cast(elem->call_data); data->call = args->call_stack; return GRPC_ERROR_NONE; @@ -312,8 +312,8 @@ static void server_destroy_call_elem(grpc_call_element* elem, gpr_mu_unlock(&g_mu); } -static grpc_error* init_channel_elem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +static grpc_error_handle init_channel_elem( + grpc_channel_element* /*elem*/, grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } diff --git a/test/core/end2end/tests/retry.cc b/test/core/end2end/tests/retry.cc index 5e9f8aa52da..1c82b51b627 100644 --- a/test/core/end2end/tests/retry.cc +++ b/test/core/end2end/tests/retry.cc @@ -120,25 +120,28 @@ static void test_retry(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_cancel_during_delay.cc b/test/core/end2end/tests/retry_cancel_during_delay.cc new file mode 100644 index 00000000000..161b7aa16d9 --- /dev/null +++ b/test/core/end2end/tests/retry_cancel_during_delay.cc @@ -0,0 +1,288 @@ +// +// Copyright 2017 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include + +#include "absl/strings/str_cat.h" + +#include +#include +#include +#include +#include + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/transport/static_metadata.h" + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/tests/cancel_test_helpers.h" + +static void* tag(intptr_t t) { return reinterpret_cast(t); } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char* test_name, + grpc_channel_args* client_args, + grpc_channel_args* server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue* cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture* f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + nullptr) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = nullptr; +} + +static void shutdown_client(grpc_end2end_test_fixture* f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = nullptr; +} + +static void end_test(grpc_end2end_test_fixture* f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +// Tests retry cancellation during backoff. +static void test_retry_cancel_during_delay(grpc_end2end_test_config config, + cancellation_mode mode) { + grpc_call* c; + grpc_call* s; + grpc_op ops[6]; + grpc_op* op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); + grpc_slice response_payload_slice = grpc_slice_from_static_string("bar"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload = + grpc_raw_byte_buffer_create(&response_payload_slice, 1); + grpc_byte_buffer* request_payload_recv = nullptr; + grpc_byte_buffer* response_payload_recv = nullptr; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + char* peer; + + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"10s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " },\n" + " \"timeout\": \"5s\"\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; + std::string name = absl::StrCat("retry_cancel_during_delay/", mode.name); + grpc_end2end_test_fixture f = + begin_test(config, name.c_str(), &client_args, nullptr); + + cq_verifier* cqv = cq_verifier_create(f.cq); + + gpr_timespec expect_finish_before = n_seconds_from_now(10); + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/service/method"), + nullptr, deadline, nullptr); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != nullptr); + gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); + gpr_free(peer); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + + // Client starts a batch with all 6 ops. + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op++; + error = grpc_call_start_batch(c, ops, static_cast(op - ops), tag(1), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + // Server gets a call and fails with retryable status. + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), true); + cq_verify(cqv); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != nullptr); + gpr_log(GPR_DEBUG, "server_peer=%s", peer); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != nullptr); + gpr_log(GPR_DEBUG, "client_peer=%s", peer); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_ABORTED; + op->data.send_status_from_server.status_details = &status_details; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op++; + error = grpc_call_start_batch(s, ops, static_cast(op - ops), tag(102), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), true); + cq_verify(cqv); + + grpc_call_unref(s); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_call_details_init(&call_details); + + // Server should never get a second call, because the initial retry + // delay is longer than the call's deadline. + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(201)); + GPR_ASSERT(GRPC_CALL_OK == error); + cq_verify_empty(cqv); + + // Initiate cancellation. + GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr)); + + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + cq_verify(cqv); + + // Make sure we didn't wait the full deadline before failing. + gpr_log( + GPR_INFO, "Expect completion before: %s", + absl::FormatTime(grpc_core::ToAbslTime(expect_finish_before)).c_str()); + GPR_ASSERT(gpr_time_cmp(gpr_now(GPR_CLOCK_MONOTONIC), expect_finish_before) < + 0); + + gpr_log(GPR_INFO, "status=%d expected=%d", status, mode.expect_status); + GPR_ASSERT(status == mode.expect_status); + GPR_ASSERT(was_cancelled == 0); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload); + grpc_byte_buffer_destroy(request_payload_recv); + grpc_byte_buffer_destroy(response_payload_recv); + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + + end_test(&f); + config.tear_down_data(&f); +} + +void retry_cancel_during_delay(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); + for (size_t i = 0; i < GPR_ARRAY_SIZE(cancellation_modes); ++i) { + test_retry_cancel_during_delay(config, cancellation_modes[i]); + } +} + +void retry_cancel_during_delay_pre_init(void) {} diff --git a/test/core/end2end/tests/retry_cancellation.cc b/test/core/end2end/tests/retry_cancellation.cc index 261e962c369..c4f1b943ea5 100644 --- a/test/core/end2end/tests/retry_cancellation.cc +++ b/test/core/end2end/tests/retry_cancellation.cc @@ -121,27 +121,30 @@ static void test_retry_cancellation(grpc_end2end_test_config config, int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " },\n" - " \"timeout\": \"5s\"\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; - std::string name = absl::StrCat("retry_cancellation/%s", mode.name); + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " },\n" + " \"timeout\": \"5s\"\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; + std::string name = absl::StrCat("retry_cancellation/", mode.name); grpc_end2end_test_fixture f = begin_test(config, name.c_str(), &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_disabled.cc b/test/core/end2end/tests/retry_disabled.cc index 3cdc0452c70..dc953db7efe 100644 --- a/test/core/end2end/tests/retry_disabled.cc +++ b/test/core/end2end/tests/retry_disabled.cc @@ -93,11 +93,13 @@ static void end_test(grpc_end2end_test_fixture* f) { grpc_completion_queue_destroy(f->shutdown_cq); } -// Tests that we don't retry when retries are disabled via the +// Tests that we don't retry when retries are not enabled via the // GRPC_ARG_ENABLE_RETRIES channel arg, even when there is retry // configuration in the service config. // - 1 retry allowed for ABORTED status // - first attempt returns ABORTED but does not retry +// TODO(roth): Update this when we change the default of +// GRPC_ARG_ENABLE_RETRIES to true. static void test_retry_disabled(grpc_end2end_test_config config) { grpc_call* c; grpc_call* s; @@ -121,28 +123,24 @@ static void test_retry_disabled(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg args[2]; - args[0].type = GRPC_ARG_STRING; - args[0].key = const_cast(GRPC_ARG_SERVICE_CONFIG); - args[0].value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - args[1].type = GRPC_ARG_INTEGER; - args[1].key = const_cast(GRPC_ARG_ENABLE_RETRIES); - args[1].value.integer = 0; - grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; + grpc_arg arg = grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")); + grpc_channel_args client_args = {1, &arg}; grpc_end2end_test_fixture f = begin_test(config, "retry_disabled", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc index 4d5f6914c82..3a7f42b05af 100644 --- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc +++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc @@ -123,27 +123,29 @@ static void test_retry_exceeds_buffer_size_in_initial_batch( int was_cancelled = 2; char* peer; - grpc_arg args[2]; - args[0].type = GRPC_ARG_STRING; - args[0].key = const_cast(GRPC_ARG_SERVICE_CONFIG); - args[0].value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - args[1].type = GRPC_ARG_INTEGER; - args[1].key = const_cast(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE); - args[1].value.integer = 2; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE), 2), + }; grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_exceeds_buffer_size_in_initial_batch", diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc index 1c99f4c31ba..7c84297d3d8 100644 --- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc +++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc @@ -128,27 +128,29 @@ static void test_retry_exceeds_buffer_size_in_subsequent_batch( int was_cancelled = 2; char* peer; - grpc_arg args[2]; - args[0].type = GRPC_ARG_STRING; - args[0].key = const_cast(GRPC_ARG_SERVICE_CONFIG); - args[0].value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - args[1].type = GRPC_ARG_INTEGER; - args[1].key = const_cast(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE); - args[1].value.integer = 102400; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_PER_RPC_RETRY_BUFFER_SIZE), 102400), + }; grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_exceeds_buffer_size_in_subsequent_batch", diff --git a/test/core/end2end/tests/retry_lb_drop.cc b/test/core/end2end/tests/retry_lb_drop.cc new file mode 100644 index 00000000000..d81b04aaf24 --- /dev/null +++ b/test/core/end2end/tests/retry_lb_drop.cc @@ -0,0 +1,279 @@ +// +// Copyright 2017 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "test/core/end2end/end2end_tests.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "src/core/ext/filters/client_channel/lb_policy_registry.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gpr/useful.h" +#include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/transport/static_metadata.h" + +#include "test/core/end2end/cq_verifier.h" +#include "test/core/end2end/tests/cancel_test_helpers.h" +#include "test/core/util/test_lb_policies.h" + +namespace grpc_core { +namespace { + +const char* kDropPolicyName = "drop_lb"; + +class DropPolicy : public LoadBalancingPolicy { + public: + explicit DropPolicy(Args args) : LoadBalancingPolicy(std::move(args)) {} + + const char* name() const override { return kDropPolicyName; } + + void UpdateLocked(UpdateArgs) override { + channel_control_helper()->UpdateState(GRPC_CHANNEL_READY, absl::Status(), + absl::make_unique()); + } + + void ResetBackoffLocked() override {} + void ShutdownLocked() override {} + + private: + class DropPicker : public SubchannelPicker { + public: + PickResult Pick(PickArgs /*args*/) override { + PickResult result; + result.type = PickResult::PICK_COMPLETE; + return result; + } + }; +}; + +class DropLbConfig : public LoadBalancingPolicy::Config { + public: + const char* name() const override { return kDropPolicyName; } +}; + +class DropPolicyFactory : public LoadBalancingPolicyFactory { + public: + OrphanablePtr CreateLoadBalancingPolicy( + LoadBalancingPolicy::Args args) const override { + return MakeOrphanable(std::move(args)); + } + + const char* name() const override { return kDropPolicyName; } + + RefCountedPtr ParseLoadBalancingConfig( + const Json& /*json*/, grpc_error_handle* /*error*/) const override { + return MakeRefCounted(); + } +}; + +std::vector* g_pick_args_vector = nullptr; + +void RegisterDropPolicy() { + LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory( + absl::make_unique()); + RegisterTestPickArgsLoadBalancingPolicy( + [](const PickArgsSeen& pick_args) { + GPR_ASSERT(g_pick_args_vector != nullptr); + g_pick_args_vector->push_back(pick_args); + }, + kDropPolicyName); +} + +} // namespace +} // namespace grpc_core + +static void* tag(intptr_t t) { return reinterpret_cast(t); } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char* test_name, + grpc_channel_args* client_args, + grpc_channel_args* server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue* cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture* f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + nullptr) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = nullptr; +} + +static void shutdown_client(grpc_end2end_test_fixture* f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = nullptr; +} + +static void end_test(grpc_end2end_test_fixture* f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +// Tests that we don't retry when retries are disabled via the +// GRPC_ARG_ENABLE_RETRIES channel arg, even when there is retry +// configuration in the service config. +// - 1 retry allowed for ABORTED status +// - first attempt returns ABORTED but does not retry +static void test_retry_lb_drop(grpc_end2end_test_config config) { + grpc_call* c; + grpc_op ops[6]; + grpc_op* op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_slice request_payload_slice = grpc_slice_from_static_string("foo"); + grpc_byte_buffer* request_payload = + grpc_raw_byte_buffer_create(&request_payload_slice, 1); + grpc_byte_buffer* response_payload_recv = nullptr; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + + std::vector pick_args_seen; + grpc_core::g_pick_args_vector = &pick_args_seen; + + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"loadBalancingConfig\": [ {\n" + " \"test_pick_args_lb\": {}\n" + " } ],\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"UNAVAILABLE\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; + grpc_end2end_test_fixture f = + begin_test(config, "retry_lb_drop", &client_args, nullptr); + + cq_verifier* cqv = cq_verifier_create(f.cq); + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/service/method"), + nullptr, deadline, nullptr); + GPR_ASSERT(c); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op++; + op->op = GRPC_OP_SEND_MESSAGE; + op->data.send_message.send_message = request_payload; + op++; + op->op = GRPC_OP_RECV_MESSAGE; + op->data.recv_message.recv_message = &response_payload_recv; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op++; + error = grpc_call_start_batch(c, ops, static_cast(op - ops), tag(1), + nullptr); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(1), true); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, + "Call dropped by load balancing policy")); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_byte_buffer_destroy(request_payload); + grpc_byte_buffer_destroy(response_payload_recv); + + grpc_call_unref(c); + + cq_verifier_destroy(cqv); + + gpr_log(GPR_INFO, "NUMBER OF LB PICKS: %" PRIuPTR, pick_args_seen.size()); + GPR_ASSERT(pick_args_seen.size() == 1); + + grpc_core::g_pick_args_vector = nullptr; + + end_test(&f); + config.tear_down_data(&f); +} + +void retry_lb_drop(grpc_end2end_test_config config) { + GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL); + test_retry_lb_drop(config); +} + +void retry_lb_drop_pre_init(void) { grpc_core::RegisterDropPolicy(); } diff --git a/test/core/end2end/tests/retry_non_retriable_status.cc b/test/core/end2end/tests/retry_non_retriable_status.cc index 51247138bef..3ad91ea59e2 100644 --- a/test/core/end2end/tests/retry_non_retriable_status.cc +++ b/test/core/end2end/tests/retry_non_retriable_status.cc @@ -119,25 +119,28 @@ static void test_retry_non_retriable_status(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_non_retriable_status", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc index 5bdada8a1f6..cc854b8ae4e 100644 --- a/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc +++ b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc @@ -122,27 +122,32 @@ test_retry_non_retriable_status_before_recv_trailing_metadata_started( int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; - grpc_end2end_test_fixture f = - begin_test(config, "retry_non_retriable_status", &client_args, nullptr); + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; + grpc_end2end_test_fixture f = begin_test( + config, + "retry_non_retriable_status_before_recv_trailing_metadata_started", + &client_args, nullptr); cq_verifier* cqv = cq_verifier_create(f.cq); diff --git a/test/core/end2end/tests/retry_recv_initial_metadata.cc b/test/core/end2end/tests/retry_recv_initial_metadata.cc index eae84eee257..ac131107091 100644 --- a/test/core/end2end/tests/retry_recv_initial_metadata.cc +++ b/test/core/end2end/tests/retry_recv_initial_metadata.cc @@ -120,25 +120,28 @@ static void test_retry_recv_initial_metadata(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_recv_initial_metadata", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_recv_message.cc b/test/core/end2end/tests/retry_recv_message.cc index f720591f926..24a33e231fe 100644 --- a/test/core/end2end/tests/retry_recv_message.cc +++ b/test/core/end2end/tests/retry_recv_message.cc @@ -120,25 +120,28 @@ static void test_retry_recv_message(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_recv_message", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_server_pushback_delay.cc b/test/core/end2end/tests/retry_server_pushback_delay.cc index 122eb494dc8..4990c6fe1f8 100644 --- a/test/core/end2end/tests/retry_server_pushback_delay.cc +++ b/test/core/end2end/tests/retry_server_pushback_delay.cc @@ -125,25 +125,28 @@ static void test_retry_server_pushback_delay(grpc_end2end_test_config config) { pushback_md.key = GRPC_MDSTR_GRPC_RETRY_PUSHBACK_MS; pushback_md.value = grpc_slice_from_static_string("2000"); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_server_pushback_delay", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_server_pushback_disabled.cc b/test/core/end2end/tests/retry_server_pushback_disabled.cc index 44a37a42195..75744d33cde 100644 --- a/test/core/end2end/tests/retry_server_pushback_disabled.cc +++ b/test/core/end2end/tests/retry_server_pushback_disabled.cc @@ -126,25 +126,28 @@ static void test_retry_server_pushback_disabled( pushback_md.key = GRPC_MDSTR_GRPC_RETRY_PUSHBACK_MS; pushback_md.value = grpc_slice_from_static_string("-1"); - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test( config, "retry_server_pushback_disabled", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_streaming.cc b/test/core/end2end/tests/retry_streaming.cc index 25219102b80..3d2e9dc6545 100644 --- a/test/core/end2end/tests/retry_streaming.cc +++ b/test/core/end2end/tests/retry_streaming.cc @@ -137,6 +137,8 @@ static void test_retry_streaming(grpc_end2end_test_config config) { char* peer; grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), grpc_channel_arg_integer_create( const_cast(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE), 1024 * 8), diff --git a/test/core/end2end/tests/retry_streaming_after_commit.cc b/test/core/end2end/tests/retry_streaming_after_commit.cc index de7d7c3d372..a3ea534ea3f 100644 --- a/test/core/end2end/tests/retry_streaming_after_commit.cc +++ b/test/core/end2end/tests/retry_streaming_after_commit.cc @@ -126,25 +126,28 @@ static void test_retry_streaming_after_commit(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_streaming_after_commit", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc index 866c948161d..aee927c43ef 100644 --- a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc +++ b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc @@ -127,25 +127,28 @@ static void test_retry_streaming_succeeds_before_replay_finished( int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 3,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 3,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_streaming", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_throttled.cc b/test/core/end2end/tests/retry_throttled.cc index 9fdca88ec2f..91c60fa6a49 100644 --- a/test/core/end2end/tests/retry_throttled.cc +++ b/test/core/end2end/tests/retry_throttled.cc @@ -119,32 +119,35 @@ static void test_retry_throttled(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ],\n" - // A single failure will cause us to be throttled. - // (This is not a very realistic config, but it works for the - // purposes of this test.) - " \"retryThrottling\": {\n" - " \"maxTokens\": 2,\n" - " \"tokenRatio\": 1.0\n" - " }\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ],\n" + // A single failure will cause us to be throttled. + // (This is not a very realistic config, but it works for the + // purposes of this test.) + " \"retryThrottling\": {\n" + " \"maxTokens\": 2,\n" + " \"tokenRatio\": 1.0\n" + " }\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_throttled", &client_args, nullptr); diff --git a/test/core/end2end/tests/retry_too_many_attempts.cc b/test/core/end2end/tests/retry_too_many_attempts.cc index 2a8301fd2ee..bdb1a67a8e4 100644 --- a/test/core/end2end/tests/retry_too_many_attempts.cc +++ b/test/core/end2end/tests/retry_too_many_attempts.cc @@ -120,25 +120,28 @@ static void test_retry_too_many_attempts(grpc_end2end_test_config config) { int was_cancelled = 2; char* peer; - grpc_arg arg; - arg.type = GRPC_ARG_STRING; - arg.key = const_cast(GRPC_ARG_SERVICE_CONFIG); - arg.value.string = const_cast( - "{\n" - " \"methodConfig\": [ {\n" - " \"name\": [\n" - " { \"service\": \"service\", \"method\": \"method\" }\n" - " ],\n" - " \"retryPolicy\": {\n" - " \"maxAttempts\": 2,\n" - " \"initialBackoff\": \"1s\",\n" - " \"maxBackoff\": \"120s\",\n" - " \"backoffMultiplier\": 1.6,\n" - " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" - " }\n" - " } ]\n" - "}"); - grpc_channel_args client_args = {1, &arg}; + grpc_arg args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_ENABLE_RETRIES), 1), + grpc_channel_arg_string_create( + const_cast(GRPC_ARG_SERVICE_CONFIG), + const_cast( + "{\n" + " \"methodConfig\": [ {\n" + " \"name\": [\n" + " { \"service\": \"service\", \"method\": \"method\" }\n" + " ],\n" + " \"retryPolicy\": {\n" + " \"maxAttempts\": 2,\n" + " \"initialBackoff\": \"1s\",\n" + " \"maxBackoff\": \"120s\",\n" + " \"backoffMultiplier\": 1.6,\n" + " \"retryableStatusCodes\": [ \"ABORTED\" ]\n" + " }\n" + " } ]\n" + "}")), + }; + grpc_channel_args client_args = {GPR_ARRAY_SIZE(args), args}; grpc_end2end_test_fixture f = begin_test(config, "retry_too_many_attempts", &client_args, nullptr); diff --git a/test/core/gprpp/BUILD b/test/core/gprpp/BUILD index c0c3b5302eb..caa6f5da247 100644 --- a/test/core/gprpp/BUILD +++ b/test/core/gprpp/BUILD @@ -193,6 +193,20 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "status_helper_test", + srcs = ["status_helper_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + uses_polling = False, + deps = [ + "//:gpr", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "time_util_test", srcs = ["time_util_test.cc"], diff --git a/test/core/gprpp/ref_counted_test.cc b/test/core/gprpp/ref_counted_test.cc index fefe90b0caa..6e95aa2823c 100644 --- a/test/core/gprpp/ref_counted_test.cc +++ b/test/core/gprpp/ref_counted_test.cc @@ -51,7 +51,7 @@ TEST(RefCounted, ExtraRef) { foo->Unref(); } -class Value : public RefCounted { +class Value : public RefCounted { public: Value(int value, std::set>* registry) : value_(value) { registry->emplace(this); @@ -104,6 +104,26 @@ TEST(RefCounted, NoDeleteUponUnref) { EXPECT_THAT(registry, ::testing::UnorderedElementsAre()); } +class ValueInExternalAllocation + : public RefCounted { + public: + explicit ValueInExternalAllocation(int value) : value_(value) {} + + int value() const { return value_; } + + private: + int value_; +}; + +TEST(RefCounted, CallDtorUponUnref) { + std::aligned_storage::type storage; + RefCountedPtr value( + new (&storage) ValueInExternalAllocation(5)); + EXPECT_EQ(value->value(), 5); +} + class FooNonPolymorphic : public RefCounted { public: diff --git a/test/core/gprpp/status_helper_test.cc b/test/core/gprpp/status_helper_test.cc new file mode 100644 index 00000000000..0f59b2ac1c9 --- /dev/null +++ b/test/core/gprpp/status_helper_test.cc @@ -0,0 +1,170 @@ +// +// Copyright 2021 the gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "src/core/lib/gprpp/status_helper.h" + +#include +#include + +#include "absl/status/status.h" +#include "absl/strings/str_cat.h" +#include "absl/time/clock.h" +#include "google/rpc/status.upb.h" +#include "upb/upb.hpp" + +namespace grpc_core { +namespace { + +TEST(StatusUtilTest, CreateStatus) { + absl::Status s = + StatusCreate(absl::StatusCode::kUnknown, "Test", DEBUG_LOCATION, + {absl::OkStatus(), absl::CancelledError()}); + EXPECT_EQ(absl::StatusCode::kUnknown, s.code()); + EXPECT_EQ("Test", s.message()); +#ifndef NDEBUG + EXPECT_EQ(true, StatusGetStr(s, StatusStrProperty::kFile).has_value()); + EXPECT_EQ(true, StatusGetInt(s, StatusIntProperty::kFileLine).has_value()); +#endif + EXPECT_EQ(true, StatusGetTime(s, StatusTimeProperty::kCreated).has_value()); + EXPECT_THAT(StatusGetChildren(s), + ::testing::ElementsAre(absl::CancelledError())); +} + +TEST(StatusUtilTest, SetAndGetInt) { + absl::Status s = absl::CancelledError(); + StatusSetInt(&s, StatusIntProperty::kErrorNo, 2021); + EXPECT_EQ(2021, StatusGetInt(s, StatusIntProperty::kErrorNo)); +} + +TEST(StatusUtilTest, GetIntNotExistent) { + absl::Status s = absl::CancelledError(); + EXPECT_EQ(absl::optional(), + StatusGetInt(s, StatusIntProperty::kErrorNo)); +} + +TEST(StatusUtilTest, SetAndGetStr) { + absl::Status s = absl::CancelledError(); + StatusSetStr(&s, StatusStrProperty::kOsError, "value"); + EXPECT_EQ("value", StatusGetStr(s, StatusStrProperty::kOsError)); +} + +TEST(StatusUtilTest, GetStrNotExistent) { + absl::Status s = absl::CancelledError(); + EXPECT_EQ(absl::optional(), + StatusGetStr(s, StatusStrProperty::kOsError)); +} + +TEST(StatusUtilTest, SetAndGetTime) { + absl::Status s = absl::CancelledError(); + absl::Time t = absl::Now(); + StatusSetTime(&s, StatusTimeProperty::kCreated, t); + EXPECT_EQ(t, StatusGetTime(s, StatusTimeProperty::kCreated)); +} + +TEST(StatusUtilTest, GetTimeNotExistent) { + absl::Status s = absl::CancelledError(); + EXPECT_EQ(absl::optional(), + StatusGetTime(s, StatusTimeProperty::kCreated)); +} + +TEST(StatusUtilTest, AddAndGetChildren) { + absl::Status s = absl::CancelledError(); + absl::Status child1 = absl::AbortedError("Message1"); + absl::Status child2 = absl::DeadlineExceededError("Message2"); + StatusAddChild(&s, child1); + StatusAddChild(&s, child2); + EXPECT_THAT(StatusGetChildren(s), ::testing::ElementsAre(child1, child2)); +} + +TEST(StatusUtilTest, ToAndFromProto) { + absl::Status s = absl::CancelledError("Message"); + StatusSetInt(&s, StatusIntProperty::kErrorNo, 2021); + StatusSetStr(&s, StatusStrProperty::kOsError, "value"); + upb::Arena arena; + google_rpc_Status* msg = internal::StatusToProto(s, arena.ptr()); + absl::Status s2 = internal::StatusFromProto(msg); + EXPECT_EQ(s, s2); +} + +TEST(StatusUtilTest, OkToString) { + absl::Status s = absl::OkStatus(); + std::string t = StatusToString(s); + EXPECT_EQ("OK", t); +} + +TEST(StatusUtilTest, CancelledErrorToString) { + absl::Status s = absl::CancelledError(); + std::string t = StatusToString(s); + EXPECT_EQ("CANCELLED", t); +} + +TEST(StatusUtilTest, ErrorWithIntPropertyToString) { + absl::Status s = absl::CancelledError("Message"); + StatusSetInt(&s, StatusIntProperty::kErrorNo, 2021); + std::string t = StatusToString(s); + EXPECT_EQ("CANCELLED:Message {errno:2021}", t); +} + +TEST(StatusUtilTest, ErrorWithStrPropertyToString) { + absl::Status s = absl::CancelledError("Message"); + StatusSetStr(&s, StatusStrProperty::kDescription, "Hey"); + std::string t = StatusToString(s); + EXPECT_EQ("CANCELLED:Message {description:\"Hey\"}", t); +} + +TEST(StatusUtilTest, ErrorWithTimePropertyToString) { + absl::Status s = absl::CancelledError("Message"); + absl::Time t = absl::FromCivil(absl::CivilSecond(2021, 4, 29, 8, 56, 30), + absl::LocalTimeZone()); + StatusSetTime(&s, StatusTimeProperty::kCreated, t); + EXPECT_EQ(StatusToString(s), + absl::StrCat("CANCELLED:Message {created_time:\"", + absl::FormatTime(t), "\"}")); +} + +TEST(StatusUtilTest, ComplexErrorWithChildrenToString) { + absl::Status s = absl::CancelledError("Message"); + StatusSetInt(&s, StatusIntProperty::kErrorNo, 2021); + absl::Status s1 = absl::AbortedError("Message1"); + StatusAddChild(&s, s1); + absl::Status s2 = absl::AlreadyExistsError("Message2"); + StatusSetStr(&s2, StatusStrProperty::kOsError, "value"); + StatusAddChild(&s, s2); + std::string t = StatusToString(s); + EXPECT_EQ( + "CANCELLED:Message {errno:2021, children:[" + "ABORTED:Message1, ALREADY_EXISTS:Message2 {os_error:\"value\"}]}", + t); +} + +TEST(StatusUtilTest, AllocPtr) { + absl::Status statuses[] = {absl::OkStatus(), absl::CancelledError(), + absl::AbortedError("Message")}; + for (const auto& s : statuses) { + uintptr_t p = internal::StatusAllocPtr(s); + EXPECT_EQ(s, internal::StatusGetFromPtr(p)); + internal::StatusFreePtr(p); + } +} + +} // namespace +} // namespace grpc_core + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/test/core/handshake/readahead_handshaker_server_ssl.cc b/test/core/handshake/readahead_handshaker_server_ssl.cc index 708b316e793..ec1cdc46d65 100644 --- a/test/core/handshake/readahead_handshaker_server_ssl.cc +++ b/test/core/handshake/readahead_handshaker_server_ssl.cc @@ -55,7 +55,7 @@ class ReadAheadHandshaker : public Handshaker { public: ~ReadAheadHandshaker() override {} const char* name() const override { return "read_ahead"; } - void Shutdown(grpc_error* /*why*/) override {} + void Shutdown(grpc_error_handle /*why*/) override {} void DoHandshake(grpc_tcp_server_acceptor* /*acceptor*/, grpc_closure* on_handshake_done, HandshakerArgs* args) override { diff --git a/test/core/http/httpcli_test.cc b/test/core/http/httpcli_test.cc index a227050555b..f9fd3114807 100644 --- a/test/core/http/httpcli_test.cc +++ b/test/core/http/httpcli_test.cc @@ -41,14 +41,14 @@ static grpc_millis n_seconds_time(int seconds) { grpc_timeout_seconds_to_deadline(seconds)); } -static void on_finish(void* arg, grpc_error* error) { +static void on_finish(void* arg, grpc_error_handle error) { const char* expect = "Hello world!" "

This is a test

"; grpc_http_response* response = static_cast(arg); GPR_ASSERT(response); gpr_log(GPR_INFO, "response status=%d error=%s", response->status, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); GPR_ASSERT(response->status == 200); GPR_ASSERT(response->body_length == strlen(expect)); GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length)); @@ -138,7 +138,7 @@ static void test_post(int port) { grpc_http_response_destroy(&response); } -static void destroy_pops(void* p, grpc_error* /*error*/) { +static void destroy_pops(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy( grpc_polling_entity_pollset(static_cast(p))); } diff --git a/test/core/http/httpscli_test.cc b/test/core/http/httpscli_test.cc index 542fe553d19..a94a67b5f76 100644 --- a/test/core/http/httpscli_test.cc +++ b/test/core/http/httpscli_test.cc @@ -44,14 +44,14 @@ static grpc_millis n_seconds_time(int seconds) { grpc_timeout_seconds_to_deadline(seconds)); } -static void on_finish(void* arg, grpc_error* error) { +static void on_finish(void* arg, grpc_error_handle error) { const char* expect = "Hello world!" "

This is a test

"; grpc_http_response* response = static_cast(arg); GPR_ASSERT(response); gpr_log(GPR_INFO, "response status=%d error=%s", response->status, - grpc_error_string(error)); + grpc_error_std_string(error).c_str()); GPR_ASSERT(response->status == 200); GPR_ASSERT(response->body_length == strlen(expect)); GPR_ASSERT(0 == memcmp(expect, response->body, response->body_length)); @@ -143,7 +143,7 @@ static void test_post(int port) { grpc_http_response_destroy(&response); } -static void destroy_pops(void* p, grpc_error* /*error*/) { +static void destroy_pops(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy( grpc_polling_entity_pollset(static_cast(p))); } diff --git a/test/core/http/parser_test.cc b/test/core/http/parser_test.cc index 04afdd2b9d1..c08df1d4e88 100644 --- a/test/core/http/parser_test.cc +++ b/test/core/http/parser_test.cc @@ -156,7 +156,7 @@ static void test_fails(grpc_slice_split_mode split_mode, size_t num_slices; size_t i; grpc_slice* slices; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_http_response response; response = {}; @@ -189,7 +189,7 @@ static void test_request_fails(grpc_slice_split_mode split_mode, size_t num_slices; size_t i; grpc_slice* slices; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_http_request request; memset(&request, 0, sizeof(request)); diff --git a/test/core/iomgr/BUILD b/test/core/iomgr/BUILD index 55b6d0eb706..03827578528 100644 --- a/test/core/iomgr/BUILD +++ b/test/core/iomgr/BUILD @@ -233,17 +233,6 @@ grpc_cc_test( ], ) -grpc_cc_test( - name = "sockaddr_utils_test", - srcs = ["sockaddr_utils_test.cc"], - language = "C++", - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:grpc_test_util", - ], -) - grpc_cc_test( name = "socket_utils_test", srcs = ["socket_utils_test.cc"], @@ -386,27 +375,3 @@ grpc_cc_test( "//test/core/util:grpc_test_util", ], ) - -grpc_cc_test( - name = "parse_address_test", - srcs = ["parse_address_test.cc"], - language = "C++", - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:grpc_test_util", - ], -) - -grpc_cc_test( - name = "parse_address_with_named_scope_id_test", - srcs = ["parse_address_with_named_scope_id_test.cc"], - language = "C++", - tags = ["no_windows"], - uses_polling = False, - deps = [ - "//:gpr", - "//:grpc", - "//test/core/util:grpc_test_util", - ], -) diff --git a/test/core/iomgr/buffer_list_test.cc b/test/core/iomgr/buffer_list_test.cc index 2c179c4a047..6df4156336c 100644 --- a/test/core/iomgr/buffer_list_test.cc +++ b/test/core/iomgr/buffer_list_test.cc @@ -28,7 +28,7 @@ static void TestShutdownFlushesListVerifier(void* arg, grpc_core::Timestamps* /*ts*/, - grpc_error* error) { + grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(arg != nullptr); gpr_atm* done = reinterpret_cast(arg); @@ -60,7 +60,7 @@ static void TestShutdownFlushesList() { static void TestVerifierCalledOnAckVerifier(void* arg, grpc_core::Timestamps* ts, - grpc_error* error) { + grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(arg != nullptr); GPR_ASSERT(ts->acked_time.time.clock_type == GPR_CLOCK_REALTIME); diff --git a/test/core/iomgr/combiner_test.cc b/test/core/iomgr/combiner_test.cc index fa0a23df59c..7aa0e1c0632 100644 --- a/test/core/iomgr/combiner_test.cc +++ b/test/core/iomgr/combiner_test.cc @@ -32,7 +32,7 @@ static void test_no_op(void) { GRPC_COMBINER_UNREF(grpc_combiner_create(), "test_no_op"); } -static void set_event_to_true(void* value, grpc_error* /*error*/) { +static void set_event_to_true(void* value, grpc_error_handle /*error*/) { gpr_event_set(static_cast(value), reinterpret_cast(1)); } @@ -62,7 +62,7 @@ typedef struct { size_t value; } ex_args; -static void check_one(void* a, grpc_error* /*error*/) { +static void check_one(void* a, grpc_error_handle /*error*/) { ex_args* args = static_cast(a); GPR_ASSERT(*args->ctr == args->value - 1); *args->ctr = args->value; @@ -114,11 +114,11 @@ static void test_execute_many(void) { static gpr_event got_in_finally; -static void in_finally(void* /*arg*/, grpc_error* /*error*/) { +static void in_finally(void* /*arg*/, grpc_error_handle /*error*/) { gpr_event_set(&got_in_finally, reinterpret_cast(1)); } -static void add_finally(void* arg, grpc_error* /*error*/) { +static void add_finally(void* arg, grpc_error_handle /*error*/) { static_cast(arg)->Run( GRPC_CLOSURE_CREATE(in_finally, arg, nullptr), GRPC_ERROR_NONE); } diff --git a/test/core/iomgr/endpoint_pair_test.cc b/test/core/iomgr/endpoint_pair_test.cc index 40d676abc32..fb7686b81ed 100644 --- a/test/core/iomgr/endpoint_pair_test.cc +++ b/test/core/iomgr/endpoint_pair_test.cc @@ -54,7 +54,7 @@ static grpc_endpoint_test_config configs[] = { {"tcp/tcp_socketpair", create_fixture_endpoint_pair, clean_up}, }; -static void destroy_pollset(void* p, grpc_error* /*error*/) { +static void destroy_pollset(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/iomgr/endpoint_tests.cc b/test/core/iomgr/endpoint_tests.cc index 1a16e843730..78a6df6bd71 100644 --- a/test/core/iomgr/endpoint_tests.cc +++ b/test/core/iomgr/endpoint_tests.cc @@ -118,14 +118,15 @@ struct read_and_write_test_state { grpc_closure write_scheduler; }; -static void read_scheduler(void* data, grpc_error* /* error */) { +static void read_scheduler(void* data, grpc_error_handle /* error */) { struct read_and_write_test_state* state = static_cast(data); grpc_endpoint_read(state->read_ep, &state->incoming, &state->done_read, /*urgent=*/false); } -static void read_and_write_test_read_handler(void* data, grpc_error* error) { +static void read_and_write_test_read_handler(void* data, + grpc_error_handle error) { struct read_and_write_test_state* state = static_cast(data); @@ -146,14 +147,15 @@ static void read_and_write_test_read_handler(void* data, grpc_error* error) { } } -static void write_scheduler(void* data, grpc_error* /* error */) { +static void write_scheduler(void* data, grpc_error_handle /* error */) { struct read_and_write_test_state* state = static_cast(data); grpc_endpoint_write(state->write_ep, &state->outgoing, &state->done_write, nullptr); } -static void read_and_write_test_write_handler(void* data, grpc_error* error) { +static void read_and_write_test_write_handler(void* data, + grpc_error_handle error) { struct read_and_write_test_state* state = static_cast(data); grpc_slice* slices = nullptr; @@ -272,7 +274,7 @@ static void read_and_write_test(grpc_endpoint_test_config config, grpc_endpoint_destroy(state.write_ep); } -static void inc_on_failure(void* arg, grpc_error* error) { +static void inc_on_failure(void* arg, grpc_error_handle error) { gpr_mu_lock(g_mu); *static_cast(arg) += (error != GRPC_ERROR_NONE); GPR_ASSERT(GRPC_LOG_IF_ERROR("kick", grpc_pollset_kick(g_pollset, nullptr))); diff --git a/test/core/iomgr/error_test.cc b/test/core/iomgr/error_test.cc index 3ba90147aad..e50a5f0140e 100644 --- a/test/core/iomgr/error_test.cc +++ b/test/core/iomgr/error_test.cc @@ -27,7 +27,7 @@ #include "test/core/util/test_config.h" static void test_set_get_int() { - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); GPR_ASSERT(error); intptr_t i = 0; GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i)); @@ -49,7 +49,7 @@ static void test_set_get_int() { } static void test_set_get_str() { - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"); grpc_slice str; GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL, &str)); @@ -76,7 +76,7 @@ static void test_set_get_str() { static void test_copy_and_unref() { // error1 has one ref - grpc_error* error1 = grpc_error_set_str( + grpc_error_handle error1 = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Test"), GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); grpc_slice str; @@ -87,7 +87,7 @@ static void test_copy_and_unref() { // error 1 has two refs GRPC_ERROR_REF(error1); // this gives error3 a ref to the new error, and decrements error1 to one ref - grpc_error* error3 = grpc_error_set_str( + grpc_error_handle error3 = grpc_error_set_str( error1, GRPC_ERROR_STR_SYSCALL, grpc_slice_from_static_string("syscall")); GPR_ASSERT(error3 != error1); // should not be the same because of extra ref GPR_ASSERT(grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE, &str)); @@ -105,10 +105,10 @@ static void test_copy_and_unref() { } static void test_create_referencing() { - grpc_error* child = grpc_error_set_str( + grpc_error_handle child = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child"), GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); - grpc_error* parent = + grpc_error_handle parent = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", &child, 1); GPR_ASSERT(parent); @@ -117,7 +117,7 @@ static void test_create_referencing() { } static void test_create_referencing_many() { - grpc_error* children[3]; + grpc_error_handle children[3]; children[0] = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child1"), GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); @@ -128,7 +128,7 @@ static void test_create_referencing_many() { GRPC_ERROR_CREATE_FROM_STATIC_STRING("Child3"), GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message 3")); - grpc_error* parent = + grpc_error_handle parent = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 3); GPR_ASSERT(parent); @@ -139,18 +139,18 @@ static void test_create_referencing_many() { } static void print_error_string() { - grpc_error* error = + grpc_error_handle error = grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED); error = grpc_error_set_int(error, GRPC_ERROR_INT_SIZE, 666); error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message")); - // gpr_log(GPR_DEBUG, "%s", grpc_error_string(error)); + // gpr_log(GPR_DEBUG, "%s", grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); } static void print_error_string_reference() { - grpc_error* children[2]; + grpc_error_handle children[2]; children[0] = grpc_error_set_str( grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("1"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED), @@ -162,7 +162,7 @@ static void print_error_string_reference() { GRPC_ERROR_STR_GRPC_MESSAGE, grpc_slice_from_static_string("message for child 2")); - grpc_error* parent = + grpc_error_handle parent = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING("Parent", children, 2); for (size_t i = 0; i < 2; ++i) { @@ -174,7 +174,7 @@ static void print_error_string_reference() { static void test_os_error() { int fake_errno = 5; const char* syscall = "syscall name"; - grpc_error* error = GRPC_OS_ERROR(fake_errno, syscall); + grpc_error_handle error = GRPC_OS_ERROR(fake_errno, syscall); intptr_t i = 0; GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i)); @@ -188,7 +188,7 @@ static void test_os_error() { } static void test_overflow() { - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow"); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Overflow"); for (size_t i = 0; i < 150; ++i) { error = grpc_error_add_child(error, diff --git a/test/core/iomgr/ev_epollex_linux_test.cc b/test/core/iomgr/ev_epollex_linux_test.cc index 5bc5935a95e..35c27ec8758 100644 --- a/test/core/iomgr/ev_epollex_linux_test.cc +++ b/test/core/iomgr/ev_epollex_linux_test.cc @@ -27,7 +27,7 @@ #include "test/core/util/test_config.h" -static void pollset_destroy(void* ps, grpc_error* /*error*/) { +static void pollset_destroy(void* ps, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(ps)); gpr_free(ps); } diff --git a/test/core/iomgr/fd_posix_test.cc b/test/core/iomgr/fd_posix_test.cc index 85f5378f7f4..9ca837e5d51 100644 --- a/test/core/iomgr/fd_posix_test.cc +++ b/test/core/iomgr/fd_posix_test.cc @@ -124,7 +124,7 @@ static void session_shutdown_cb(void* arg, /*session */ /* Called when data become readable in a session. */ static void session_read_cb(void* arg, /*session */ - grpc_error* error) { + grpc_error_handle error) { session* se = static_cast(arg); int fd = grpc_fd_wrapped_fd(se->em_fd); @@ -182,7 +182,7 @@ static void listen_shutdown_cb(void* arg /*server*/, int /*success*/) { /* Called when a new TCP connection request arrives in the listening port. */ static void listen_cb(void* arg, /*=sv_arg*/ - grpc_error* error) { + grpc_error_handle error) { server* sv = static_cast(arg); int fd; int flags; @@ -297,7 +297,7 @@ static void client_session_shutdown_cb(void* arg /*client*/, int /*success*/) { /* Write as much as possible, then register notify_on_write. */ static void client_session_write(void* arg, /*client */ - grpc_error* error) { + grpc_error_handle error) { client* cl = static_cast(arg); int fd = grpc_fd_wrapped_fd(cl->em_fd); ssize_t write_once = 0; @@ -404,7 +404,7 @@ void init_change_data(fd_change_data* fdc) { fdc->cb_that_ran = nullptr; } void destroy_change_data(fd_change_data* /*fdc*/) {} static void first_read_callback(void* arg /* fd_change_data */, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { fd_change_data* fdc = static_cast(arg); gpr_mu_lock(g_mu); @@ -415,7 +415,7 @@ static void first_read_callback(void* arg /* fd_change_data */, } static void second_read_callback(void* arg /* fd_change_data */, - grpc_error* /*error*/) { + grpc_error_handle /*error*/) { fd_change_data* fdc = static_cast(arg); gpr_mu_lock(g_mu); @@ -509,7 +509,7 @@ static void test_grpc_fd_change(void) { close(sv[1]); } -static void destroy_pollset(void* p, grpc_error* /*error*/) { +static void destroy_pollset(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm b/test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm index 24afdd28e03..a826f0469c6 100644 --- a/test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamClientTests.mm @@ -43,7 +43,7 @@ static void finish_connection() { gpr_mu_unlock(&g_mu); } -static void must_succeed(void* arg, grpc_error* error) { +static void must_succeed(void* arg, grpc_error_handle error) { GPR_ASSERT(g_connecting != nullptr); GPR_ASSERT(error == GRPC_ERROR_NONE); grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING("must_succeed called")); @@ -52,11 +52,10 @@ static void must_succeed(void* arg, grpc_error* error) { finish_connection(); } -static void must_fail(void* arg, grpc_error* error) { +static void must_fail(void* arg, grpc_error_handle error) { GPR_ASSERT(g_connecting == nullptr); GPR_ASSERT(error != GRPC_ERROR_NONE); - const char* error_str = grpc_error_string(error); - NSLog(@"%s", error_str); + NSLog(@"%s", grpc_error_std_string(error).c_str()); finish_connection(); } diff --git a/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm b/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm index 5cd0d693102..a4a8555a10d 100644 --- a/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm +++ b/test/core/iomgr/ios/CFStreamTests/CFStreamEndpointTests.mm @@ -40,7 +40,7 @@ static const int kBufferSize = 10000; static const int kRunLoopTimeout = 1; -static void set_atm(void *arg, grpc_error *error) { +static void set_atm(void *arg, grpc_error_handle error) { gpr_atm *p = static_cast(arg); gpr_atm_full_cas(p, -1, reinterpret_cast(error)); } @@ -138,7 +138,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch /* wait for the connection callback to finish */ XCTAssertEqual([self waitForEvent:&connected timeout:kConnectTimeout], YES); - XCTAssertEqual(reinterpret_cast(connected), GRPC_ERROR_NONE); + XCTAssertEqual(reinterpret_cast(connected), GRPC_ERROR_NONE); } - (void)tearDown { @@ -170,7 +170,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr); XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); - XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); + XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); while (recv_size < kBufferSize) { ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); @@ -189,7 +189,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch init_event_closure(&read_done, &read); grpc_endpoint_read(ep_, &read_one_slice, &read_done, /*urgent=*/false); XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); - XCTAssertEqual(reinterpret_cast(read), GRPC_ERROR_NONE); + XCTAssertEqual(reinterpret_cast(read), GRPC_ERROR_NONE); grpc_slice_buffer_move_into(&read_one_slice, &read_slices); XCTAssertLessThanOrEqual(read_slices.length, kBufferSize); } @@ -227,7 +227,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr); XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); - XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); + XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); while (recv_size < kBufferSize) { ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); @@ -244,7 +244,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch grpc_core::ExecCtx::Get()->Flush(); XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); - XCTAssertNotEqual(reinterpret_cast(read), GRPC_ERROR_NONE); + XCTAssertNotEqual(reinterpret_cast(read), GRPC_ERROR_NONE); grpc_slice_buffer_reset_and_unref(&read_slices); grpc_slice_buffer_reset_and_unref(&write_slices); @@ -276,7 +276,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch grpc_endpoint_write(ep_, &write_slices, &write_done, nullptr); XCTAssertEqual([self waitForEvent:&write timeout:kWriteTimeout], YES); - XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); + XCTAssertEqual(reinterpret_cast(write), GRPC_ERROR_NONE); while (recv_size < kBufferSize) { ssize_t size = recv(svr_fd_, read_buffer, kBufferSize, 0); @@ -290,7 +290,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch close(svr_fd_); XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); - XCTAssertNotEqual(reinterpret_cast(read), GRPC_ERROR_NONE); + XCTAssertNotEqual(reinterpret_cast(read), GRPC_ERROR_NONE); grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE); grpc_slice_buffer_reset_and_unref(&read_slices); @@ -316,7 +316,7 @@ static bool compare_slice_buffer_with_buffer(grpc_slice_buffer *slices, const ch close(svr_fd_); XCTAssertEqual([self waitForEvent:&read timeout:kReadTimeout], YES); - XCTAssertNotEqual(reinterpret_cast(read), GRPC_ERROR_NONE); + XCTAssertNotEqual(reinterpret_cast(read), GRPC_ERROR_NONE); grpc_endpoint_shutdown(ep_, GRPC_ERROR_NONE); grpc_slice_buffer_reset_and_unref(&read_slices); diff --git a/test/core/iomgr/load_file_test.cc b/test/core/iomgr/load_file_test.cc index a0e0e4d7a74..6974cedea11 100644 --- a/test/core/iomgr/load_file_test.cc +++ b/test/core/iomgr/load_file_test.cc @@ -37,7 +37,7 @@ static void test_load_empty_file(void) { FILE* tmp = nullptr; grpc_slice slice; grpc_slice slice_with_null_term; - grpc_error* error; + grpc_error_handle error; char* tmp_name; LOG_TEST_NAME("test_load_empty_file"); @@ -65,7 +65,7 @@ static void test_load_empty_file(void) { static void test_load_failure(void) { FILE* tmp = nullptr; grpc_slice slice; - grpc_error* error; + grpc_error_handle error; char* tmp_name; LOG_TEST_NAME("test_load_failure"); @@ -88,7 +88,7 @@ static void test_load_small_file(void) { FILE* tmp = nullptr; grpc_slice slice; grpc_slice slice_with_null_term; - grpc_error* error; + grpc_error_handle error; char* tmp_name; const char* blah = "blah"; @@ -120,7 +120,7 @@ static void test_load_small_file(void) { static void test_load_big_file(void) { FILE* tmp = nullptr; grpc_slice slice; - grpc_error* error; + grpc_error_handle error; char* tmp_name; static const size_t buffer_size = 124631; unsigned char* buffer = static_cast(gpr_malloc(buffer_size)); diff --git a/test/core/iomgr/poller/eventmanager_libuv_test.cc b/test/core/iomgr/poller/eventmanager_libuv_test.cc deleted file mode 100644 index 82b6de1b913..00000000000 --- a/test/core/iomgr/poller/eventmanager_libuv_test.cc +++ /dev/null @@ -1,90 +0,0 @@ - -/* - * - * Copyright 2019 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -#include "src/core/lib/iomgr/poller/eventmanager_libuv.h" - -#include -#include -#include - -#include "test/core/util/test_config.h" - -using grpc::experimental::LibuvEventManager; - -namespace grpc_core { -namespace { - -TEST(LibuvEventManager, Allocation) { - for (int i = 0; i < 10; i++) { - LibuvEventManager* em = - new LibuvEventManager(LibuvEventManager::Options(i)); - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1)); - delete em; - } -} - -TEST(LibuvEventManager, ShutdownRef) { - for (int i = 0; i < 10; i++) { - LibuvEventManager* em = - new LibuvEventManager(LibuvEventManager::Options(i)); - for (int j = 0; j < i; j++) { - em->ShutdownRef(); - } - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1)); - for (int j = 0; j < i; j++) { - em->ShutdownUnref(); - } - delete em; - } -} - -TEST(LibuvEventManager, ShutdownRefAsync) { - for (int i = 0; i < 10; i++) { - LibuvEventManager* em = - new LibuvEventManager(LibuvEventManager::Options(i)); - for (int j = 0; j < i; j++) { - em->ShutdownRef(); - } - // TSAN doesn't like this approach although this would work. TSAN considers - // it dangerous to have a destructor being called while its member function - // is called but LibuvEventManager handles this by making LibuvEventManager - // wait until all pending operations finish. - grpc_core::Thread deleter( - "deleter", [](void* em) { delete static_cast(em); }, - em); - deleter.Start(); - gpr_sleep_until(grpc_timeout_milliseconds_to_deadline(1)); - for (int j = 0; j < i; j++) { - em->ShutdownUnref(); - } - deleter.Join(); - } -} - -} // namespace -} // namespace grpc_core - -int main(int argc, char** argv) { - grpc_init(); - grpc::testing::TestEnvironment env(argc, argv); - ::testing::InitGoogleTest(&argc, argv); - int retval = RUN_ALL_TESTS(); - grpc_shutdown(); - return retval; -} diff --git a/test/core/iomgr/pollset_windows_starvation_test.cc b/test/core/iomgr/pollset_windows_starvation_test.cc index eed57b10075..3357e3b5bf9 100644 --- a/test/core/iomgr/pollset_windows_starvation_test.cc +++ b/test/core/iomgr/pollset_windows_starvation_test.cc @@ -91,7 +91,7 @@ int main(int argc, char** argv) { // Queue for work and once we're done, make sure to kick the remaining // threads. - grpc_error* error; + grpc_error_handle error; error = grpc_pollset_work(&pollset, NULL, GRPC_MILLIS_INF_FUTURE); error = grpc_pollset_kick(&pollset, NULL); diff --git a/test/core/iomgr/resolve_address_posix_test.cc b/test/core/iomgr/resolve_address_posix_test.cc index 04cf766d725..6924a35c753 100644 --- a/test/core/iomgr/resolve_address_posix_test.cc +++ b/test/core/iomgr/resolve_address_posix_test.cc @@ -56,7 +56,7 @@ typedef struct args_struct { grpc_pollset_set* pollset_set; } args_struct; -static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} +static void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} void args_init(args_struct* args) { gpr_event_init(&args->ev); @@ -118,7 +118,7 @@ static void poll_pollset_until_request_done(args_struct* args) { args->thd.Start(); } -static void must_succeed(void* argsp, grpc_error* err) { +static void must_succeed(void* argsp, grpc_error_handle err) { args_struct* args = static_cast(argsp); GPR_ASSERT(err == GRPC_ERROR_NONE); GPR_ASSERT(args->addrs != nullptr); @@ -128,7 +128,7 @@ static void must_succeed(void* argsp, grpc_error* err) { GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr)); } -static void must_fail(void* argsp, grpc_error* err) { +static void must_fail(void* argsp, grpc_error_handle err) { args_struct* args = static_cast(argsp); GPR_ASSERT(err != GRPC_ERROR_NONE); grpc_core::MutexLockForGprMu lock(args->mu); diff --git a/test/core/iomgr/resolve_address_test.cc b/test/core/iomgr/resolve_address_test.cc index b77fd72ad00..c8a4d15917e 100644 --- a/test/core/iomgr/resolve_address_test.cc +++ b/test/core/iomgr/resolve_address_test.cc @@ -48,7 +48,7 @@ typedef struct args_struct { grpc_pollset_set* pollset_set; } args_struct; -static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} +static void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} void args_init(args_struct* args) { gpr_event_init(&args->ev); @@ -105,7 +105,7 @@ static void poll_pollset_until_request_done(args_struct* args) { gpr_event_set(&args->ev, reinterpret_cast(1)); } -static void must_succeed(void* argsp, grpc_error* err) { +static void must_succeed(void* argsp, grpc_error_handle err) { args_struct* args = static_cast(argsp); GPR_ASSERT(err == GRPC_ERROR_NONE); GPR_ASSERT(args->addrs != nullptr); @@ -115,7 +115,7 @@ static void must_succeed(void* argsp, grpc_error* err) { GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr)); } -static void must_fail(void* argsp, grpc_error* err) { +static void must_fail(void* argsp, grpc_error_handle err) { args_struct* args = static_cast(argsp); GPR_ASSERT(err != GRPC_ERROR_NONE); grpc_core::MutexLockForGprMu lock(args->mu); @@ -124,7 +124,7 @@ static void must_fail(void* argsp, grpc_error* err) { } // This test assumes the environment has an ipv6 loopback -static void must_succeed_with_ipv6_first(void* argsp, grpc_error* err) { +static void must_succeed_with_ipv6_first(void* argsp, grpc_error_handle err) { args_struct* args = static_cast(argsp); GPR_ASSERT(err == GRPC_ERROR_NONE); GPR_ASSERT(args->addrs != nullptr); @@ -137,7 +137,7 @@ static void must_succeed_with_ipv6_first(void* argsp, grpc_error* err) { GRPC_LOG_IF_ERROR("pollset_kick", grpc_pollset_kick(args->pollset, nullptr)); } -static void must_succeed_with_ipv4_first(void* argsp, grpc_error* err) { +static void must_succeed_with_ipv4_first(void* argsp, grpc_error_handle err) { args_struct* args = static_cast(argsp); GPR_ASSERT(err == GRPC_ERROR_NONE); GPR_ASSERT(args->addrs != nullptr); diff --git a/test/core/iomgr/resource_quota_test.cc b/test/core/iomgr/resource_quota_test.cc index 7f516b77a43..5d71af13e6d 100644 --- a/test/core/iomgr/resource_quota_test.cc +++ b/test/core/iomgr/resource_quota_test.cc @@ -28,7 +28,7 @@ gpr_mu g_mu; gpr_cv g_cv; -static void inc_int_cb(void* a, grpc_error* /*error*/) { +static void inc_int_cb(void* a, grpc_error_handle /*error*/) { gpr_mu_lock(&g_mu); ++*static_cast(a); gpr_cv_signal(&g_cv); @@ -44,7 +44,7 @@ static void assert_counter_becomes(int* ctr, int value) { gpr_mu_unlock(&g_mu); } -static void set_event_cb(void* a, grpc_error* /*error*/) { +static void set_event_cb(void* a, grpc_error_handle /*error*/) { gpr_event_set(static_cast(a), reinterpret_cast(1)); } grpc_closure* set_event(gpr_event* ev) { @@ -57,7 +57,7 @@ typedef struct { grpc_closure* then; } reclaimer_args; -static void reclaimer_cb(void* args, grpc_error* error) { +static void reclaimer_cb(void* args, grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); reclaimer_args* a = static_cast(args); grpc_resource_user_free(a->resource_user, a->size); @@ -75,7 +75,7 @@ grpc_closure* make_reclaimer(grpc_resource_user* resource_user, size_t size, return GRPC_CLOSURE_CREATE(reclaimer_cb, a, grpc_schedule_on_exec_ctx); } -static void unused_reclaimer_cb(void* arg, grpc_error* error) { +static void unused_reclaimer_cb(void* arg, grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_CANCELLED); grpc_core::Closure::Run(DEBUG_LOCATION, static_cast(arg), GRPC_ERROR_NONE); diff --git a/test/core/iomgr/sockaddr_utils_test.cc b/test/core/iomgr/sockaddr_utils_test.cc deleted file mode 100644 index 6464933477f..00000000000 --- a/test/core/iomgr/sockaddr_utils_test.cc +++ /dev/null @@ -1,273 +0,0 @@ -/* - * - * 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. - * - */ - -/* With the addition of a libuv endpoint, sockaddr.h now includes uv.h when - using that endpoint. Because of various transitive includes in uv.h, - including windows.h on Windows, uv.h must be included before other system - headers. Therefore, sockaddr.h must always be included first */ -#include "src/core/lib/iomgr/sockaddr_utils.h" -#include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/socket_utils.h" - -#include -#include - -#include -#include -#include -#include "test/core/util/test_config.h" - -static grpc_resolved_address make_addr4(const uint8_t* data, size_t data_len) { - grpc_resolved_address resolved_addr4; - grpc_sockaddr_in* addr4 = - reinterpret_cast(resolved_addr4.addr); - memset(&resolved_addr4, 0, sizeof(resolved_addr4)); - addr4->sin_family = GRPC_AF_INET; - GPR_ASSERT(data_len == sizeof(addr4->sin_addr.s_addr)); - memcpy(&addr4->sin_addr.s_addr, data, data_len); - addr4->sin_port = grpc_htons(12345); - resolved_addr4.len = static_cast(sizeof(grpc_sockaddr_in)); - return resolved_addr4; -} - -static grpc_resolved_address make_addr6(const uint8_t* data, size_t data_len) { - grpc_resolved_address resolved_addr6; - grpc_sockaddr_in6* addr6 = - reinterpret_cast(resolved_addr6.addr); - memset(&resolved_addr6, 0, sizeof(resolved_addr6)); - addr6->sin6_family = GRPC_AF_INET6; - GPR_ASSERT(data_len == sizeof(addr6->sin6_addr.s6_addr)); - memcpy(&addr6->sin6_addr.s6_addr, data, data_len); - addr6->sin6_port = grpc_htons(12345); - resolved_addr6.len = static_cast(sizeof(grpc_sockaddr_in6)); - return resolved_addr6; -} - -static void set_addr6_scope_id(grpc_resolved_address* addr, uint32_t scope_id) { - grpc_sockaddr_in6* addr6 = reinterpret_cast(addr->addr); - GPR_ASSERT(addr6->sin6_family == GRPC_AF_INET6); - addr6->sin6_scope_id = scope_id; -} - -static const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xff, 0xff, 192, 0, 2, 1}; - -static const uint8_t kNotQuiteMapped[] = {0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xff, 0xfe, 192, 0, 2, 99}; -static const uint8_t kIPv4[] = {192, 0, 2, 1}; - -static const uint8_t kIPv6[] = {0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1}; - -static void test_sockaddr_is_v4mapped(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address output4; - grpc_resolved_address expect4; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_is_v4mapped"); - - /* v4mapped input should succeed. */ - input6 = make_addr6(kMapped, sizeof(kMapped)); - GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, nullptr)); - GPR_ASSERT(grpc_sockaddr_is_v4mapped(&input6, &output4)); - expect4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0); - - /* Non-v4mapped input should fail. */ - input6 = make_addr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); - GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, nullptr)); - GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input6, &output4)); - /* Output is unchanged. */ - GPR_ASSERT(memcmp(&expect4, &output4, sizeof(expect4)) == 0); - - /* Plain IPv4 input should also fail. */ - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(!grpc_sockaddr_is_v4mapped(&input4, nullptr)); -} - -static void test_sockaddr_to_v4mapped(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address output6; - grpc_resolved_address expect6; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_to_v4mapped"); - - /* IPv4 input should succeed. */ - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(grpc_sockaddr_to_v4mapped(&input4, &output6)); - expect6 = make_addr6(kMapped, sizeof(kMapped)); - GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0); - - /* IPv6 input should fail. */ - input6 = make_addr6(kIPv6, sizeof(kIPv6)); - GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6)); - /* Output is unchanged. */ - GPR_ASSERT(memcmp(&expect6, &output6, sizeof(output6)) == 0); - - /* Already-v4mapped input should also fail. */ - input6 = make_addr6(kMapped, sizeof(kMapped)); - GPR_ASSERT(!grpc_sockaddr_to_v4mapped(&input6, &output6)); -} - -static void test_sockaddr_is_wildcard(void) { - grpc_resolved_address wild4; - grpc_resolved_address wild6; - grpc_resolved_address wild_mapped; - grpc_resolved_address phony; - grpc_sockaddr_in* wild4_addr; - grpc_sockaddr_in6* wild6_addr; - grpc_sockaddr_in6* wild_mapped_addr; - int port; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_is_wildcard"); - - /* Generate wildcards. */ - grpc_sockaddr_make_wildcards(555, &wild4, &wild6); - GPR_ASSERT(grpc_sockaddr_to_v4mapped(&wild4, &wild_mapped)); - - /* Test 0.0.0.0:555 */ - port = -1; - GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild4, &port)); - GPR_ASSERT(port == 555); - wild4_addr = reinterpret_cast(&wild4.addr); - memset(&wild4_addr->sin_addr.s_addr, 0xbd, 1); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild4, &port)); - - /* Test [::]:555 */ - port = -1; - GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild6, &port)); - GPR_ASSERT(port == 555); - wild6_addr = reinterpret_cast(&wild6.addr); - memset(&wild6_addr->sin6_addr.s6_addr, 0xbd, 1); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild6, &port)); - - /* Test [::ffff:0.0.0.0]:555 */ - port = -1; - GPR_ASSERT(grpc_sockaddr_is_wildcard(&wild_mapped, &port)); - GPR_ASSERT(port == 555); - wild_mapped_addr = reinterpret_cast(&wild_mapped.addr); - memset(&wild_mapped_addr->sin6_addr.s6_addr, 0xbd, 1); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&wild_mapped, &port)); - - /* Test AF_UNSPEC. */ - port = -1; - memset(&phony, 0, sizeof(phony)); - GPR_ASSERT(!grpc_sockaddr_is_wildcard(&phony, &port)); - GPR_ASSERT(port == -1); -} - -static void expect_sockaddr_str(const char* expected, - grpc_resolved_address* addr, int normalize) { - gpr_log(GPR_INFO, " expect_sockaddr_str(%s)", expected); - std::string actual = grpc_sockaddr_to_string(addr, normalize); - GPR_ASSERT(actual == expected); -} - -static void expect_sockaddr_uri(const char* expected, - grpc_resolved_address* addr) { - gpr_log(GPR_INFO, " expect_sockaddr_uri(%s)", expected); - std::string actual = grpc_sockaddr_to_uri(addr); - GPR_ASSERT(actual == expected); -} - -static void test_sockaddr_to_string(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address phony; - grpc_sockaddr* phony_addr; - - gpr_log(GPR_INFO, "%s", "test_sockaddr_to_string"); - - errno = 0x7EADBEEF; - - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - expect_sockaddr_str("192.0.2.1:12345", &input4, 0); - expect_sockaddr_str("192.0.2.1:12345", &input4, 1); - expect_sockaddr_uri("ipv4:192.0.2.1:12345", &input4); - - input6 = make_addr6(kIPv6, sizeof(kIPv6)); - expect_sockaddr_str("[2001:db8::1]:12345", &input6, 0); - expect_sockaddr_str("[2001:db8::1]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[2001:db8::1]:12345", &input6); - - set_addr6_scope_id(&input6, 2); - expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 0); - expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[2001:db8::1%252]:12345", &input6); - - set_addr6_scope_id(&input6, 101); - expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 0); - expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[2001:db8::1%25101]:12345", &input6); - - input6 = make_addr6(kMapped, sizeof(kMapped)); - expect_sockaddr_str("[::ffff:192.0.2.1]:12345", &input6, 0); - expect_sockaddr_str("192.0.2.1:12345", &input6, 1); - expect_sockaddr_uri("ipv4:192.0.2.1:12345", &input6); - - input6 = make_addr6(kNotQuiteMapped, sizeof(kNotQuiteMapped)); - expect_sockaddr_str("[::fffe:c000:263]:12345", &input6, 0); - expect_sockaddr_str("[::fffe:c000:263]:12345", &input6, 1); - expect_sockaddr_uri("ipv6:[::fffe:c000:263]:12345", &input6); - - memset(&phony, 0, sizeof(phony)); - phony_addr = reinterpret_cast(phony.addr); - phony_addr->sa_family = 123; - expect_sockaddr_str("(sockaddr family=123)", &phony, 0); - expect_sockaddr_str("(sockaddr family=123)", &phony, 1); - GPR_ASSERT(grpc_sockaddr_to_uri(&phony).empty()); -} - -static void test_sockaddr_set_get_port(void) { - grpc_resolved_address input4; - grpc_resolved_address input6; - grpc_resolved_address phony; - grpc_sockaddr* phony_addr; - - gpr_log(GPR_DEBUG, "test_sockaddr_set_get_port"); - - input4 = make_addr4(kIPv4, sizeof(kIPv4)); - GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 12345); - GPR_ASSERT(grpc_sockaddr_set_port(&input4, 54321)); - GPR_ASSERT(grpc_sockaddr_get_port(&input4) == 54321); - - input6 = make_addr6(kIPv6, sizeof(kIPv6)); - GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 12345); - GPR_ASSERT(grpc_sockaddr_set_port(&input6, 54321)); - GPR_ASSERT(grpc_sockaddr_get_port(&input6) == 54321); - - memset(&phony, 0, sizeof(phony)); - phony_addr = reinterpret_cast(phony.addr); - phony_addr->sa_family = 123; - GPR_ASSERT(grpc_sockaddr_get_port(&phony) == 0); - GPR_ASSERT(grpc_sockaddr_set_port(&phony, 1234) == 0); -} - -int main(int argc, char** argv) { - grpc::testing::TestEnvironment env(argc, argv); - - test_sockaddr_is_v4mapped(); - test_sockaddr_to_v4mapped(); - test_sockaddr_is_wildcard(); - test_sockaddr_to_string(); - test_sockaddr_set_get_port(); - - return 0; -} diff --git a/test/core/iomgr/socket_utils_test.cc b/test/core/iomgr/socket_utils_test.cc index d307f04fb18..f6f0b37d0f3 100644 --- a/test/core/iomgr/socket_utils_test.cc +++ b/test/core/iomgr/socket_utils_test.cc @@ -80,7 +80,7 @@ static const grpc_socket_mutator_vtable mutator_vtable = { int main(int argc, char** argv) { int sock; - grpc_error* err; + grpc_error_handle err; grpc::testing::TestEnvironment env(argc, argv); sock = socket(PF_INET, SOCK_STREAM, 0); diff --git a/test/core/iomgr/stranded_event_test.cc b/test/core/iomgr/stranded_event_test.cc index 64f2c591f21..451182345b9 100644 --- a/test/core/iomgr/stranded_event_test.cc +++ b/test/core/iomgr/stranded_event_test.cc @@ -41,11 +41,11 @@ #include "absl/types/optional.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/security/credentials/alts/alts_credentials.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/security_connector/alts/alts_security_connector.h" diff --git a/test/core/iomgr/tcp_client_posix_test.cc b/test/core/iomgr/tcp_client_posix_test.cc index d9186094c59..4e21292c515 100644 --- a/test/core/iomgr/tcp_client_posix_test.cc +++ b/test/core/iomgr/tcp_client_posix_test.cc @@ -60,7 +60,7 @@ static void finish_connection() { gpr_mu_unlock(g_mu); } -static void must_succeed(void* /*arg*/, grpc_error* error) { +static void must_succeed(void* /*arg*/, grpc_error_handle error) { GPR_ASSERT(g_connecting != nullptr); GPR_ASSERT(error == GRPC_ERROR_NONE); grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -70,7 +70,7 @@ static void must_succeed(void* /*arg*/, grpc_error* error) { finish_connection(); } -static void must_fail(void* /*arg*/, grpc_error* error) { +static void must_fail(void* /*arg*/, grpc_error_handle error) { GPR_ASSERT(g_connecting == nullptr); GPR_ASSERT(error != GRPC_ERROR_NONE); finish_connection(); @@ -185,7 +185,7 @@ void test_fails(void) { gpr_mu_unlock(g_mu); } -static void destroy_pollset(void* p, grpc_error* /*error*/) { +static void destroy_pollset(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/iomgr/tcp_client_uv_test.cc b/test/core/iomgr/tcp_client_uv_test.cc index 35e8d180f4c..6b73833319f 100644 --- a/test/core/iomgr/tcp_client_uv_test.cc +++ b/test/core/iomgr/tcp_client_uv_test.cc @@ -54,7 +54,7 @@ static void finish_connection() { gpr_mu_unlock(g_mu); } -static void must_succeed(void* arg, grpc_error* error) { +static void must_succeed(void* arg, grpc_error_handle error) { GPR_ASSERT(g_connecting != NULL); GPR_ASSERT(error == GRPC_ERROR_NONE); grpc_endpoint_shutdown(g_connecting, GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -64,7 +64,7 @@ static void must_succeed(void* arg, grpc_error* error) { finish_connection(); } -static void must_fail(void* arg, grpc_error* error) { +static void must_fail(void* arg, grpc_error_handle error) { GPR_ASSERT(g_connecting == NULL); GPR_ASSERT(error != GRPC_ERROR_NONE); finish_connection(); @@ -182,7 +182,7 @@ void test_fails(void) { grpc_core::ExecCtx::Get()->Flush(); } -static void destroy_pollset(void* p, grpc_error* error) { +static void destroy_pollset(void* p, grpc_error_handle error) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/iomgr/tcp_posix_test.cc b/test/core/iomgr/tcp_posix_test.cc index 3d995eedc11..17c81b86477 100644 --- a/test/core/iomgr/tcp_posix_test.cc +++ b/test/core/iomgr/tcp_posix_test.cc @@ -172,7 +172,7 @@ static size_t count_slices(grpc_slice* slices, size_t nslices, return num_bytes; } -static void read_cb(void* user_data, grpc_error* error) { +static void read_cb(void* user_data, grpc_error_handle error) { struct read_socket_state* state = static_cast(user_data); size_t read_bytes; @@ -330,7 +330,7 @@ static grpc_slice* allocate_blocks(size_t num_bytes, size_t slice_size, } static void write_done(void* user_data /* write_socket_state */, - grpc_error* error) { + grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); struct write_socket_state* state = static_cast(user_data); @@ -383,7 +383,7 @@ void drain_socket_blocking(int fd, size_t num_bytes, size_t read_size) { /* Verifier for timestamps callback for write_test */ void timestamps_verifier(void* arg, grpc_core::Timestamps* ts, - grpc_error* error) { + grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(arg != nullptr); GPR_ASSERT(ts->sendmsg_time.time.clock_type == GPR_CLOCK_REALTIME); @@ -473,7 +473,7 @@ static void write_test(size_t num_bytes, size_t slice_size, gpr_free(slices); } -void on_fd_released(void* arg, grpc_error* /*errors*/) { +void on_fd_released(void* arg, grpc_error_handle /*errors*/) { int* done = static_cast(arg); *done = 1; GPR_ASSERT( @@ -619,7 +619,7 @@ static grpc_endpoint_test_config configs[] = { {"tcp/tcp_socketpair", create_fixture_tcp_socketpair, clean_up}, }; -static void destroy_pollset(void* p, grpc_error* /*error*/) { +static void destroy_pollset(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/iomgr/tcp_server_posix_test.cc b/test/core/iomgr/tcp_server_posix_test.cc index 1441c0d54e5..2e54266e48c 100644 --- a/test/core/iomgr/tcp_server_posix_test.cc +++ b/test/core/iomgr/tcp_server_posix_test.cc @@ -40,10 +40,10 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" @@ -112,7 +112,7 @@ static void on_connect_result_set(on_connect_result* result, result->server, acceptor->port_index, acceptor->fd_index); } -static void server_weak_ref_shutdown(void* arg, grpc_error* /*error*/) { +static void server_weak_ref_shutdown(void* arg, grpc_error_handle /*error*/) { server_weak_ref* weak_ref = static_cast(arg); weak_ref->server = nullptr; } @@ -220,8 +220,8 @@ static void test_no_op_with_port_and_start(void) { grpc_tcp_server_unref(s); } -static grpc_error* tcp_connect(const test_addr* remote, - on_connect_result* result) { +static grpc_error_handle tcp_connect(const test_addr* remote, + on_connect_result* result) { grpc_millis deadline = grpc_timespec_to_millis_round_up(grpc_timeout_seconds_to_deadline(10)); int clifd; @@ -249,7 +249,7 @@ static grpc_error* tcp_connect(const test_addr* remote, while (g_nconnects == nconnects_before && deadline > grpc_core::ExecCtx::Get()->Now()) { grpc_pollset_worker* worker = nullptr; - grpc_error* err; + grpc_error_handle err; if ((err = grpc_pollset_work(g_pollset, &worker, deadline)) != GRPC_ERROR_NONE) { gpr_mu_unlock(g_mu); @@ -358,7 +358,7 @@ static void test_connect(size_t num_connects, for (dst_idx = 0; dst_idx < dst_addrs->naddrs; ++dst_idx) { test_addr dst = dst_addrs->addrs[dst_idx]; on_connect_result result; - grpc_error* err; + grpc_error_handle err; if (dst.addr.len == 0) { gpr_log(GPR_DEBUG, "Skipping test of non-functional local IP %s", dst.str); @@ -373,7 +373,7 @@ static void test_connect(size_t num_connects, continue; } gpr_log(GPR_ERROR, "Failed to connect to %s: %s", dst.str, - grpc_error_string(err)); + grpc_error_std_string(err).c_str()); GPR_ASSERT(test_dst_addrs); dst_addrs->addrs[dst_idx].addr.len = 0; GRPC_ERROR_UNREF(err); @@ -423,7 +423,7 @@ static void test_connect(size_t num_connects, GPR_ASSERT(weak_ref.server == nullptr); } -static void destroy_pollset(void* p, grpc_error* /*error*/) { +static void destroy_pollset(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/iomgr/tcp_server_uv_test.cc b/test/core/iomgr/tcp_server_uv_test.cc index a084cccbb27..0bc0beb5184 100644 --- a/test/core/iomgr/tcp_server_uv_test.cc +++ b/test/core/iomgr/tcp_server_uv_test.cc @@ -33,9 +33,9 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" @@ -74,7 +74,7 @@ static void on_connect_result_set(on_connect_result* result, result->fd_index = acceptor->fd_index; } -static void server_weak_ref_shutdown(void* arg, grpc_error* error) { +static void server_weak_ref_shutdown(void* arg, grpc_error_handle error) { server_weak_ref* weak_ref = static_cast(arg); weak_ref->server = NULL; } @@ -282,7 +282,7 @@ static void test_connect(unsigned n) { GPR_ASSERT(weak_ref.server == NULL); } -static void destroy_pollset(void* p, grpc_error* error) { +static void destroy_pollset(void* p, grpc_error_handle error) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/iomgr/timer_list_test.cc b/test/core/iomgr/timer_list_test.cc index a26926d5a84..f4a1b20316d 100644 --- a/test/core/iomgr/timer_list_test.cc +++ b/test/core/iomgr/timer_list_test.cc @@ -41,7 +41,7 @@ static int cb_called[MAX_CB][2]; static const int64_t kMillisIn25Days = 2160000000; static const int64_t kHoursIn25Days = 600; -static void cb(void* arg, grpc_error* error) { +static void cb(void* arg, grpc_error_handle error) { cb_called[reinterpret_cast(arg)][error == GRPC_ERROR_NONE]++; } diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc index a0e02e240ab..a036b0c1018 100644 --- a/test/core/iomgr/udp_server_test.cc +++ b/test/core/iomgr/udp_server_test.cc @@ -172,7 +172,7 @@ static test_socket_factory* test_socket_factory_create(void) { return factory; } -static void destroy_pollset(void* p, grpc_error* /*error*/) { +static void destroy_pollset(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/json/fuzzer.cc b/test/core/json/fuzzer.cc index e9eecf2332b..2925611c330 100644 --- a/test/core/json/fuzzer.cc +++ b/test/core/json/fuzzer.cc @@ -29,7 +29,7 @@ bool squelch = true; bool leak_check = true; extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json::Parse( absl::string_view(reinterpret_cast(data), size), &error); GRPC_ERROR_UNREF(error); diff --git a/test/core/json/json_test.cc b/test/core/json/json_test.cc index 1e5b404b94d..c724f1b6342 100644 --- a/test/core/json/json_test.cc +++ b/test/core/json/json_test.cc @@ -75,9 +75,9 @@ void ValidateValue(const Json& actual, const Json& expected) { void RunSuccessTest(const char* input, const Json& expected, const char* expected_output) { gpr_log(GPR_INFO, "parsing string \"%s\" - should succeed", input); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(input, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ValidateValue(json, expected); std::string output = json.Dump(); EXPECT_EQ(output, expected_output); @@ -165,9 +165,9 @@ TEST(Json, Keywords) { void RunParseFailureTest(const char* input) { gpr_log(GPR_INFO, "parsing string \"%s\" - should fail", input); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(input, &error); - gpr_log(GPR_INFO, "error: %s", grpc_error_string(error)); + gpr_log(GPR_INFO, "error: %s", grpc_error_std_string(error).c_str()); EXPECT_NE(error, GRPC_ERROR_NONE); GRPC_ERROR_UNREF(error); } diff --git a/test/core/security/BUILD b/test/core/security/BUILD index b3ed6a2d76c..248e0bbadcf 100644 --- a/test/core/security/BUILD +++ b/test/core/security/BUILD @@ -73,13 +73,14 @@ grpc_cc_test( ) grpc_cc_test( - name = "authorization_engine_test", - srcs = ["authorization_engine_test.cc"], + name = "cel_authorization_engine_test", + srcs = ["cel_authorization_engine_test.cc"], external_deps = ["gtest"], language = "C++", deps = [ "//:gpr", "//:grpc", + "//:grpc_cel_engine", "//test/core/util:grpc_test_util", ], ) @@ -116,6 +117,7 @@ grpc_cc_test( deps = [ "//:gpr", "//:grpc", + "//:grpc_rbac_engine", "//test/core/util:grpc_test_util", "//test/core/util:grpc_test_util_base", ], @@ -406,6 +408,46 @@ grpc_cc_test( deps = [ "//:gpr", "//:grpc", + "//:grpc_secure", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "rbac_translator_test", + srcs = ["rbac_translator_test.cc"], + external_deps = ["gtest"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//:grpc_authorization_provider", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "authorization_matchers_test", + srcs = ["authorization_matchers_test.cc"], + external_deps = ["gtest"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//:grpc_rbac_engine", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "grpc_authorization_engine_test", + srcs = ["grpc_authorization_engine_test.cc"], + external_deps = ["gtest"], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//:grpc_rbac_engine", "//test/core/util:grpc_test_util", ], ) diff --git a/test/core/security/authorization_matchers_test.cc b/test/core/security/authorization_matchers_test.cc new file mode 100644 index 00000000000..36b38621d18 --- /dev/null +++ b/test/core/security/authorization_matchers_test.cc @@ -0,0 +1,420 @@ +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include + +#include +#include + +#include "src/core/lib/security/authorization/evaluate_args.h" +#include "src/core/lib/security/authorization/matchers.h" +#include "test/core/util/evaluate_args_test_util.h" + +namespace grpc_core { + +class AuthorizationMatchersTest : public ::testing::Test { + protected: + EvaluateArgsTestUtil args_; +}; + +TEST_F(AuthorizationMatchersTest, AlwaysAuthorizationMatcher) { + EvaluateArgs args = args_.MakeEvaluateArgs(); + AlwaysAuthorizationMatcher matcher; + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, NotAlwaysAuthorizationMatcher) { + EvaluateArgs args = args_.MakeEvaluateArgs(); + AlwaysAuthorizationMatcher matcher(/*not_rule=*/true); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, AndAuthorizationMatcherSuccessfulMatch) { + args_.AddPairToMetadata("foo", "bar"); + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> rules; + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value())); + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kDestPort, /*port=*/123)); + AndAuthorizationMatcher matcher(std::move(rules)); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, AndAuthorizationMatcherFailedMatch) { + args_.AddPairToMetadata("foo", "not_bar"); + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> rules; + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value())); + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kDestPort, /*port=*/123)); + AndAuthorizationMatcher matcher(std::move(rules)); + // Header rule fails. Expected value "bar", got "not_bar" for key "foo". + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, NotAndAuthorizationMatcher) { + args_.AddPairToMetadata(":path", "/expected/foo"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + StringMatcher string_matcher = + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"/expected/foo", + /*case_sensitive=*/false) + .value(); + std::vector> ids; + ids.push_back(absl::make_unique( + Rbac::Permission::RuleType::kPath, std::move(string_matcher))); + AndAuthorizationMatcher matcher(std::move(ids), /*not_rule=*/true); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, OrAuthorizationMatcherSuccessfulMatch) { + args_.AddPairToMetadata("foo", "bar"); + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + HeaderMatcher header_matcher = + HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value(); + std::vector> rules; + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, header_matcher)); + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kDestPort, /*port=*/456)); + OrAuthorizationMatcher matcher(std::move(rules)); + // Matches as header rule matches even though port rule fails. + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, OrAuthorizationMatcherFailedMatch) { + args_.AddPairToMetadata("foo", "not_bar"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> rules; + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value())); + OrAuthorizationMatcher matcher(std::move(rules)); + // Header rule fails. Expected value "bar", got "not_bar" for key "foo". + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, NotOrAuthorizationMatcher) { + args_.AddPairToMetadata("foo", "not_bar"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> rules; + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value())); + OrAuthorizationMatcher matcher(std::move(rules), /*not_rule=*/true); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, HybridAuthorizationMatcherSuccessfulMatch) { + args_.AddPairToMetadata("foo", "bar"); + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> sub_and_rules; + sub_and_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value())); + std::vector> sub_or_rules; + sub_or_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kDestPort, /*port=*/123)); + std::vector> and_rules; + and_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kAnd, std::move(sub_and_rules))); + and_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kOr, std::move(std::move(sub_or_rules)))); + AndAuthorizationMatcher matcher(std::move(and_rules)); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, HybridAuthorizationMatcherFailedMatch) { + args_.AddPairToMetadata("foo", "bar"); + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> sub_and_rules; + sub_and_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"foo", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value())); + sub_and_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"absent_key", HeaderMatcher::Type::kExact, + /*matcher=*/"some_value") + .value())); + std::vector> sub_or_rules; + sub_or_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kDestPort, /*port=*/123)); + std::vector> and_rules; + and_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kAnd, std::move(sub_and_rules))); + and_rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kOr, std::move(std::move(sub_or_rules)))); + AndAuthorizationMatcher matcher(std::move(and_rules)); + // Fails as "absent_key" header was not present. + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, PathAuthorizationMatcherSuccessfulMatch) { + args_.AddPairToMetadata(":path", "expected/path"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + PathAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"expected/path", + /*case_sensitive=*/false) + .value()); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, PathAuthorizationMatcherFailedMatch) { + args_.AddPairToMetadata(":path", "different/path"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + PathAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"expected/path", + /*case_sensitive=*/false) + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, NotPathAuthorizationMatcher) { + args_.AddPairToMetadata(":path", "expected/path"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + PathAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, "expected/path", false) + .value(), + /*not_rule=*/true); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, + PathAuthorizationMatcherFailedMatchMissingPath) { + EvaluateArgs args = args_.MakeEvaluateArgs(); + PathAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"expected/path", + /*case_sensitive=*/false) + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, HeaderAuthorizationMatcherSuccessfulMatch) { + args_.AddPairToMetadata("key123", "foo_xxx"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + HeaderAuthorizationMatcher matcher( + HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kPrefix, + /*matcher=*/"foo") + .value()); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, HeaderAuthorizationMatcherFailedMatch) { + args_.AddPairToMetadata("key123", "foo"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + HeaderAuthorizationMatcher matcher( + HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, + HeaderAuthorizationMatcherFailedMatchMultivaluedHeader) { + args_.AddPairToMetadata("key123", "foo"); + args_.AddPairToMetadata("key123", "bar"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + HeaderAuthorizationMatcher matcher( + HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact, + /*matcher=*/"foo") + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, + HeaderAuthorizationMatcherFailedMatchMissingHeader) { + EvaluateArgs args = args_.MakeEvaluateArgs(); + HeaderAuthorizationMatcher matcher( + HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kSuffix, + /*matcher=*/"foo") + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, NotHeaderAuthorizationMatcher) { + args_.AddPairToMetadata("key123", "foo"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + HeaderAuthorizationMatcher matcher( + HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value(), + /*not_rule=*/true); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, PortAuthorizationMatcherSuccessfulMatch) { + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + PortAuthorizationMatcher matcher(/*port=*/123); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, PortAuthorizationMatcherFailedMatch) { + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + PortAuthorizationMatcher matcher(/*port=*/456); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, NotPortAuthorizationMatcher) { + args_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + PortAuthorizationMatcher matcher(/*port=*/123, /*not_rule=*/true); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, + AuthenticatedMatcherUnAuthenticatedConnection) { + EvaluateArgs args = args_.MakeEvaluateArgs(); + AuthenticatedAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"foo.com", + /*case_sensitive=*/false) + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, + AuthenticatedMatcherAuthenticatedConnectionMatcherUnset) { + args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_SSL_TRANSPORT_SECURITY_TYPE); + EvaluateArgs args = args_.MakeEvaluateArgs(); + AuthenticatedAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"", + /*case_sensitive=*/false) + .value()); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, + AuthenticatedMatcherSuccessfulSpiffeIdMatches) { + args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_SSL_TRANSPORT_SECURITY_TYPE); + args_.AddPropertyToAuthContext(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, + "spiffe://foo.abc"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + AuthenticatedAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"spiffe://foo.abc", + /*case_sensitive=*/false) + .value()); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedSpiffeIdMatches) { + args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_SSL_TRANSPORT_SECURITY_TYPE); + args_.AddPropertyToAuthContext(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, + "spiffe://bar.abc"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + AuthenticatedAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"spiffe://foo.abc", + /*case_sensitive=*/false) + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, AuthenticatedMatcherFailedNothingMatches) { + args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_SSL_TRANSPORT_SECURITY_TYPE); + EvaluateArgs args = args_.MakeEvaluateArgs(); + AuthenticatedAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, + /*matcher=*/"foo", + /*case_sensitive=*/false) + .value()); + EXPECT_FALSE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, NotAuthenticatedMatcher) { + args_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + GRPC_SSL_TRANSPORT_SECURITY_TYPE); + EvaluateArgs args = args_.MakeEvaluateArgs(); + AuthenticatedAuthorizationMatcher matcher( + StringMatcher::Create(StringMatcher::Type::kExact, /*matcher=*/"foo", + /*case_sensitive=*/false) + .value(), + /*not_rule=*/true); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, PolicyAuthorizationMatcherSuccessfulMatch) { + args_.AddPairToMetadata("key123", "foo"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> rules; + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact, + /*matcher=*/"foo") + .value())); + PolicyAuthorizationMatcher matcher(Rbac::Policy( + Rbac::Permission(Rbac::Permission::RuleType::kOr, std::move(rules)), + Rbac::Principal(Rbac::Principal::RuleType::kAny))); + EXPECT_TRUE(matcher.Matches(args)); +} + +TEST_F(AuthorizationMatchersTest, PolicyAuthorizationMatcherFailedMatch) { + args_.AddPairToMetadata("key123", "foo"); + EvaluateArgs args = args_.MakeEvaluateArgs(); + std::vector> rules; + rules.push_back(absl::make_unique( + Rbac::Permission::RuleType::kHeader, + HeaderMatcher::Create(/*name=*/"key123", HeaderMatcher::Type::kExact, + /*matcher=*/"bar") + .value())); + PolicyAuthorizationMatcher matcher(Rbac::Policy( + Rbac::Permission(Rbac::Permission::RuleType::kOr, std::move(rules)), + Rbac::Principal(Rbac::Principal::RuleType::kAny))); + EXPECT_FALSE(matcher.Matches(args)); +} + +} // namespace grpc_core + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + grpc_init(); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; +} diff --git a/test/core/security/aws_request_signer_test.cc b/test/core/security/aws_request_signer_test.cc index e384183c42e..bc5780fadb3 100644 --- a/test/core/security/aws_request_signer_test.cc +++ b/test/core/security/aws_request_signer_test.cc @@ -65,7 +65,7 @@ const char* kBotoTestDate = "Mon, 09 Sep 2011 23:36:00 GMT"; // AWS official example from the developer doc. // https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html TEST(GrpcAwsRequestSignerTest, AWSOfficialExample) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( "AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY", "", "GET", "https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08", @@ -83,7 +83,7 @@ TEST(GrpcAwsRequestSignerTest, AWSOfficialExample) { } TEST(GrpcAwsRequestSignerTest, GetDescribeRegions) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kAmzTestAccessKeyId, kAmzTestSecretAccessKey, kAmzTestToken, "GET", "https://" @@ -100,7 +100,7 @@ TEST(GrpcAwsRequestSignerTest, GetDescribeRegions) { } TEST(GrpcAwsRequestSignerTest, PostGetCallerIdentity) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kAmzTestAccessKeyId, kAmzTestSecretAccessKey, kAmzTestToken, "POST", "https://" @@ -117,7 +117,7 @@ TEST(GrpcAwsRequestSignerTest, PostGetCallerIdentity) { } TEST(GrpcAwsRequestSignerTest, PostGetCallerIdentityNoToken) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kAmzTestAccessKeyId, kAmzTestSecretAccessKey, "", "POST", "https://" @@ -134,7 +134,7 @@ TEST(GrpcAwsRequestSignerTest, PostGetCallerIdentityNoToken) { } TEST(GrpcAwsRequestSignerTest, GetHost) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer(kBotoTestAccessKeyId, kBotoTestSecretAccessKey, kBotoTestToken, "GET", "https://host.foo.com", "us-east-1", @@ -149,7 +149,7 @@ TEST(GrpcAwsRequestSignerTest, GetHost) { } TEST(GrpcAwsRequestSignerTest, GetHostDuplicateQueryParam) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kBotoTestAccessKeyId, kBotoTestSecretAccessKey, kBotoTestToken, "GET", "https://host.foo.com/?foo=Zoo&foo=aha", "us-east-1", "", @@ -164,7 +164,7 @@ TEST(GrpcAwsRequestSignerTest, GetHostDuplicateQueryParam) { } TEST(GrpcAwsRequestSignerTest, PostWithUpperCaseHeaderKey) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kBotoTestAccessKeyId, kBotoTestSecretAccessKey, kBotoTestToken, "POST", "https://host.foo.com/", "us-east-1", "", @@ -179,7 +179,7 @@ TEST(GrpcAwsRequestSignerTest, PostWithUpperCaseHeaderKey) { } TEST(GrpcAwsRequestSignerTest, PostWithUpperCaseHeaderValue) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kBotoTestAccessKeyId, kBotoTestSecretAccessKey, kBotoTestToken, "POST", "https://host.foo.com/", "us-east-1", "", @@ -194,7 +194,7 @@ TEST(GrpcAwsRequestSignerTest, PostWithUpperCaseHeaderValue) { } TEST(GrpcAwsRequestSignerTest, SignPostWithHeader) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kBotoTestAccessKeyId, kBotoTestSecretAccessKey, kBotoTestToken, "POST", "https://host.foo.com/", "us-east-1", "", @@ -209,7 +209,7 @@ TEST(GrpcAwsRequestSignerTest, SignPostWithHeader) { } TEST(GrpcAwsRequestSignerTest, PostWithBodyNoCustomHeaders) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kBotoTestAccessKeyId, kBotoTestSecretAccessKey, kBotoTestToken, "POST", "https://host.foo.com/", "us-east-1", "foo=bar", @@ -226,7 +226,7 @@ TEST(GrpcAwsRequestSignerTest, PostWithBodyNoCustomHeaders) { } TEST(GrpcAwsRequestSignerTest, SignPostWithQueryString) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( kBotoTestAccessKeyId, kBotoTestSecretAccessKey, kBotoTestToken, "POST", "https://host.foo.com/?foo=bar", "us-east-1", "", @@ -241,7 +241,7 @@ TEST(GrpcAwsRequestSignerTest, SignPostWithQueryString) { } TEST(GrpcAwsRequestSignerTest, InvalidUrl) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer("access_key_id", "secret_access_key", "token", "POST", "invalid_url", "us-east-1", "", {}, &error); @@ -256,7 +256,7 @@ TEST(GrpcAwsRequestSignerTest, InvalidUrl) { } TEST(GrpcAwsRequestSignerTest, DuplicateRequestDate) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::AwsRequestSigner signer( "access_key_id", "secret_access_key", "token", "POST", "invalid_url", "us-east-1", "", {{"date", kBotoTestDate}, {"x-amz-date", kAmzTestDate}}, diff --git a/test/core/security/authorization_engine_test.cc b/test/core/security/cel_authorization_engine_test.cc similarity index 57% rename from test/core/security/authorization_engine_test.cc rename to test/core/security/cel_authorization_engine_test.cc index 4b456a93550..4c94a87d195 100644 --- a/test/core/security/authorization_engine_test.cc +++ b/test/core/security/cel_authorization_engine_test.cc @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "src/core/lib/security/authorization/authorization_engine.h" +#include "src/core/lib/security/authorization/cel_authorization_engine.h" #include namespace grpc_core { -class AuthorizationEngineTest : public ::testing::Test { +class CelAuthorizationEngineTest : public ::testing::Test { protected: void SetUp() override { deny_policy_ = envoy_config_rbac_v3_RBAC_new(arena_.ptr()); @@ -31,44 +31,44 @@ class AuthorizationEngineTest : public ::testing::Test { envoy_config_rbac_v3_RBAC* allow_policy_; }; -TEST_F(AuthorizationEngineTest, CreateEngineSuccessOnePolicy) { +TEST_F(CelAuthorizationEngineTest, CreateEngineSuccessOnePolicy) { std::vector policies{allow_policy_}; - std::unique_ptr engine = - AuthorizationEngine::CreateAuthorizationEngine(policies); + std::unique_ptr engine = + CelAuthorizationEngine::CreateCelAuthorizationEngine(policies); EXPECT_NE(engine, nullptr) - << "Error: Failed to create an AuthorizationEngine with one policy."; + << "Error: Failed to create CelAuthorizationEngine with one policy."; } -TEST_F(AuthorizationEngineTest, CreateEngineSuccessTwoPolicies) { +TEST_F(CelAuthorizationEngineTest, CreateEngineSuccessTwoPolicies) { std::vector policies{deny_policy_, allow_policy_}; - std::unique_ptr engine = - AuthorizationEngine::CreateAuthorizationEngine(policies); + std::unique_ptr engine = + CelAuthorizationEngine::CreateCelAuthorizationEngine(policies); EXPECT_NE(engine, nullptr) - << "Error: Failed to create an AuthorizationEngine with two policies."; + << "Error: Failed to create CelAuthorizationEngine with two policies."; } -TEST_F(AuthorizationEngineTest, CreateEngineFailNoPolicies) { +TEST_F(CelAuthorizationEngineTest, CreateEngineFailNoPolicies) { std::vector policies{}; - std::unique_ptr engine = - AuthorizationEngine::CreateAuthorizationEngine(policies); + std::unique_ptr engine = + CelAuthorizationEngine::CreateCelAuthorizationEngine(policies); EXPECT_EQ(engine, nullptr) - << "Error: Created an AuthorizationEngine without policies."; + << "Error: Created CelAuthorizationEngine without policies."; } -TEST_F(AuthorizationEngineTest, CreateEngineFailTooManyPolicies) { +TEST_F(CelAuthorizationEngineTest, CreateEngineFailTooManyPolicies) { std::vector policies{deny_policy_, allow_policy_, deny_policy_}; - std::unique_ptr engine = - AuthorizationEngine::CreateAuthorizationEngine(policies); + std::unique_ptr engine = + CelAuthorizationEngine::CreateCelAuthorizationEngine(policies); EXPECT_EQ(engine, nullptr) - << "Error: Created an AuthorizationEngine with more than two policies."; + << "Error: Created CelAuthorizationEngine with more than two policies."; } -TEST_F(AuthorizationEngineTest, CreateEngineFailWrongPolicyOrder) { +TEST_F(CelAuthorizationEngineTest, CreateEngineFailWrongPolicyOrder) { std::vector policies{allow_policy_, deny_policy_}; - std::unique_ptr engine = - AuthorizationEngine::CreateAuthorizationEngine(policies); - EXPECT_EQ(engine, nullptr) << "Error: Created an AuthorizationEngine with " + std::unique_ptr engine = + CelAuthorizationEngine::CreateCelAuthorizationEngine(policies); + EXPECT_EQ(engine, nullptr) << "Error: Created CelAuthorizationEngine with " "policies in the wrong order."; } diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc index 8bed1a05f31..0533247a182 100644 --- a/test/core/security/credentials_test.cc +++ b/test/core/security/credentials_test.cc @@ -415,7 +415,7 @@ typedef struct { } expected_md; typedef struct { - grpc_error* expected_error; + grpc_error_handle expected_error; const expected_md* expected; size_t expected_size; grpc_credentials_mdelem_array md_array; @@ -443,11 +443,11 @@ static void check_metadata(const expected_md* expected, } } -static void check_request_metadata(void* arg, grpc_error* error) { +static void check_request_metadata(void* arg, grpc_error_handle error) { request_metadata_state* state = static_cast(arg); gpr_log(GPR_INFO, "expected_error: %s", - grpc_error_string(state->expected_error)); - gpr_log(GPR_INFO, "actual_error: %s", grpc_error_string(error)); + grpc_error_std_string(state->expected_error).c_str()); + gpr_log(GPR_INFO, "actual_error: %s", grpc_error_std_string(error).c_str()); if (state->expected_error == GRPC_ERROR_NONE) { GPR_ASSERT(error == GRPC_ERROR_NONE); } else { @@ -470,7 +470,7 @@ static void check_request_metadata(void* arg, grpc_error* error) { } static request_metadata_state* make_request_metadata_state( - grpc_error* expected_error, const expected_md* expected, + grpc_error_handle expected_error, const expected_md* expected, size_t expected_size) { request_metadata_state* state = static_cast(gpr_zalloc(sizeof(*state))); @@ -487,7 +487,7 @@ static request_metadata_state* make_request_metadata_state( static void run_request_metadata_test(grpc_call_credentials* creds, grpc_auth_metadata_context auth_md_ctx, request_metadata_state* state) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (creds->get_request_metadata(&state->pollent, auth_md_ctx, &state->md_array, &state->on_request_metadata, &error)) { @@ -1674,13 +1674,13 @@ struct fake_call_creds : public grpc_call_credentials { grpc_auth_metadata_context /*context*/, grpc_credentials_mdelem_array* md_array, grpc_closure* /*on_request_metadata*/, - grpc_error** /*error*/) override { + grpc_error_handle* /*error*/) override { grpc_credentials_mdelem_array_add(md_array, phony_md_); return true; } void cancel_get_request_metadata(grpc_credentials_mdelem_array* /*md_array*/, - grpc_error* /*error*/) override {} + grpc_error_handle /*error*/) override {} private: grpc_mdelem phony_md_; @@ -2143,6 +2143,9 @@ static void validate_aws_external_account_creds_token_exchage_request( // Check that the body is constructed properly. GPR_ASSERT(body != nullptr); GPR_ASSERT(body_size != 0); + // Check that the regional_cred_verification_url got constructed + // with the correct AWS Region ("test_regionz" or "test_region"). + GPR_ASSERT(strstr(body, "regional_cred_verification_url_test_region")); GPR_ASSERT(request->handshaker == &grpc_httpcli_ssl); std::string get_url_equivalent = absl::StrFormat("%s?%s", "https://foo.com:5555/token", body); @@ -2213,7 +2216,7 @@ class TestExternalAccountCredentials final protected: void RetrieveSubjectToken( HTTPRequestContext* /*ctx*/, const Options& /*options*/, - std::function cb) override { + std::function cb) override { cb("test_subject_token", GRPC_ERROR_NONE); } }; @@ -2337,10 +2340,11 @@ static void test_external_account_creds_failure_invalid_token_url(void) { TestExternalAccountCredentials creds(options, {}); grpc_httpcli_set_override(httpcli_get_should_not_be_called, httpcli_post_should_not_be_called); - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Invalid token url: invalid_token_url."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); run_request_metadata_test(&creds, auth_md_ctx, state); @@ -2371,11 +2375,12 @@ test_external_account_creds_failure_invalid_service_account_impersonation_url( TestExternalAccountCredentials creds(options, {}); grpc_httpcli_set_override(httpcli_get_should_not_be_called, external_account_creds_httpcli_post_success); - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Invalid service account impersonation url: " "invalid_service_account_impersonation_url."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); run_request_metadata_test(&creds, auth_md_ctx, state); @@ -2407,12 +2412,13 @@ test_external_account_creds_failure_token_exchange_response_missing_access_token grpc_httpcli_set_override( httpcli_get_should_not_be_called, external_account_creds_httpcli_post_failure_token_exchange_response_missing_access_token); - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Missing or invalid access_token in " "{\"not_access_token\":\"not_access_token\",\"expires_in\":3599,\"token_" "type\":\"Bearer\"}."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); run_request_metadata_test(&creds, auth_md_ctx, state); @@ -2426,7 +2432,7 @@ static void test_url_external_account_creds_success_format_text(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( valid_url_external_account_creds_options_credential_source_format_text, &error); @@ -2463,7 +2469,7 @@ test_url_external_account_creds_success_with_qurey_params_format_text(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( valid_url_external_account_creds_options_credential_source_with_qurey_params_format_text, &error); @@ -2499,7 +2505,7 @@ static void test_url_external_account_creds_success_format_json(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( valid_url_external_account_creds_options_credential_source_format_json, &error); @@ -2532,7 +2538,7 @@ static void test_url_external_account_creds_success_format_json(void) { static void test_url_external_account_creds_failure_invalid_credential_source_url(void) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( invalid_url_external_account_creds_options_credential_source, &error); GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -2565,7 +2571,7 @@ static void test_file_external_account_creds_success_format_text(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; char* subject_token_path = write_tmp_jwt_file("test_subject_token"); grpc_core::Json credential_source = grpc_core::Json::Parse( absl::StrFormat( @@ -2606,7 +2612,7 @@ static void test_file_external_account_creds_success_format_json(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; char* subject_token_path = write_tmp_jwt_file("{\"access_token\":\"test_subject_token\"}"); grpc_core::Json credential_source = grpc_core::Json::Parse( @@ -2654,7 +2660,7 @@ static void test_file_external_account_creds_failure_file_not_found(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse("{\"file\":\"non_exisiting_file\"}", &error); GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -2677,8 +2683,9 @@ static void test_file_external_account_creds_failure_file_not_found(void) { grpc_httpcli_set_override(httpcli_get_should_not_be_called, httpcli_post_should_not_be_called); error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to load file"); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); run_request_metadata_test(creds.get(), auth_md_ctx, state); @@ -2692,7 +2699,7 @@ static void test_file_external_account_creds_failure_invalid_json_content( grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; char* subject_token_path = write_tmp_jwt_file("not_a_valid_json_file"); grpc_core::Json credential_source = grpc_core::Json::Parse( absl::StrFormat( @@ -2727,8 +2734,9 @@ static void test_file_external_account_creds_failure_invalid_json_content( httpcli_post_should_not_be_called); error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "The content of the file is not a valid json object."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); run_request_metadata_test(creds.get(), auth_md_ctx, state); @@ -2743,7 +2751,7 @@ static void test_aws_external_account_creds_success(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &error); GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -2780,7 +2788,7 @@ static void test_aws_external_account_creds_success_path_region_env_keys_url( grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; gpr_setenv("AWS_REGION", "test_regionz"); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &error); GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -2811,6 +2819,86 @@ static void test_aws_external_account_creds_success_path_region_env_keys_url( gpr_unsetenv("AWS_REGION"); } +static void +test_aws_external_account_creds_success_path_default_region_env_keys_url(void) { + expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}}; + grpc_core::ExecCtx exec_ctx; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, + nullptr, nullptr}; + gpr_setenv("AWS_DEFAULT_REGION", "test_regionz"); + grpc_error_handle error = GRPC_ERROR_NONE; + grpc_core::Json credential_source = grpc_core::Json::Parse( + valid_aws_external_account_creds_options_credential_source, &error); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_core::ExternalAccountCredentials::Options options = { + "external_account", // type; + "audience", // audience; + "subject_token_type", // subject_token_type; + "", // service_account_impersonation_url; + "https://foo.com:5555/token", // token_url; + "https://foo.com:5555/token_info", // token_info_url; + credential_source, // credential_source; + "quota_project_id", // quota_project_id; + "client_id", // client_id; + "client_secret", // client_secret; + }; + auto creds = + grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error); + GPR_ASSERT(creds != nullptr); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); + request_metadata_state* state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, + aws_external_account_creds_httpcli_post_success); + run_request_metadata_test(creds.get(), auth_md_ctx, state); + grpc_core::ExecCtx::Get()->Flush(); + grpc_httpcli_set_override(nullptr, nullptr); + gpr_unsetenv("AWS_DEFAULT_REGION"); +} + +static void +test_aws_external_account_creds_success_path_duplicate_region_env_keys_url( + void) { + expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}}; + grpc_core::ExecCtx exec_ctx; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, + nullptr, nullptr}; + // Make sure that AWS_REGION gets used over AWS_DEFAULT_REGION + gpr_setenv("AWS_REGION", "test_regionz"); + gpr_setenv("AWS_DEFAULT_REGION", "ERROR_REGION"); + grpc_error_handle error = GRPC_ERROR_NONE; + grpc_core::Json credential_source = grpc_core::Json::Parse( + valid_aws_external_account_creds_options_credential_source, &error); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_core::ExternalAccountCredentials::Options options = { + "external_account", // type; + "audience", // audience; + "subject_token_type", // subject_token_type; + "", // service_account_impersonation_url; + "https://foo.com:5555/token", // token_url; + "https://foo.com:5555/token_info", // token_info_url; + credential_source, // credential_source; + "quota_project_id", // quota_project_id; + "client_id", // client_id; + "client_secret", // client_secret; + }; + auto creds = + grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error); + GPR_ASSERT(creds != nullptr); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); + request_metadata_state* state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, + aws_external_account_creds_httpcli_post_success); + run_request_metadata_test(creds.get(), auth_md_ctx, state); + grpc_core::ExecCtx::Get()->Flush(); + grpc_httpcli_set_override(nullptr, nullptr); + gpr_unsetenv("AWS_REGION"); + gpr_unsetenv("AWS_DEFAULT_REGION"); +} + static void test_aws_external_account_creds_success_path_region_url_keys_env( void) { expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}}; @@ -2820,7 +2908,7 @@ static void test_aws_external_account_creds_success_path_region_url_keys_env( gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id"); gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key"); gpr_setenv("AWS_SESSION_TOKEN", "test_token"); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &error); GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -2863,7 +2951,98 @@ static void test_aws_external_account_creds_success_path_region_env_keys_env( gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id"); gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key"); gpr_setenv("AWS_SESSION_TOKEN", "test_token"); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; + grpc_core::Json credential_source = grpc_core::Json::Parse( + valid_aws_external_account_creds_options_credential_source, &error); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_core::ExternalAccountCredentials::Options options = { + "external_account", // type; + "audience", // audience; + "subject_token_type", // subject_token_type; + "", // service_account_impersonation_url; + "https://foo.com:5555/token", // token_url; + "https://foo.com:5555/token_info", // token_info_url; + credential_source, // credential_source; + "quota_project_id", // quota_project_id; + "client_id", // client_id; + "client_secret", // client_secret; + }; + auto creds = + grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error); + GPR_ASSERT(creds != nullptr); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); + request_metadata_state* state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, + aws_external_account_creds_httpcli_post_success); + run_request_metadata_test(creds.get(), auth_md_ctx, state); + grpc_core::ExecCtx::Get()->Flush(); + grpc_httpcli_set_override(nullptr, nullptr); + gpr_unsetenv("AWS_REGION"); + gpr_unsetenv("AWS_ACCESS_KEY_ID"); + gpr_unsetenv("AWS_SECRET_ACCESS_KEY"); + gpr_unsetenv("AWS_SESSION_TOKEN"); +} + +static void +test_aws_external_account_creds_success_path_default_region_env_keys_env(void) { + expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}}; + grpc_core::ExecCtx exec_ctx; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, + nullptr, nullptr}; + gpr_setenv("AWS_DEFAULT_REGION", "test_regionz"); + gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id"); + gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key"); + gpr_setenv("AWS_SESSION_TOKEN", "test_token"); + grpc_error_handle error = GRPC_ERROR_NONE; + grpc_core::Json credential_source = grpc_core::Json::Parse( + valid_aws_external_account_creds_options_credential_source, &error); + GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_core::ExternalAccountCredentials::Options options = { + "external_account", // type; + "audience", // audience; + "subject_token_type", // subject_token_type; + "", // service_account_impersonation_url; + "https://foo.com:5555/token", // token_url; + "https://foo.com:5555/token_info", // token_info_url; + credential_source, // credential_source; + "quota_project_id", // quota_project_id; + "client_id", // client_id; + "client_secret", // client_secret; + }; + auto creds = + grpc_core::AwsExternalAccountCredentials::Create(options, {}, &error); + GPR_ASSERT(creds != nullptr); + GPR_ASSERT(error == GRPC_ERROR_NONE); + GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); + request_metadata_state* state = + make_request_metadata_state(GRPC_ERROR_NONE, emd, GPR_ARRAY_SIZE(emd)); + grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, + aws_external_account_creds_httpcli_post_success); + run_request_metadata_test(creds.get(), auth_md_ctx, state); + grpc_core::ExecCtx::Get()->Flush(); + grpc_httpcli_set_override(nullptr, nullptr); + gpr_unsetenv("AWS_DEFAULT_REGION"); + gpr_unsetenv("AWS_ACCESS_KEY_ID"); + gpr_unsetenv("AWS_SECRET_ACCESS_KEY"); + gpr_unsetenv("AWS_SESSION_TOKEN"); +} + +static void +test_aws_external_account_creds_success_path_duplicate_region_env_keys_env( + void) { + expected_md emd[] = {{"authorization", "Bearer token_exchange_access_token"}}; + grpc_core::ExecCtx exec_ctx; + grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, + nullptr, nullptr}; + // Make sure that AWS_REGION gets used over AWS_DEFAULT_REGION + gpr_setenv("AWS_REGION", "test_regionz"); + gpr_setenv("AWS_DEFAULT_REGION", "ERROR_REGION"); + gpr_setenv("AWS_ACCESS_KEY_ID", "test_access_key_id"); + gpr_setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key"); + gpr_setenv("AWS_SESSION_TOKEN", "test_token"); + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( valid_aws_external_account_creds_options_credential_source, &error); GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -2892,6 +3071,7 @@ static void test_aws_external_account_creds_success_path_region_env_keys_env( grpc_core::ExecCtx::Get()->Flush(); grpc_httpcli_set_override(nullptr, nullptr); gpr_unsetenv("AWS_REGION"); + gpr_unsetenv("AWS_DEFAULT_REGION"); gpr_unsetenv("AWS_ACCESS_KEY_ID"); gpr_unsetenv("AWS_SECRET_ACCESS_KEY"); gpr_unsetenv("AWS_SESSION_TOKEN"); @@ -2899,7 +3079,7 @@ static void test_aws_external_account_creds_success_path_region_env_keys_env( static void test_aws_external_account_creds_failure_unmatched_environment_id( void) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( invalid_aws_external_account_creds_options_credential_source_unmatched_environment_id, &error); @@ -2932,7 +3112,7 @@ static void test_aws_external_account_creds_failure_invalid_region_url(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( invalid_aws_external_account_creds_options_credential_source_invalid_region_url, &error); @@ -2956,8 +3136,9 @@ static void test_aws_external_account_creds_failure_invalid_region_url(void) { GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Invalid region url: invalid_region_url."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, @@ -2972,7 +3153,7 @@ static void test_aws_external_account_creds_failure_invalid_url(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( invalid_aws_external_account_creds_options_credential_source_invalid_url, &error); @@ -2995,8 +3176,9 @@ static void test_aws_external_account_creds_failure_invalid_url(void) { GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Invalid url: invalid_url."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, @@ -3011,7 +3193,7 @@ static void test_aws_external_account_creds_failure_missing_role_name(void) { grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( invalid_aws_external_account_creds_options_credential_source_missing_role_name, &error); @@ -3035,8 +3217,9 @@ static void test_aws_external_account_creds_failure_missing_role_name(void) { GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Missing role name when retrieving signing keys."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, @@ -3053,7 +3236,7 @@ test_aws_external_account_creds_failure_invalid_regional_cred_verification_url( grpc_core::ExecCtx exec_ctx; grpc_auth_metadata_context auth_md_ctx = {test_service_url, test_method, nullptr, nullptr}; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json credential_source = grpc_core::Json::Parse( invalid_aws_external_account_creds_options_credential_source_invalid_regional_cred_verification_url, &error); @@ -3077,8 +3260,9 @@ test_aws_external_account_creds_failure_invalid_regional_cred_verification_url( GPR_ASSERT(creds->min_security_level() == GRPC_PRIVACY_AND_INTEGRITY); error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Creating aws request signer failed."); - grpc_error* expected_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Error occurred when fetching oauth2 token.", &error, 1); + grpc_error_handle expected_error = + GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( + "Error occurred when fetching oauth2 token.", &error, 1); request_metadata_state* state = make_request_metadata_state(expected_error, nullptr, 0); grpc_httpcli_set_override(aws_external_account_creds_httpcli_get_success, @@ -3235,8 +3419,12 @@ int main(int argc, char** argv) { test_file_external_account_creds_failure_invalid_json_content(); test_aws_external_account_creds_success(); test_aws_external_account_creds_success_path_region_env_keys_url(); + test_aws_external_account_creds_success_path_default_region_env_keys_url(); + test_aws_external_account_creds_success_path_duplicate_region_env_keys_url(); test_aws_external_account_creds_success_path_region_url_keys_env(); test_aws_external_account_creds_success_path_region_env_keys_env(); + test_aws_external_account_creds_success_path_default_region_env_keys_env(); + test_aws_external_account_creds_success_path_duplicate_region_env_keys_env(); test_aws_external_account_creds_failure_unmatched_environment_id(); test_aws_external_account_creds_failure_invalid_region_url(); test_aws_external_account_creds_failure_invalid_url(); diff --git a/test/core/security/evaluate_args_test.cc b/test/core/security/evaluate_args_test.cc index 2ddbdde9aee..de98537d5f3 100644 --- a/test/core/security/evaluate_args_test.cc +++ b/test/core/security/evaluate_args_test.cc @@ -1,4 +1,4 @@ -// Copyright 2020 gRPC authors. +// Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,227 +17,139 @@ #include #include -#include "absl/strings/string_view.h" - #include "src/core/lib/security/authorization/evaluate_args.h" -#include "test/core/util/eval_args_mock_endpoint.h" +#include "test/core/util/evaluate_args_test_util.h" #include "test/core/util/test_config.h" namespace grpc_core { class EvaluateArgsTest : public ::testing::Test { protected: - void SetUp() override { - local_address_ = "255.255.255.255"; - peer_address_ = "128.128.128.128"; - local_port_ = 413; - peer_port_ = 314; - endpoint_ = CreateEvalArgsMockEndpoint(local_address_.c_str(), local_port_, - peer_address_.c_str(), peer_port_); - evaluate_args_ = - absl::make_unique(nullptr, nullptr, endpoint_); - } - void TearDown() override { grpc_endpoint_destroy(endpoint_); } - grpc_endpoint* endpoint_; - std::unique_ptr evaluate_args_; - std::string local_address_; - std::string peer_address_; - int local_port_; - int peer_port_; + EvaluateArgsTestUtil util_; }; -TEST_F(EvaluateArgsTest, TestEvaluateArgsLocalAddress) { - absl::string_view src_address = evaluate_args_->GetLocalAddress(); - EXPECT_EQ(src_address, local_address_); +TEST_F(EvaluateArgsTest, EmptyMetadata) { + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetPath(), nullptr); + EXPECT_EQ(args.GetMethod(), nullptr); + EXPECT_EQ(args.GetHost(), nullptr); + EXPECT_THAT(args.GetHeaders(), ::testing::ElementsAre()); + EXPECT_EQ(args.GetHeaderValue("some_key", nullptr), absl::nullopt); } -TEST_F(EvaluateArgsTest, TestEvaluateArgsLocalPort) { - int src_port = evaluate_args_->GetLocalPort(); - EXPECT_EQ(src_port, local_port_); +TEST_F(EvaluateArgsTest, GetPathSuccess) { + util_.AddPairToMetadata(":path", "/expected/path"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetPath(), "/expected/path"); } -TEST_F(EvaluateArgsTest, TestEvaluateArgsPeerAddress) { - absl::string_view dest_address = evaluate_args_->GetPeerAddress(); - EXPECT_EQ(dest_address, peer_address_); +TEST_F(EvaluateArgsTest, GetHostSuccess) { + util_.AddPairToMetadata("host", "host123"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetHost(), "host123"); } -TEST_F(EvaluateArgsTest, TestEvaluateArgsPeerPort) { - int dest_port = evaluate_args_->GetPeerPort(); - EXPECT_EQ(dest_port, peer_port_); +TEST_F(EvaluateArgsTest, GetMethodSuccess) { + util_.AddPairToMetadata(":method", "GET"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetMethod(), "GET"); } -TEST(EvaluateArgsMetadataTest, HandlesNullMetadata) { - EvaluateArgs eval_args(nullptr, nullptr, nullptr); - EXPECT_EQ(eval_args.GetPath(), nullptr); - EXPECT_EQ(eval_args.GetMethod(), nullptr); - EXPECT_EQ(eval_args.GetHost(), nullptr); - EXPECT_THAT(eval_args.GetHeaders(), ::testing::ElementsAre()); - EXPECT_EQ(eval_args.GetHeaderValue("some_key", nullptr), absl::nullopt); +TEST_F(EvaluateArgsTest, GetHeadersSuccess) { + util_.AddPairToMetadata("host", "host123"); + util_.AddPairToMetadata(":path", "/expected/path"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_THAT(args.GetHeaders(), + ::testing::UnorderedElementsAre( + ::testing::Pair("host", "host123"), + ::testing::Pair(":path", "/expected/path"))); } -TEST(EvaluateArgsMetadataTest, HandlesEmptyMetadata) { - grpc_metadata_batch metadata; - grpc_metadata_batch_init(&metadata); - EvaluateArgs eval_args(&metadata, nullptr, nullptr); - EXPECT_EQ(eval_args.GetPath(), nullptr); - EXPECT_EQ(eval_args.GetMethod(), nullptr); - EXPECT_EQ(eval_args.GetHost(), nullptr); - EXPECT_THAT(eval_args.GetHeaders(), ::testing::ElementsAre()); - EXPECT_EQ(eval_args.GetHeaderValue("some_key", nullptr), absl::nullopt); - grpc_metadata_batch_destroy(&metadata); +TEST_F(EvaluateArgsTest, GetHeaderValueSuccess) { + util_.AddPairToMetadata("key123", "value123"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + std::string concatenated_value; + absl::optional value = + args.GetHeaderValue("key123", &concatenated_value); + ASSERT_TRUE(value.has_value()); + EXPECT_EQ(value.value(), "value123"); } -TEST(EvaluateArgsMetadataTest, GetPathSuccess) { - grpc_init(); - const char* kPath = "/some/path"; - grpc_metadata_batch metadata; - grpc_metadata_batch_init(&metadata); - grpc_slice fake_val = grpc_slice_intern(grpc_slice_from_static_string(kPath)); - grpc_mdelem fake_val_md = grpc_mdelem_from_slices(GRPC_MDSTR_PATH, fake_val); - grpc_linked_mdelem storage; - storage.md = fake_val_md; - ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage), - GRPC_ERROR_NONE); - EvaluateArgs eval_args(&metadata, nullptr, nullptr); - EXPECT_EQ(eval_args.GetPath(), kPath); - grpc_metadata_batch_destroy(&metadata); - grpc_shutdown(); +TEST_F(EvaluateArgsTest, TestIpv4LocalAddressAndPort) { + util_.SetLocalEndpoint("ipv4:255.255.255.255:123"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetLocalAddress(), "255.255.255.255"); + EXPECT_EQ(args.GetLocalPort(), 123); } -TEST(EvaluateArgsMetadataTest, GetHostSuccess) { - grpc_init(); - const char* kHost = "host"; - grpc_metadata_batch metadata; - grpc_metadata_batch_init(&metadata); - grpc_slice fake_val = grpc_slice_intern(grpc_slice_from_static_string(kHost)); - grpc_mdelem fake_val_md = grpc_mdelem_from_slices(GRPC_MDSTR_HOST, fake_val); - grpc_linked_mdelem storage; - storage.md = fake_val_md; - ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage), - GRPC_ERROR_NONE); - EvaluateArgs eval_args(&metadata, nullptr, nullptr); - EXPECT_EQ(eval_args.GetHost(), kHost); - grpc_metadata_batch_destroy(&metadata); - grpc_shutdown(); +TEST_F(EvaluateArgsTest, TestIpv4PeerAddressAndPort) { + util_.SetPeerEndpoint("ipv4:128.128.128.128:321"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetPeerAddress(), "128.128.128.128"); + EXPECT_EQ(args.GetPeerPort(), 321); } -TEST(EvaluateArgsMetadataTest, GetMethodSuccess) { - grpc_init(); - const char* kMethod = "GET"; - grpc_metadata_batch metadata; - grpc_metadata_batch_init(&metadata); - grpc_slice fake_val = - grpc_slice_intern(grpc_slice_from_static_string(kMethod)); - grpc_mdelem fake_val_md = - grpc_mdelem_from_slices(GRPC_MDSTR_METHOD, fake_val); - grpc_linked_mdelem storage; - storage.md = fake_val_md; - ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage), - GRPC_ERROR_NONE); - EvaluateArgs eval_args(&metadata, nullptr, nullptr); - EXPECT_EQ(eval_args.GetMethod(), kMethod); - grpc_metadata_batch_destroy(&metadata); - grpc_shutdown(); +TEST_F(EvaluateArgsTest, TestIpv6LocalAddressAndPort) { + util_.SetLocalEndpoint("ipv6:[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:456"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetLocalAddress(), "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + EXPECT_EQ(args.GetLocalPort(), 456); } -TEST(EvaluateArgsMetadataTest, GetHeadersSuccess) { - grpc_init(); - const char* kPath = "/some/path"; - const char* kHost = "host"; - grpc_metadata_batch metadata; - grpc_metadata_batch_init(&metadata); - grpc_slice fake_path = - grpc_slice_intern(grpc_slice_from_static_string(kPath)); - grpc_mdelem fake_path_md = - grpc_mdelem_from_slices(GRPC_MDSTR_PATH, fake_path); - grpc_linked_mdelem storage; - storage.md = fake_path_md; - ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage, GRPC_BATCH_PATH), - GRPC_ERROR_NONE); - grpc_slice fake_host = - grpc_slice_intern(grpc_slice_from_static_string(kHost)); - grpc_mdelem fake_host_md = - grpc_mdelem_from_slices(GRPC_MDSTR_HOST, fake_host); - grpc_linked_mdelem storage2; - storage2.md = fake_host_md; - ASSERT_EQ( - grpc_metadata_batch_link_tail(&metadata, &storage2, GRPC_BATCH_HOST), - GRPC_ERROR_NONE); - EvaluateArgs eval_args(&metadata, nullptr, nullptr); - EXPECT_THAT( - eval_args.GetHeaders(), - ::testing::UnorderedElementsAre( - ::testing::Pair(StringViewFromSlice(GRPC_MDSTR_HOST), kHost), - ::testing::Pair(StringViewFromSlice(GRPC_MDSTR_PATH), kPath))); - grpc_metadata_batch_destroy(&metadata); - grpc_shutdown(); +TEST_F(EvaluateArgsTest, TestIpv6PeerAddressAndPort) { + util_.SetPeerEndpoint("ipv6:[2001:db8::1]:654"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetPeerAddress(), "2001:db8::1"); + EXPECT_EQ(args.GetPeerPort(), 654); } -TEST(EvaluateArgsMetadataTest, GetHeaderValueSuccess) { - grpc_init(); - const char* kKey = "some_key"; - const char* kValue = "some_value"; - grpc_metadata_batch metadata; - grpc_metadata_batch_init(&metadata); - grpc_linked_mdelem storage; - storage.md = grpc_mdelem_from_slices( - grpc_slice_intern(grpc_slice_from_static_string(kKey)), - grpc_slice_intern(grpc_slice_from_static_string(kValue))); - ASSERT_EQ(grpc_metadata_batch_link_head(&metadata, &storage), - GRPC_ERROR_NONE); - EvaluateArgs eval_args(&metadata, nullptr, nullptr); - std::string concatenated_value; - absl::optional value = - eval_args.GetHeaderValue(kKey, &concatenated_value); - ASSERT_TRUE(value.has_value()); - EXPECT_EQ(value.value(), kValue); - grpc_metadata_batch_destroy(&metadata); - grpc_shutdown(); +TEST_F(EvaluateArgsTest, EmptyAuthContext) { + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_TRUE(args.GetTransportSecurityType().empty()); + EXPECT_TRUE(args.GetSpiffeId().empty()); + EXPECT_TRUE(args.GetCommonName().empty()); } -TEST(EvaluateArgsAuthContextTest, HandlesNullAuthContext) { - EvaluateArgs eval_args(nullptr, nullptr, nullptr); - EXPECT_EQ(eval_args.GetSpiffeId(), nullptr); - EXPECT_EQ(eval_args.GetCertServerName(), nullptr); +TEST_F(EvaluateArgsTest, GetTransportSecurityTypeSuccessOneProperty) { + util_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + "ssl"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetTransportSecurityType(), "ssl"); } -TEST(EvaluateArgsAuthContextTest, HandlesEmptyAuthCtx) { - grpc_auth_context auth_context(nullptr); - EvaluateArgs eval_args(nullptr, &auth_context, nullptr); - EXPECT_EQ(eval_args.GetSpiffeId(), nullptr); - EXPECT_EQ(eval_args.GetCertServerName(), nullptr); +TEST_F(EvaluateArgsTest, GetTransportSecurityTypeFailDuplicateProperty) { + util_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + "type1"); + util_.AddPropertyToAuthContext(GRPC_TRANSPORT_SECURITY_TYPE_PROPERTY_NAME, + "type2"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_TRUE(args.GetTransportSecurityType().empty()); } -TEST(EvaluateArgsAuthContextTest, GetSpiffeIdSuccessOneProperty) { - grpc_auth_context auth_context(nullptr); - const char* kId = "spiffeid"; - auth_context.add_cstring_property(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, kId); - EvaluateArgs eval_args(nullptr, &auth_context, nullptr); - EXPECT_EQ(eval_args.GetSpiffeId(), kId); +TEST_F(EvaluateArgsTest, GetSpiffeIdSuccessOneProperty) { + util_.AddPropertyToAuthContext(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, "id123"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetSpiffeId(), "id123"); } -TEST(EvaluateArgsAuthContextTest, GetSpiffeIdFailDuplicateProperty) { - grpc_auth_context auth_context(nullptr); - auth_context.add_cstring_property(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, "id1"); - auth_context.add_cstring_property(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, "id2"); - EvaluateArgs eval_args(nullptr, &auth_context, nullptr); - EXPECT_EQ(eval_args.GetSpiffeId(), nullptr); +TEST_F(EvaluateArgsTest, GetSpiffeIdFailDuplicateProperty) { + util_.AddPropertyToAuthContext(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, "id123"); + util_.AddPropertyToAuthContext(GRPC_PEER_SPIFFE_ID_PROPERTY_NAME, "id456"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_TRUE(args.GetSpiffeId().empty()); } -TEST(EvaluateArgsAuthContextTest, GetCertServerNameSuccessOneProperty) { - grpc_auth_context auth_context(nullptr); - const char* kServer = "server"; - auth_context.add_cstring_property(GRPC_X509_CN_PROPERTY_NAME, kServer); - EvaluateArgs eval_args(nullptr, &auth_context, nullptr); - EXPECT_EQ(eval_args.GetCertServerName(), kServer); +TEST_F(EvaluateArgsTest, GetCommonNameSuccessOneProperty) { + util_.AddPropertyToAuthContext(GRPC_X509_CN_PROPERTY_NAME, "server123"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_EQ(args.GetCommonName(), "server123"); } -TEST(EvaluateArgsAuthContextTest, GetCertServerNameFailDuplicateProperty) { - grpc_auth_context auth_context(nullptr); - auth_context.add_cstring_property(GRPC_X509_CN_PROPERTY_NAME, "server1"); - auth_context.add_cstring_property(GRPC_X509_CN_PROPERTY_NAME, "server2"); - EvaluateArgs eval_args(nullptr, &auth_context, nullptr); - EXPECT_EQ(eval_args.GetCertServerName(), nullptr); +TEST_F(EvaluateArgsTest, GetCommonNameFailDuplicateProperty) { + util_.AddPropertyToAuthContext(GRPC_X509_CN_PROPERTY_NAME, "server123"); + util_.AddPropertyToAuthContext(GRPC_X509_CN_PROPERTY_NAME, "server456"); + EvaluateArgs args = util_.MakeEvaluateArgs(); + EXPECT_TRUE(args.GetCommonName().empty()); } } // namespace grpc_core @@ -245,5 +157,8 @@ TEST(EvaluateArgsAuthContextTest, GetCertServerNameFailDuplicateProperty) { int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); + grpc_init(); + int ret = RUN_ALL_TESTS(); + grpc_shutdown(); + return ret; } diff --git a/test/core/security/grpc_authorization_engine_test.cc b/test/core/security/grpc_authorization_engine_test.cc new file mode 100644 index 00000000000..a2b5e11443e --- /dev/null +++ b/test/core/security/grpc_authorization_engine_test.cc @@ -0,0 +1,107 @@ +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include +#include + +#include "src/core/lib/security/authorization/grpc_authorization_engine.h" + +namespace grpc_core { + +TEST(GrpcAuthorizationEngineTest, AllowEngineWithMatchingPolicy) { + Rbac::Policy policy1( + Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true), + Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true)); + Rbac::Policy policy2((Rbac::Permission(Rbac::Permission::RuleType::kAny)), + (Rbac::Principal(Rbac::Principal::RuleType::kAny))); + std::map policies; + policies["policy1"] = std::move(policy1); + policies["policy2"] = std::move(policy2); + Rbac rbac(Rbac::Action::kAllow, std::move(policies)); + GrpcAuthorizationEngine engine(std::move(rbac)); + AuthorizationEngine::Decision decision = + engine.Evaluate(EvaluateArgs(nullptr, nullptr)); + EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow); + EXPECT_EQ(decision.matching_policy_name, "policy2"); +} + +TEST(GrpcAuthorizationEngineTest, AllowEngineWithNoMatchingPolicy) { + Rbac::Policy policy1( + Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true), + Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true)); + std::map policies; + policies["policy1"] = std::move(policy1); + Rbac rbac(Rbac::Action::kAllow, std::move(policies)); + GrpcAuthorizationEngine engine(std::move(rbac)); + AuthorizationEngine::Decision decision = + engine.Evaluate(EvaluateArgs(nullptr, nullptr)); + EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny); + EXPECT_TRUE(decision.matching_policy_name.empty()); +} + +TEST(GrpcAuthorizationEngineTest, AllowEngineWithEmptyPolicies) { + GrpcAuthorizationEngine engine(Rbac::Action::kAllow); + AuthorizationEngine::Decision decision = + engine.Evaluate(EvaluateArgs(nullptr, nullptr)); + EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny); + EXPECT_TRUE(decision.matching_policy_name.empty()); +} + +TEST(GrpcAuthorizationEngineTest, DenyEngineWithMatchingPolicy) { + Rbac::Policy policy1( + Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true), + Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true)); + Rbac::Policy policy2((Rbac::Permission(Rbac::Permission::RuleType::kAny)), + (Rbac::Principal(Rbac::Principal::RuleType::kAny))); + std::map policies; + policies["policy1"] = std::move(policy1); + policies["policy2"] = std::move(policy2); + Rbac rbac(Rbac::Action::kDeny, std::move(policies)); + GrpcAuthorizationEngine engine(std::move(rbac)); + AuthorizationEngine::Decision decision = + engine.Evaluate(EvaluateArgs(nullptr, nullptr)); + EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kDeny); + EXPECT_EQ(decision.matching_policy_name, "policy2"); +} + +TEST(GrpcAuthorizationEngineTest, DenyEngineWithNoMatchingPolicy) { + Rbac::Policy policy1( + Rbac::Permission(Rbac::Permission::RuleType::kAny, /*not_rule=*/true), + Rbac::Principal(Rbac::Principal::RuleType::kAny, /*not_rule=*/true)); + std::map policies; + policies["policy1"] = std::move(policy1); + Rbac rbac(Rbac::Action::kDeny, std::move(policies)); + GrpcAuthorizationEngine engine(std::move(rbac)); + AuthorizationEngine::Decision decision = + engine.Evaluate(EvaluateArgs(nullptr, nullptr)); + EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow); + EXPECT_TRUE(decision.matching_policy_name.empty()); +} + +TEST(GrpcAuthorizationEngineTest, DenyEngineWithEmptyPolicies) { + GrpcAuthorizationEngine engine(Rbac::Action::kDeny); + AuthorizationEngine::Decision decision = + engine.Evaluate(EvaluateArgs(nullptr, nullptr)); + EXPECT_EQ(decision.type, AuthorizationEngine::Decision::Type::kAllow); + EXPECT_TRUE(decision.matching_policy_name.empty()); +} + +} // namespace grpc_core + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/core/security/grpc_tls_certificate_distributor_test.cc b/test/core/security/grpc_tls_certificate_distributor_test.cc index b0a04451c04..92123a182c1 100644 --- a/test/core/security/grpc_tls_certificate_distributor_test.cc +++ b/test/core/security/grpc_tls_certificate_distributor_test.cc @@ -129,8 +129,8 @@ class GrpcTlsCertificateDistributorTest : public ::testing::Test { std::move(updated_identity)); } - void OnError(grpc_error* root_cert_error, - grpc_error* identity_cert_error) override { + void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) override { GPR_ASSERT(root_cert_error != GRPC_ERROR_NONE || identity_cert_error != GRPC_ERROR_NONE); std::string root_error_str; diff --git a/test/core/security/grpc_tls_certificate_provider_test.cc b/test/core/security/grpc_tls_certificate_provider_test.cc index 50553577d9e..9d67556955a 100644 --- a/test/core/security/grpc_tls_certificate_provider_test.cc +++ b/test/core/security/grpc_tls_certificate_provider_test.cc @@ -131,8 +131,8 @@ class GrpcTlsCertificateProviderTest : public ::testing::Test { std::move(updated_identity)); } - void OnError(grpc_error* root_cert_error, - grpc_error* identity_cert_error) override { + void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) override { MutexLock lock(&state_->mu); GPR_ASSERT(root_cert_error != GRPC_ERROR_NONE || identity_cert_error != GRPC_ERROR_NONE); diff --git a/test/core/security/json_token_test.cc b/test/core/security/json_token_test.cc index 6b032bb7430..1ded259b7f4 100644 --- a/test/core/security/json_token_test.cc +++ b/test/core/security/json_token_test.cc @@ -215,11 +215,12 @@ static Json parse_json_part_from_jwt(const char* str, size_t len) { grpc_slice slice = grpc_base64_decode(b64, 1); gpr_free(b64); GPR_ASSERT(!GRPC_SLICE_IS_EMPTY(slice)); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; absl::string_view string = grpc_core::StringViewFromSlice(slice); Json json = Json::Parse(string, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parse error: %s", + grpc_error_std_string(error).c_str()); GRPC_ERROR_UNREF(error); } grpc_slice_unref(slice); diff --git a/test/core/security/jwt_verifier_test.cc b/test/core/security/jwt_verifier_test.cc index 71178cb657d..21ed63fcfd1 100644 --- a/test/core/security/jwt_verifier_test.cc +++ b/test/core/security/jwt_verifier_test.cc @@ -207,10 +207,11 @@ static void test_jwt_issuer_email_domain(void) { static void test_claims_success(void) { grpc_jwt_claims* claims; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(claims_without_time_constraint, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parse error: %s", + grpc_error_std_string(error).c_str()); } GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(json.type() == Json::Type::OBJECT); @@ -229,10 +230,11 @@ static void test_claims_success(void) { static void test_expired_claims_failure(void) { grpc_jwt_claims* claims; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(expired_claims, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parse error: %s", + grpc_error_std_string(error).c_str()); } GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(json.type() == Json::Type::OBJECT); @@ -257,10 +259,11 @@ static void test_expired_claims_failure(void) { } static void test_invalid_claims_failure(void) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(invalid_claims, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parse error: %s", + grpc_error_std_string(error).c_str()); } GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(json.type() == Json::Type::OBJECT); @@ -270,10 +273,11 @@ static void test_invalid_claims_failure(void) { static void test_bad_audience_claims_failure(void) { grpc_jwt_claims* claims; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(claims_without_time_constraint, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parse error: %s", + grpc_error_std_string(error).c_str()); } GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(json.type() == Json::Type::OBJECT); @@ -287,10 +291,11 @@ static void test_bad_audience_claims_failure(void) { static void test_bad_subject_claims_failure(void) { grpc_jwt_claims* claims; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(claims_with_bad_subject, &error); if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "JSON parse error: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "JSON parse error: %s", + grpc_error_std_string(error).c_str()); } GPR_ASSERT(error == GRPC_ERROR_NONE); GPR_ASSERT(json.type() == Json::Type::OBJECT); diff --git a/test/core/security/matchers_test.cc b/test/core/security/matchers_test.cc index 4084623b8fe..0bacd167e97 100644 --- a/test/core/security/matchers_test.cc +++ b/test/core/security/matchers_test.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "src/core/lib/security/authorization/matchers.h" +#include "src/core/lib/matchers/matchers.h" #include @@ -20,7 +20,7 @@ namespace grpc_core { TEST(StringMatcherTest, ExactMatchCaseSensitive) { auto string_matcher = - StringMatcher::Create(StringMatcher::Type::EXACT, + StringMatcher::Create(StringMatcher::Type::kExact, /*matcher=*/"exact", /*case_sensitive=*/true); ASSERT_TRUE(string_matcher.ok()); EXPECT_TRUE(string_matcher->Match("exact")); @@ -30,7 +30,7 @@ TEST(StringMatcherTest, ExactMatchCaseSensitive) { TEST(StringMatcherTest, ExactMatchCaseInsensitive) { auto string_matcher = - StringMatcher::Create(StringMatcher::Type::EXACT, + StringMatcher::Create(StringMatcher::Type::kExact, /*matcher=*/"exact", /*case_sensitive=*/false); ASSERT_TRUE(string_matcher.ok()); EXPECT_TRUE(string_matcher->Match("Exact")); @@ -38,7 +38,7 @@ TEST(StringMatcherTest, ExactMatchCaseInsensitive) { } TEST(StringMatcherTest, PrefixMatchCaseSensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::PREFIX, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kPrefix, /*matcher=*/"prefix", /*case_sensitive=*/true); ASSERT_TRUE(string_matcher.ok()); @@ -49,7 +49,7 @@ TEST(StringMatcherTest, PrefixMatchCaseSensitive) { } TEST(StringMatcherTest, PrefixMatchCaseInsensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::PREFIX, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kPrefix, /*matcher=*/"prefix", /*case_sensitive=*/false); ASSERT_TRUE(string_matcher.ok()); @@ -59,7 +59,7 @@ TEST(StringMatcherTest, PrefixMatchCaseInsensitive) { } TEST(StringMatcherTest, SuffixMatchCaseSensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::SUFFIX, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kSuffix, /*matcher=*/"suffix", /*case_sensitive=*/true); ASSERT_TRUE(string_matcher.ok()); @@ -70,7 +70,7 @@ TEST(StringMatcherTest, SuffixMatchCaseSensitive) { } TEST(StringMatcherTest, SuffixMatchCaseInSensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::SUFFIX, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kSuffix, /*matcher=*/"suffix", /*case_sensitive=*/false); ASSERT_TRUE(string_matcher.ok()); @@ -80,7 +80,7 @@ TEST(StringMatcherTest, SuffixMatchCaseInSensitive) { } TEST(StringMatcherTest, InvalidRegex) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::SAFE_REGEX, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kSafeRegex, /*matcher=*/"a[b-a]", /*case_sensitive=*/true); EXPECT_FALSE(string_matcher.ok()); @@ -90,7 +90,7 @@ TEST(StringMatcherTest, InvalidRegex) { } TEST(StringMatcherTest, SafeRegexMatchCaseSensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::SAFE_REGEX, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kSafeRegex, /*matcher=*/"regex.*", /*case_sensitive=*/true); ASSERT_TRUE(string_matcher.ok()); @@ -101,7 +101,7 @@ TEST(StringMatcherTest, SafeRegexMatchCaseSensitive) { } TEST(StringMatcherTest, SafeRegexMatchCaseInSensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::SAFE_REGEX, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kSafeRegex, /*matcher=*/"regex.*", /*case_sensitive=*/false); ASSERT_TRUE(string_matcher.ok()); @@ -112,7 +112,7 @@ TEST(StringMatcherTest, SafeRegexMatchCaseInSensitive) { } TEST(StringMatcherTest, ContainsMatchCaseSensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::CONTAINS, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kContains, /*matcher=*/"contains", /*case_sensitive=*/true); ASSERT_TRUE(string_matcher.ok()); @@ -123,7 +123,7 @@ TEST(StringMatcherTest, ContainsMatchCaseSensitive) { } TEST(StringMatcherTest, ContainsMatchCaseInSensitive) { - auto string_matcher = StringMatcher::Create(StringMatcher::Type::CONTAINS, + auto string_matcher = StringMatcher::Create(StringMatcher::Type::kContains, /*matcher=*/"contains", /*case_sensitive=*/false); ASSERT_TRUE(string_matcher.ok()); @@ -134,7 +134,7 @@ TEST(StringMatcherTest, ContainsMatchCaseInSensitive) { TEST(HeaderMatcherTest, StringMatcher) { auto header_matcher = - HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::EXACT, + HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::kExact, /*matcher=*/"exact"); ASSERT_TRUE(header_matcher.ok()); EXPECT_TRUE(header_matcher->Match("exact")); @@ -144,7 +144,7 @@ TEST(HeaderMatcherTest, StringMatcher) { TEST(HeaderMatcherTest, StringMatcherWithInvertMatch) { auto header_matcher = - HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::EXACT, + HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::kExact, /*matcher=*/"exact", /*range_start=*/0, /*range_end=*/0, /*present_match=*/false, /*invert_match=*/true); @@ -156,7 +156,7 @@ TEST(HeaderMatcherTest, StringMatcherWithInvertMatch) { TEST(HeaderMatcherTest, InvalidRegex) { auto header_matcher = - HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::SAFE_REGEX, + HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::kSafeRegex, /*matcher=*/"a[b-a]", /*range_start=*/0, /*range_end=*/0, /*present_match=*/false, /*invert_match=*/true); @@ -168,7 +168,7 @@ TEST(HeaderMatcherTest, InvalidRegex) { TEST(HeaderMatcherTest, RangeMatcherValidRange) { auto header_matcher = - HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::RANGE, + HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::kRange, /*matcher=*/"", /*range_start=*/10, /*range_end*/ 20); ASSERT_TRUE(header_matcher.ok()); @@ -180,7 +180,7 @@ TEST(HeaderMatcherTest, RangeMatcherValidRange) { TEST(HeaderMatcherTest, RangeMatcherInvalidRange) { auto header_matcher = - HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::RANGE, + HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::kRange, /*matcher=*/"", /*range_start=*/20, /*range_end*/ 10); EXPECT_FALSE(header_matcher.ok()); @@ -192,7 +192,7 @@ TEST(HeaderMatcherTest, RangeMatcherInvalidRange) { TEST(HeaderMatcherTest, PresentMatcherTrue) { auto header_matcher = - HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::PRESENT, + HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::kPresent, /*matcher=*/"", /*range_start=*/0, /*range_end=*/0, /*present_match=*/true); ASSERT_TRUE(header_matcher.ok()); @@ -202,7 +202,7 @@ TEST(HeaderMatcherTest, PresentMatcherTrue) { TEST(HeaderMatcherTest, PresentMatcherFalse) { auto header_matcher = - HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::PRESENT, + HeaderMatcher::Create(/*name=*/"key", HeaderMatcher::Type::kPresent, /*matcher=*/"", /*range_start=*/0, /*range_end=*/0, /*present_match=*/false); ASSERT_TRUE(header_matcher.ok()); diff --git a/test/core/security/oauth2_utils.cc b/test/core/security/oauth2_utils.cc index 0885a1ac876..536696b4c5a 100644 --- a/test/core/security/oauth2_utils.cc +++ b/test/core/security/oauth2_utils.cc @@ -40,12 +40,13 @@ typedef struct { grpc_closure closure; } oauth2_request; -static void on_oauth2_response(void* arg, grpc_error* error) { +static void on_oauth2_response(void* arg, grpc_error_handle error) { oauth2_request* request = static_cast(arg); char* token = nullptr; grpc_slice token_slice; if (error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, "Fetching token failed: %s", grpc_error_string(error)); + gpr_log(GPR_ERROR, "Fetching token failed: %s", + grpc_error_std_string(error).c_str()); } else { GPR_ASSERT(request->md_array.size == 1); token_slice = GRPC_MDVALUE(request->md_array.md[0]); @@ -64,7 +65,7 @@ static void on_oauth2_response(void* arg, grpc_error* error) { gpr_mu_unlock(request->mu); } -static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} +static void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} char* grpc_test_fetch_oauth2_token_with_credentials( grpc_call_credentials* creds) { @@ -86,7 +87,7 @@ char* grpc_test_fetch_oauth2_token_with_credentials( GRPC_CLOSURE_INIT(&request.closure, on_oauth2_response, &request, grpc_schedule_on_exec_ctx); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; if (creds->get_request_metadata(&request.pops, null_ctx, &request.md_array, &request.closure, &error)) { // Synchronous result; invoke callback directly. diff --git a/test/core/security/print_google_default_creds_token.cc b/test/core/security/print_google_default_creds_token.cc index 398c58c6e17..0d6c7b79a36 100644 --- a/test/core/security/print_google_default_creds_token.cc +++ b/test/core/security/print_google_default_creds_token.cc @@ -41,10 +41,11 @@ typedef struct { grpc_closure on_request_metadata; } synchronizer; -static void on_metadata_response(void* arg, grpc_error* error) { +static void on_metadata_response(void* arg, grpc_error_handle error) { synchronizer* sync = static_cast(arg); if (error != GRPC_ERROR_NONE) { - fprintf(stderr, "Fetching token failed: %s\n", grpc_error_string(error)); + fprintf(stderr, "Fetching token failed: %s\n", + grpc_error_std_string(error).c_str()); fflush(stderr); } else { char* token; @@ -70,7 +71,7 @@ int main(int argc, char** argv) { grpc_auth_metadata_context context; gpr_cmdline* cl = gpr_cmdline_create("print_google_default_creds_token"); grpc_pollset* pollset = nullptr; - grpc_error* error = nullptr; + grpc_error_handle error = GRPC_ERROR_NONE; gpr_cmdline_add_string(cl, "service_url", "Service URL for the token request.", &service_url); gpr_cmdline_parse(cl, argc, argv); diff --git a/test/core/security/rbac_translator_test.cc b/test/core/security/rbac_translator_test.cc new file mode 100644 index 00000000000..337f47150b3 --- /dev/null +++ b/test/core/security/rbac_translator_test.cc @@ -0,0 +1,809 @@ +// Copyright 2021 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/authorization/rbac_translator.h" + +#include +#include + +namespace grpc_core { + +namespace { + +MATCHER_P2(EqualsPrincipalName, expected_matcher_type, expected_matcher_value, + "") { + return arg->type == Rbac::Principal::RuleType::kPrincipalName && + arg->string_matcher.type() == expected_matcher_type && + arg->string_matcher.string_matcher() == expected_matcher_value; +} + +MATCHER_P2(EqualsPath, expected_matcher_type, expected_matcher_value, "") { + return arg->type == Rbac::Permission::RuleType::kPath && + arg->string_matcher.type() == expected_matcher_type && + arg->string_matcher.string_matcher() == expected_matcher_value; +} + +MATCHER_P3(EqualsHeader, expected_name, expected_matcher_type, + expected_matcher_value, "") { + return arg->type == Rbac::Permission::RuleType::kHeader && + arg->header_matcher.name() == expected_name && + arg->header_matcher.type() == expected_matcher_type && + arg->header_matcher.string_matcher() == expected_matcher_value; +} + +} // namespace + +TEST(GenerateRbacPoliciesTest, InvalidPolicy) { + const char* authz_policy = + "{" + " \"name\": \"authz-policy\",," + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + std::string(rbac_policies.status().message()), + ::testing::StartsWith("Failed to parse SDK authorization policy.")); +} + +TEST(GenerateRbacPoliciesTest, MissingAuthorizationPolicyName) { + const char* authz_policy = "{}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), "\"name\" field is not present."); +} + +TEST(GenerateRbacPoliciesTest, IncorrectAuthorizationPolicyNameType) { + const char* authz_policy = + "{" + " \"name\": [\"authz_policy\"]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), "\"name\" is not a string."); +} + +TEST(GenerateRbacPoliciesTest, MissingAllowRules) { + const char* authz_policy = + "{" + " \"name\": \"authz_policy\"" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "\"allow_rules\" is not present."); +} + +TEST(GenerateRbacPoliciesTest, MissingDenyRules) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + ASSERT_TRUE(rbac_policies.ok()); + EXPECT_EQ(rbac_policies.value().deny_policy.action, Rbac::Action::kDeny); + EXPECT_TRUE(rbac_policies.value().deny_policy.policies.empty()); +} + +TEST(GenerateRbacPoliciesTest, IncorrectAllowRulesType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": {}" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "\"allow_rules\" is not an array."); +} + +TEST(GenerateRbacPoliciesTest, IncorrectDenyRulesType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"deny_rules\": 123" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "\"deny_rules\" is not an array."); +} + +TEST(GenerateRbacPoliciesTest, IncorrectRuleType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [\"rule-a\"]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: is not an object."); +} + +TEST(GenerateRbacPoliciesTest, MissingRuleNameField) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [{}]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: \"name\" is not present."); +} + +TEST(GenerateRbacPoliciesTest, IncorrectRuleNameType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": 123" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: \"name\" is not a string."); +} + +TEST(GenerateRbacPoliciesTest, MissingSourceAndRequest) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + ASSERT_TRUE(rbac_policies.ok()); + EXPECT_EQ(rbac_policies.value().allow_policy.action, Rbac::Action::kAllow); + EXPECT_THAT( + rbac_policies.value().allow_policy.policies, + ::testing::ElementsAre(::testing::Pair( + "authz_allow_policy", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::principals, + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAny)))))); +} + +TEST(GenerateRbacPoliciesTest, EmptySourceAndRequest) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"source\": {}," + " \"request\": {}" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + ASSERT_TRUE(rbac_policies.ok()); + EXPECT_EQ(rbac_policies.value().allow_policy.action, Rbac::Action::kAllow); + EXPECT_THAT( + rbac_policies.value().allow_policy.policies, + ::testing::ElementsAre(::testing::Pair( + "authz_allow_policy", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::principals, + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAny)))))); +} + +TEST(GenerateRbacPoliciesTest, IncorrectSourceType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"source\": 111" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: \"source\" is not an object."); +} + +TEST(GenerateRbacPoliciesTest, IncorrectPrincipalsType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"source\": {" + " \"principals\": [" + " \"*\"," + " 123" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: \"principals\" 1: is not a string."); +} + +TEST(GenerateRbacPoliciesTest, ParseSourceSuccess) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"source\": {" + " \"principals\": [" + " \"spiffe://foo.abc\"," + " \"spiffe://bar*\"," + " \"*baz\"," + " \"spiffe://abc.*.com\"" + " ]" + " }" + " }" + " ]," + " \"deny_rules\": [" + " {" + " \"name\": \"deny_policy\"," + " \"source\": {" + " \"principals\": [" + " \"*\"" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + ASSERT_TRUE(rbac_policies.ok()); + EXPECT_EQ(rbac_policies.value().allow_policy.action, Rbac::Action::kAllow); + EXPECT_THAT( + rbac_policies.value().allow_policy.policies, + ::testing::ElementsAre(::testing::Pair( + "authz_allow_policy", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::principals, + ::testing::AllOf( + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAnd), + ::testing::Field( + &Rbac::Principal::principals, + ::testing::ElementsAre(::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Principal::type, + Rbac::Principal::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Principal::principals, + ::testing::ElementsAre( + EqualsPrincipalName( + StringMatcher::Type::kExact, + "spiffe://foo.abc"), + EqualsPrincipalName( + StringMatcher::Type::kPrefix, + "spiffe://bar"), + EqualsPrincipalName( + StringMatcher::Type::kSuffix, "baz"), + EqualsPrincipalName( + StringMatcher::Type::kExact, + "spiffe://abc.*.com"))))))))))))); + EXPECT_EQ(rbac_policies.value().deny_policy.action, Rbac::Action::kDeny); + EXPECT_THAT( + rbac_policies.value().deny_policy.policies, + ::testing::ElementsAre(::testing::Pair( + "authz_deny_policy", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::principals, + ::testing::AllOf( + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAnd), + ::testing::Field( + &Rbac::Principal::principals, + ::testing::ElementsAre(::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Principal::type, + Rbac::Principal::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Principal::principals, + ::testing::ElementsAre(EqualsPrincipalName( + StringMatcher::Type::kPrefix, + ""))))))))))))); +} + +TEST(GenerateRbacPoliciesTest, IncorrectRequestType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"deny_rules\": [" + " {" + " \"name\": \"deny_policy\"," + " \"request\": 111" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "deny_rules 0: \"request\" is not an object."); +} + +TEST(GenerateRbacPoliciesTest, IncorrectPathType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"deny_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"request\": {" + " \"paths\": [" + " \"path-a\"," + " 123" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "deny_rules 0: \"paths\" 1: is not a string."); +} + +TEST(GenerateRbacPoliciesTest, ParseRequestPathsSuccess) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"request\": {" + " \"paths\": [" + " \"*\"" + " ]" + " }" + " }" + " ]," + " \"deny_rules\": [" + " {" + " \"name\": \"deny_policy\"," + " \"request\": {" + " \"paths\": [" + " \"path-foo\"," + " \"path-bar*\"," + " \"*baz\"" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + ASSERT_TRUE(rbac_policies.ok()); + EXPECT_EQ(rbac_policies.value().deny_policy.action, Rbac::Action::kDeny); + EXPECT_THAT( + rbac_policies.value().deny_policy.policies, + ::testing::ElementsAre(::testing::Pair( + "authz_deny_policy", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::principals, + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::AllOf( + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAnd), + ::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre(::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Permission::type, + Rbac::Permission::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre( + EqualsPath(StringMatcher::Type::kExact, + "path-foo"), + EqualsPath(StringMatcher::Type::kPrefix, + "path-bar"), + EqualsPath(StringMatcher::Type::kSuffix, + "baz"))))))))))))); + EXPECT_EQ(rbac_policies.value().allow_policy.action, Rbac::Action::kAllow); + EXPECT_THAT( + rbac_policies.value().allow_policy.policies, + ::testing::ElementsAre(::testing::Pair( + "authz_allow_policy", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::principals, + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::AllOf( + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAnd), + ::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre(::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Permission::type, + Rbac::Permission::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre( + EqualsPath(StringMatcher::Type::kPrefix, + ""))))))))))))); +} + +TEST(GenerateRbacPoliciesTest, IncorrectHeaderType) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"deny_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"request\": {" + " \"headers\": [" + " \"header-a\"" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "deny_rules 0: \"headers\" 0: is not an object."); +} + +TEST(GenerateRbacPoliciesTest, UnsupportedGrpcHeaders) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"deny_rules\": [" + " {" + " \"name\": \"policy\"," + " \"request\": {" + " \"headers\": [" + " {" + " \"key\": \"grpc-xxx\"," + " \"values\": [" + " \"*\"" + " ]" + " }" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "deny_rules 0: \"headers\" 0: Unsupported \"key\" grpc-xxx."); +} + +TEST(GenerateRbacPoliciesTest, UnsupportedPseudoHeaders) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"policy\"," + " \"request\": {" + " \"headers\": [" + " {" + " \"key\": \":method\"," + " \"values\": [" + " \"*\"" + " ]" + " }" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: \"headers\" 0: Unsupported \"key\" :method."); +} + +TEST(GenerateRbacPoliciesTest, UnsupportedhostHeader) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"deny_rules\": [" + " {" + " \"name\": \"policy\"," + " \"request\": {" + " \"headers\": [" + " {" + " \"key\": \"host\"," + " \"values\": [" + " \"*\"" + " ]" + " }" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "deny_rules 0: \"headers\" 0: Unsupported \"key\" host."); +} + +TEST(GenerateRbacPoliciesTest, UnsupportedHostHeader) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"policy\"," + " \"request\": {" + " \"headers\": [" + " {" + " \"key\": \"Host\"," + " \"values\": [" + " \"*\"" + " ]" + " }" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: \"headers\" 0: Unsupported \"key\" Host."); +} + +TEST(GenerateRbacPoliciesTest, EmptyHeaderValuesList) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy_1\"," + " \"request\": {" + " \"headers\": [" + " {" + " \"key\": \"key-a\"," + " \"values\": [" + " ]" + " }" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + EXPECT_EQ(rbac_policies.status().code(), absl::StatusCode::kInvalidArgument); + EXPECT_EQ(rbac_policies.status().message(), + "allow_rules 0: \"headers\" 0: \"values\" list is empty."); +} + +TEST(GenerateRbacPoliciesTest, ParseRequestHeadersSuccess) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy\"," + " \"request\": {" + " \"headers\": [" + " {" + " \"key\": \"key-1\"," + " \"values\": [" + " \"*\"" + " ]" + " }," + " {" + " \"key\": \"key-2\"," + " \"values\": [" + " \"foo\"," + " \"bar*\"," + " \"*baz\"" + " ]" + " }" + " ]" + " }" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + ASSERT_TRUE(rbac_policies.ok()); + EXPECT_EQ(rbac_policies.value().deny_policy.action, Rbac::Action::kDeny); + EXPECT_TRUE(rbac_policies.value().deny_policy.policies.empty()); + EXPECT_EQ(rbac_policies.value().allow_policy.action, Rbac::Action::kAllow); + EXPECT_THAT( + rbac_policies.value().allow_policy.policies, + ::testing::ElementsAre(::testing::Pair( + "authz_allow_policy", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::principals, + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::AllOf( + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAnd), + ::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre(::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Permission::type, + Rbac::Permission::RuleType::kAnd)), + ::testing::Pointee(::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre( + ::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Permission::type, + Rbac::Permission::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre( + EqualsHeader( + "key-1", + HeaderMatcher::Type:: + kPrefix, + ""))))), + ::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Permission::type, + Rbac::Permission::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre( + EqualsHeader("key-2", + HeaderMatcher:: + Type::kExact, + "foo"), + EqualsHeader( + "key-2", + HeaderMatcher::Type:: + kPrefix, + "bar"), + EqualsHeader( + "key-2", + HeaderMatcher::Type:: + kSuffix, + "baz"))))))))))))))))); +} + +TEST(GenerateRbacPoliciesTest, ParseRulesArraySuccess) { + const char* authz_policy = + "{" + " \"name\": \"authz\"," + " \"allow_rules\": [" + " {" + " \"name\": \"allow_policy_1\"," + " \"source\": {" + " \"principals\": [" + " \"spiffe://foo.abc\"" + " ]" + " }," + " \"request\": {" + " \"paths\": [" + " \"foo\"" + " ]" + " }" + " }," + " {" + " \"name\": \"allow_policy_2\"" + " }" + " ]" + "}"; + auto rbac_policies = GenerateRbacPolicies(authz_policy); + ASSERT_TRUE(rbac_policies.ok()); + EXPECT_EQ(rbac_policies.value().deny_policy.action, Rbac::Action::kDeny); + EXPECT_TRUE(rbac_policies.value().deny_policy.policies.empty()); + EXPECT_EQ(rbac_policies.value().allow_policy.action, Rbac::Action::kAllow); + EXPECT_THAT( + rbac_policies.value().allow_policy.policies, + ::testing::ElementsAre( + ::testing::Pair( + "authz_allow_policy_1", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::AllOf( + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAnd), + ::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre(::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Permission::type, + Rbac::Permission::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Permission::permissions, + ::testing::ElementsAre(EqualsPath( + StringMatcher::Type::kExact, + "foo"))))))))), + ::testing::Field( + &Rbac::Policy::principals, + ::testing::AllOf( + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAnd), + ::testing::Field( + &Rbac::Principal::principals, + ::testing::ElementsAre(::testing::AllOf( + ::testing::Pointee(::testing::Field( + &Rbac::Principal::type, + Rbac::Principal::RuleType::kOr)), + ::testing::Pointee(::testing::Field( + &Rbac::Principal::principals, + ::testing::ElementsAre( + EqualsPrincipalName( + StringMatcher::Type::kExact, + "spiffe://foo.abc"))))))))))), + ::testing::Pair( + "authz_allow_policy_2", + ::testing::AllOf( + ::testing::Field( + &Rbac::Policy::permissions, + ::testing::Field(&Rbac::Permission::type, + Rbac::Permission::RuleType::kAny)), + ::testing::Field( + &Rbac::Policy::principals, + ::testing::Field(&Rbac::Principal::type, + Rbac::Principal::RuleType::kAny)))))); +} + +} // namespace grpc_core + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/core/security/secure_endpoint_test.cc b/test/core/security/secure_endpoint_test.cc index 50c3694d772..c5621d92420 100644 --- a/test/core/security/secure_endpoint_test.cc +++ b/test/core/security/secure_endpoint_test.cc @@ -166,7 +166,7 @@ static grpc_endpoint_test_config configs[] = { clean_up}, }; -static void inc_call_ctr(void* arg, grpc_error* /*error*/) { +static void inc_call_ctr(void* arg, grpc_error_handle /*error*/) { ++*static_cast(arg); } @@ -202,7 +202,7 @@ static void test_leftover(grpc_endpoint_test_config config, size_t slice_size) { clean_up(); } -static void destroy_pollset(void* p, grpc_error* /*error*/) { +static void destroy_pollset(void* p, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(p)); } diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc index 2049832bcc7..da7f2f0c5cc 100644 --- a/test/core/security/security_connector_test.cc +++ b/test/core/security/security_connector_test.cc @@ -222,6 +222,32 @@ static int check_x509_pem_cert_chain(const grpc_auth_context* ctx, return 1; } +static int check_sans( + const grpc_auth_context* ctx, const char* expected_property_name, + const std::vector& expected_property_values) { + grpc_auth_property_iterator it = + grpc_auth_context_find_properties_by_name(ctx, expected_property_name); + for (const auto& property_value : expected_property_values) { + const grpc_auth_property* prop = grpc_auth_property_iterator_next(&it); + if (prop == nullptr) { + gpr_log(GPR_ERROR, "Expected value %s not found.", + property_value.c_str()); + return 0; + } + if (strncmp(prop->value, property_value.c_str(), prop->value_length) != 0) { + gpr_log(GPR_ERROR, "Expected peer %s and got %s.", property_value.c_str(), + prop->value); + return 0; + } + } + if (grpc_auth_property_iterator_next(&it) != nullptr) { + gpr_log(GPR_ERROR, "Expected only %zu property values.", + expected_property_values.size()); + return 0; + } + return 1; +} + static int check_spiffe_id(const grpc_auth_context* ctx, const char* expected_spiffe_id, bool expect_spiffe_id) { @@ -444,6 +470,59 @@ static void test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context( ctx.reset(DEBUG_LOCATION, "test"); } +static void test_dns_peer_to_auth_context(void) { + tsi_peer peer; + const std::vector expected_dns = {"dns1", "dns2", "dns3"}; + GPR_ASSERT(tsi_construct_peer(expected_dns.size(), &peer) == TSI_OK); + for (size_t i = 0; i < expected_dns.size(); ++i) { + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_DNS_PEER_PROPERTY, expected_dns[i].c_str(), + &peer.properties[i]) == TSI_OK); + } + grpc_core::RefCountedPtr ctx = + grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE); + GPR_ASSERT(ctx != nullptr); + GPR_ASSERT(check_sans(ctx.get(), GRPC_PEER_DNS_PROPERTY_NAME, expected_dns)); + tsi_peer_destruct(&peer); + ctx.reset(DEBUG_LOCATION, "test"); +} + +static void test_email_peer_to_auth_context(void) { + tsi_peer peer; + const std::vector expected_emails = {"email1", "email2"}; + GPR_ASSERT(tsi_construct_peer(expected_emails.size(), &peer) == TSI_OK); + for (size_t i = 0; i < expected_emails.size(); ++i) { + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_EMAIL_PEER_PROPERTY, expected_emails[i].c_str(), + &peer.properties[i]) == TSI_OK); + } + grpc_core::RefCountedPtr ctx = + grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE); + GPR_ASSERT(ctx != nullptr); + GPR_ASSERT( + check_sans(ctx.get(), GRPC_PEER_EMAIL_PROPERTY_NAME, expected_emails)); + tsi_peer_destruct(&peer); + ctx.reset(DEBUG_LOCATION, "test"); +} + +static void test_ip_peer_to_auth_context(void) { + tsi_peer peer; + const std::vector expected_ips = {"128.128.128.128", + "255.255.255.255"}; + GPR_ASSERT(tsi_construct_peer(expected_ips.size(), &peer) == TSI_OK); + for (size_t i = 0; i < expected_ips.size(); ++i) { + GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( + TSI_X509_IP_PEER_PROPERTY, expected_ips[i].c_str(), + &peer.properties[i]) == TSI_OK); + } + grpc_core::RefCountedPtr ctx = + grpc_ssl_peer_to_auth_context(&peer, GRPC_SSL_TRANSPORT_SECURITY_TYPE); + GPR_ASSERT(ctx != nullptr); + GPR_ASSERT(check_sans(ctx.get(), GRPC_PEER_IP_PROPERTY_NAME, expected_ips)); + tsi_peer_destruct(&peer); + ctx.reset(DEBUG_LOCATION, "test"); +} + static void test_spiffe_id_peer_to_auth_context(void) { // Invalid SPIFFE IDs should not be plumbed. std::string long_id(2050, 'x'); @@ -558,6 +637,7 @@ static void test_ipv6_address_san(void) { } tsi_peer_destruct(&peer); } + namespace grpc_core { namespace { @@ -637,7 +717,7 @@ static void test_peer_alpn_check(void) { GPR_ASSERT(tsi_construct_string_peer_property("wrong peer property name", alpn, strlen(alpn), &peer.properties[0]) == TSI_OK); - grpc_error* error = grpc_ssl_check_alpn(&peer); + grpc_error_handle error = grpc_ssl_check_alpn(&peer); GPR_ASSERT(error != GRPC_ERROR_NONE); tsi_peer_destruct(&peer); GRPC_ERROR_UNREF(error); @@ -672,6 +752,9 @@ int main(int argc, char** argv) { test_cn_and_one_san_ssl_peer_to_auth_context(); test_cn_and_multiple_sans_ssl_peer_to_auth_context(); test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context(); + test_dns_peer_to_auth_context(); + test_email_peer_to_auth_context(); + test_ip_peer_to_auth_context(); test_spiffe_id_peer_to_auth_context(); test_ipv6_address_san(); test_default_ssl_roots(); diff --git a/test/core/security/ssl_server_fuzzer.cc b/test/core/security/ssl_server_fuzzer.cc index cdd00e0633a..6401f8e2f6a 100644 --- a/test/core/security/ssl_server_fuzzer.cc +++ b/test/core/security/ssl_server_fuzzer.cc @@ -42,7 +42,7 @@ struct handshake_state { bool done_callback_called; }; -static void on_handshake_done(void* arg, grpc_error* error) { +static void on_handshake_done(void* arg, grpc_error_handle error) { grpc_core::HandshakerArgs* args = static_cast(arg); struct handshake_state* state = diff --git a/test/core/security/tls_security_connector_test.cc b/test/core/security/tls_security_connector_test.cc index 5c94e89c1d2..c041fd9242c 100644 --- a/test/core/security/tls_security_connector_test.cc +++ b/test/core/security/tls_security_connector_test.cc @@ -352,7 +352,8 @@ TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameSuccess) { GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, target_name, &peer.properties[0]) == TSI_OK); - grpc_error* error = grpc_core::internal::TlsCheckHostName(target_name, &peer); + grpc_error_handle error = + grpc_core::internal::TlsCheckHostName(target_name, &peer); tsi_peer_destruct(&peer); EXPECT_EQ(error, GRPC_ERROR_NONE); GRPC_ERROR_UNREF(error); @@ -366,7 +367,8 @@ TEST_F(TlsSecurityConnectorTest, TlsCheckHostNameFail) { GPR_ASSERT(tsi_construct_string_peer_property_from_cstring( TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, another_name, &peer.properties[0]) == TSI_OK); - grpc_error* error = grpc_core::internal::TlsCheckHostName(target_name, &peer); + grpc_error_handle error = + grpc_core::internal::TlsCheckHostName(target_name, &peer); tsi_peer_destruct(&peer); EXPECT_NE(error, GRPC_ERROR_NONE); GRPC_ERROR_UNREF(error); diff --git a/test/core/security/xds_credentials_test.cc b/test/core/security/xds_credentials_test.cc index 3e27fbaa45f..c055972a01d 100644 --- a/test/core/security/xds_credentials_test.cc +++ b/test/core/security/xds_credentials_test.cc @@ -30,29 +30,29 @@ namespace testing { namespace { StringMatcher ExactMatcher(const char* string) { - return StringMatcher::Create(StringMatcher::Type::EXACT, string).value(); + return StringMatcher::Create(StringMatcher::Type::kExact, string).value(); } StringMatcher PrefixMatcher(const char* string, bool case_sensitive = true) { - return StringMatcher::Create(StringMatcher::Type::PREFIX, string, + return StringMatcher::Create(StringMatcher::Type::kPrefix, string, case_sensitive) .value(); } StringMatcher SuffixMatcher(const char* string, bool case_sensitive = true) { - return StringMatcher::Create(StringMatcher::Type::SUFFIX, string, + return StringMatcher::Create(StringMatcher::Type::kSuffix, string, case_sensitive) .value(); } StringMatcher ContainsMatcher(const char* string, bool case_sensitive = true) { - return StringMatcher::Create(StringMatcher::Type::CONTAINS, string, + return StringMatcher::Create(StringMatcher::Type::kContains, string, case_sensitive) .value(); } StringMatcher SafeRegexMatcher(const char* string) { - return StringMatcher::Create(StringMatcher::Type::SAFE_REGEX, string).value(); + return StringMatcher::Create(StringMatcher::Type::kSafeRegex, string).value(); } TEST(XdsSanMatchingTest, EmptySansList) { diff --git a/test/core/surface/concurrent_connectivity_test.cc b/test/core/surface/concurrent_connectivity_test.cc index f2edbc86a0b..5cf69311c0c 100644 --- a/test/core/surface/concurrent_connectivity_test.cc +++ b/test/core/surface/concurrent_connectivity_test.cc @@ -34,11 +34,11 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/tcp_server.h" #include "test/core/util/port.h" @@ -137,7 +137,7 @@ void bad_server_thread(void* vargs) { grpc_sockaddr* addr = reinterpret_cast(resolved_addr.addr); int port; grpc_tcp_server* s; - grpc_error* error = grpc_tcp_server_create(nullptr, nullptr, &s); + grpc_error_handle error = grpc_tcp_server_create(nullptr, nullptr, &s); GPR_ASSERT(error == GRPC_ERROR_NONE); memset(&resolved_addr, 0, sizeof(resolved_addr)); addr->sa_family = GRPC_AF_INET; @@ -150,7 +150,7 @@ void bad_server_thread(void* vargs) { gpr_event_set(&args->ready, reinterpret_cast(1)); gpr_mu_lock(args->mu); - while (args->stop.load(std::memory_order_acquire) == false) { + while (!args->stop.load(std::memory_order_acquire)) { grpc_millis deadline = grpc_core::ExecCtx::Get()->Now() + 100; grpc_pollset_worker* worker = nullptr; @@ -168,7 +168,7 @@ void bad_server_thread(void* vargs) { grpc_tcp_server_unref(s); } -static void done_pollset_shutdown(void* pollset, grpc_error* /*error*/) { +static void done_pollset_shutdown(void* pollset, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(pollset)); gpr_free(pollset); } diff --git a/test/core/surface/lame_client_test.cc b/test/core/surface/lame_client_test.cc index bac7ee008ee..bd443a769c9 100644 --- a/test/core/surface/lame_client_test.cc +++ b/test/core/surface/lame_client_test.cc @@ -40,7 +40,7 @@ static void* tag(intptr_t t) { return reinterpret_cast(t); } static grpc_closure transport_op_cb; -static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} +static void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} void test_transport_op(grpc_channel* channel) { grpc_core::ExecCtx exec_ctx; diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c index 22f89ba27a4..6651afb2069 100644 --- a/test/core/surface/public_headers_must_be_c89.c +++ b/test/core/surface/public_headers_must_be_c89.c @@ -144,6 +144,7 @@ int main(int argc, char **argv) { printf("%lx", (unsigned long) grpc_resource_quota_unref); printf("%lx", (unsigned long) grpc_resource_quota_resize); printf("%lx", (unsigned long) grpc_resource_quota_set_max_threads); + printf("%lx", (unsigned long) grpc_dump_xds_configs); printf("%lx", (unsigned long) grpc_resource_quota_arg_vtable); printf("%lx", (unsigned long) grpc_channelz_get_top_channels); printf("%lx", (unsigned long) grpc_channelz_get_servers); diff --git a/test/core/surface/server_test.cc b/test/core/surface/server_test.cc index 0e829c2cf84..2aa962a7027 100644 --- a/test/core/surface/server_test.cc +++ b/test/core/surface/server_test.cc @@ -132,7 +132,7 @@ void test_bind_server_to_addr(const char* host, bool secure) { static int external_dns_works(const char* host) { grpc_resolved_addresses* res = nullptr; - grpc_error* error = grpc_blocking_resolve_address(host, "80", &res); + grpc_error_handle error = grpc_blocking_resolve_address(host, "80", &res); GRPC_ERROR_UNREF(error); if (res != nullptr) { grpc_resolved_addresses_destroy(res); diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD index 1bec5af5dbf..3eeb4f9f73b 100644 --- a/test/core/transport/BUILD +++ b/test/core/transport/BUILD @@ -63,6 +63,20 @@ grpc_cc_test( ], ) +grpc_cc_test( + name = "error_utils_test", + srcs = ["error_utils_test.cc"], + external_deps = [ + "gtest", + ], + language = "C++", + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "metadata_test", srcs = ["metadata_test.cc"], diff --git a/test/core/transport/byte_stream_test.cc b/test/core/transport/byte_stream_test.cc index 16294079832..32ee73f39b7 100644 --- a/test/core/transport/byte_stream_test.cc +++ b/test/core/transport/byte_stream_test.cc @@ -37,7 +37,7 @@ namespace { // SliceBufferByteStream tests // -void NotCalledClosure(void* /*arg*/, grpc_error* /*error*/) { +void NotCalledClosure(void* /*arg*/, grpc_error_handle /*error*/) { GPR_ASSERT(false); } @@ -64,7 +64,7 @@ TEST(SliceBufferByteStream, Basic) { for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { ASSERT_TRUE(stream.Next(~(size_t)0, &closure)); grpc_slice output; - grpc_error* error = stream.Pull(&output); + grpc_error_handle error = stream.Pull(&output); EXPECT_TRUE(error == GRPC_ERROR_NONE); EXPECT_TRUE(grpc_slice_eq(input[i], output)); grpc_slice_unref_internal(output); @@ -95,12 +95,12 @@ TEST(SliceBufferByteStream, Shutdown) { // Read the first slice. ASSERT_TRUE(stream.Next(~(size_t)0, &closure)); grpc_slice output; - grpc_error* error = stream.Pull(&output); + grpc_error_handle error = stream.Pull(&output); EXPECT_TRUE(error == GRPC_ERROR_NONE); EXPECT_TRUE(grpc_slice_eq(input[0], output)); grpc_slice_unref_internal(output); // Now shutdown. - grpc_error* shutdown_error = + grpc_error_handle shutdown_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("shutdown error"); stream.Shutdown(GRPC_ERROR_REF(shutdown_error)); // After shutdown, the next pull() should return the error. @@ -142,7 +142,7 @@ TEST(CachingByteStream, Basic) { for (size_t i = 0; i < GPR_ARRAY_SIZE(input); ++i) { ASSERT_TRUE(stream.Next(~(size_t)0, &closure)); grpc_slice output; - grpc_error* error = stream.Pull(&output); + grpc_error_handle error = stream.Pull(&output); EXPECT_TRUE(error == GRPC_ERROR_NONE); EXPECT_TRUE(grpc_slice_eq(input[i], output)); grpc_slice_unref_internal(output); @@ -175,7 +175,7 @@ TEST(CachingByteStream, Reset) { // Read one slice. ASSERT_TRUE(stream.Next(~(size_t)0, &closure)); grpc_slice output; - grpc_error* error = stream.Pull(&output); + grpc_error_handle error = stream.Pull(&output); EXPECT_TRUE(error == GRPC_ERROR_NONE); EXPECT_TRUE(grpc_slice_eq(input[0], output)); grpc_slice_unref_internal(output); @@ -218,7 +218,7 @@ TEST(CachingByteStream, SharedCache) { // Read one slice from stream1. EXPECT_TRUE(stream1.Next(~(size_t)0, &closure)); grpc_slice output; - grpc_error* error = stream1.Pull(&output); + grpc_error_handle error = stream1.Pull(&output); EXPECT_TRUE(error == GRPC_ERROR_NONE); EXPECT_TRUE(grpc_slice_eq(input[0], output)); grpc_slice_unref_internal(output); diff --git a/test/core/transport/chttp2/context_list_test.cc b/test/core/transport/chttp2/context_list_test.cc index 9f0ffeb54e6..d88d66c7cca 100644 --- a/test/core/transport/chttp2/context_list_test.cc +++ b/test/core/transport/chttp2/context_list_test.cc @@ -39,7 +39,7 @@ const uint32_t kByteOffset = 123; void* PhonyArgsCopier(void* arg) { return arg; } void TestExecuteFlushesListVerifier(void* arg, grpc_core::Timestamps* ts, - grpc_error* error) { + grpc_error_handle error) { ASSERT_NE(arg, nullptr); EXPECT_EQ(error, GRPC_ERROR_NONE); if (ts) { diff --git a/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc b/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc index 22465db0db4..e86cdef98fe 100644 --- a/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc +++ b/test/core/transport/chttp2/hpack_parser_fuzzer_test.cc @@ -30,7 +30,7 @@ bool squelch = true; bool leak_check = true; -static grpc_error* onhdr(void* /*ud*/, grpc_mdelem md) { +static grpc_error_handle onhdr(void* /*ud*/, grpc_mdelem md) { GRPC_MDELEM_UNREF(md); return GRPC_ERROR_NONE; } diff --git a/test/core/transport/chttp2/hpack_parser_test.cc b/test/core/transport/chttp2/hpack_parser_test.cc index 4782d484d1b..bc488815306 100644 --- a/test/core/transport/chttp2/hpack_parser_test.cc +++ b/test/core/transport/chttp2/hpack_parser_test.cc @@ -34,7 +34,7 @@ typedef struct { va_list args; } test_checker; -static grpc_error* onhdr(void* ud, grpc_mdelem md) { +static grpc_error_handle onhdr(void* ud, grpc_mdelem md) { const char *ekey, *evalue; test_checker* chk = static_cast(ud); ekey = va_arg(chk->args, char*); diff --git a/test/core/transport/chttp2/settings_timeout_test.cc b/test/core/transport/chttp2/settings_timeout_test.cc index 81642315dec..b9790208578 100644 --- a/test/core/transport/chttp2/settings_timeout_test.cc +++ b/test/core/transport/chttp2/settings_timeout_test.cc @@ -104,9 +104,9 @@ class Client { void Connect() { grpc_core::ExecCtx exec_ctx; grpc_resolved_addresses* server_addresses = nullptr; - grpc_error* error = + grpc_error_handle error = grpc_blocking_resolve_address(server_address_, "80", &server_addresses); - ASSERT_EQ(GRPC_ERROR_NONE, error) << grpc_error_string(error); + ASSERT_EQ(GRPC_ERROR_NONE, error) << grpc_error_std_string(error); ASSERT_GE(server_addresses->naddrs, 1UL); pollset_ = static_cast(gpr_zalloc(grpc_pollset_size())); grpc_pollset_init(pollset_, &mu_); @@ -177,11 +177,12 @@ class Client { bool done() const { return gpr_atm_acq_load(&done_atm_) != 0; } // Caller does NOT take ownership of the error. - grpc_error* error() const { return error_; } + grpc_error_handle error() const { return error_; } private: - static void OnEventDone(void* arg, grpc_error* error) { - gpr_log(GPR_INFO, "OnEventDone(): %s", grpc_error_string(error)); + static void OnEventDone(void* arg, grpc_error_handle error) { + gpr_log(GPR_INFO, "OnEventDone(): %s", + grpc_error_std_string(error).c_str()); EventState* state = static_cast(arg); state->error_ = GRPC_ERROR_REF(error); gpr_atm_rel_store(&state->done_atm_, 1); @@ -189,7 +190,7 @@ class Client { grpc_closure closure_; gpr_atm done_atm_ = 0; - grpc_error* error_ = GRPC_ERROR_NONE; + grpc_error_handle error_ = GRPC_ERROR_NONE; }; // Returns true if done, or false if deadline exceeded. @@ -209,7 +210,7 @@ class Client { } } - static void PollsetDestroy(void* arg, grpc_error* /*error*/) { + static void PollsetDestroy(void* arg, grpc_error_handle /*error*/) { grpc_pollset* pollset = static_cast(arg); grpc_pollset_destroy(pollset); gpr_free(pollset); diff --git a/test/core/transport/chttp2/too_many_pings_test.cc b/test/core/transport/chttp2/too_many_pings_test.cc index abb3ae5768a..57e5fa87c78 100644 --- a/test/core/transport/chttp2/too_many_pings_test.cc +++ b/test/core/transport/chttp2/too_many_pings_test.cc @@ -40,11 +40,12 @@ #include #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" +#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/gprpp/thd.h" #include "src/core/lib/iomgr/error.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/security/credentials/alts/alts_credentials.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/security_connector/alts/alts_security_connector.h" @@ -59,6 +60,48 @@ namespace { +class TransportCounter { + public: + static void CounterInitCallback() { + absl::MutexLock lock(&mu()); + ++count_; + } + + static void CounterDestructCallback() { + absl::MutexLock lock(&mu()); + if (--count_ == 0) { + cv().SignalAll(); + } + } + + static void WaitForTransportsToBeDestroyed() { + absl::MutexLock lock(&mu()); + while (count_ != 0) { + ASSERT_FALSE(cv().WaitWithTimeout(&mu(), absl::Seconds(10))); + } + } + + static int count() { + absl::MutexLock lock(&mu()); + return count_; + } + + static absl::Mutex& mu() { + static absl::Mutex* mu = new absl::Mutex(); + return *mu; + } + + static absl::CondVar& cv() { + static absl::CondVar* cv = new absl::CondVar(); + return *cv; + } + + private: + static int count_; +}; + +int TransportCounter::count_ = 0; + void* tag(intptr_t t) { return reinterpret_cast(t); } // Perform a simple RPC where the server cancels the request with @@ -681,8 +724,8 @@ TEST(TooManyPings, BdpPingNotSentWithoutReceiveSideActivity) { grpc_channel* channel = grpc_insecure_channel_create( server_address.c_str(), &client_channel_args, nullptr); VerifyChannelReady(channel, cq); + EXPECT_EQ(TransportCounter::count(), 2 /* one each for server and client */); cq_verifier* cqv = cq_verifier_create(cq); - cq_verify_empty_timeout(cqv, 1); // Channel should be able to send two pings without disconnect if there was no // BDP sent. grpc_channel_ping(channel, cq, tag(1), nullptr); @@ -707,9 +750,67 @@ TEST(TooManyPings, BdpPingNotSentWithoutReceiveSideActivity) { grpc_channel_ping(channel, cq, tag(4), nullptr); CQ_EXPECT_COMPLETION(cqv, tag(4), 1); cq_verify(cqv, 5); - // Give some time for the server to disconnect if it hasn't already. - cq_verify_empty_timeout(cqv, 3); + // Make sure that the transports have been destroyed + VerifyChannelDisconnected(channel, cq); + TransportCounter::WaitForTransportsToBeDestroyed(); + cq_verifier_destroy(cqv); + // shutdown and destroy the client and server + ServerShutdownAndDestroy(server, cq); + grpc_channel_destroy(channel); + grpc_completion_queue_shutdown(cq); + while (grpc_completion_queue_next(cq, gpr_inf_future(GPR_CLOCK_REALTIME), + nullptr) + .type != GRPC_QUEUE_SHUTDOWN) { + } + grpc_completion_queue_destroy(cq); +} + +TEST(TooManyPings, TransportsGetCleanedUpOnDisconnect) { + grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); + // create the client and server + std::string server_address = + grpc_core::JoinHostPort("localhost", grpc_pick_unused_port_or_die()); + grpc_arg server_args[] = { + grpc_channel_arg_integer_create( + const_cast( + GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS), + 60 * 1000), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_MAX_PING_STRIKES), 1)}; + grpc_channel_args server_channel_args = {GPR_ARRAY_SIZE(server_args), + server_args}; + grpc_server* server = grpc_server_create(&server_channel_args, nullptr); + grpc_server_register_completion_queue(server, cq, nullptr); + GPR_ASSERT( + grpc_server_add_insecure_http2_port(server, server_address.c_str())); + grpc_server_start(server); + grpc_arg client_args[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 1)}; + grpc_channel_args client_channel_args = {GPR_ARRAY_SIZE(client_args), + client_args}; + grpc_channel* channel = grpc_insecure_channel_create( + server_address.c_str(), &client_channel_args, nullptr); + VerifyChannelReady(channel, cq); + EXPECT_EQ(TransportCounter::count(), 2 /* one each for server and client */); + cq_verifier* cqv = cq_verifier_create(cq); + // First ping + grpc_channel_ping(channel, cq, tag(1), nullptr); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv, 5); + // Second ping + grpc_channel_ping(channel, cq, tag(2), nullptr); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv, 5); + // Third ping caused disconnect + grpc_channel_ping(channel, cq, tag(2), nullptr); + CQ_EXPECT_COMPLETION(cqv, tag(2), 1); + cq_verify(cqv, 5); + // Make sure that the transports have been destroyed VerifyChannelDisconnected(channel, cq); + TransportCounter::WaitForTransportsToBeDestroyed(); cq_verifier_destroy(cqv); // shutdown and destroy the client and server ServerShutdownAndDestroy(server, cq); @@ -727,6 +828,10 @@ TEST(TooManyPings, BdpPingNotSentWithoutReceiveSideActivity) { int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); grpc::testing::TestEnvironment env(argc, argv); + grpc_core::TestOnlySetGlobalHttp2TransportInitCallback( + TransportCounter::CounterInitCallback); + grpc_core::TestOnlySetGlobalHttp2TransportDestructCallback( + TransportCounter::CounterDestructCallback); grpc_init(); auto result = RUN_ALL_TESTS(); grpc_shutdown(); diff --git a/test/core/transport/error_utils_test.cc b/test/core/transport/error_utils_test.cc new file mode 100644 index 00000000000..909a5b8a70a --- /dev/null +++ b/test/core/transport/error_utils_test.cc @@ -0,0 +1,95 @@ +// +// Copyright 2021 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/transport/error_utils.h" + +#include +#include "absl/status/status.h" + +#include "src/core/lib/slice/slice_internal.h" +#include "test/core/util/test_config.h" + +namespace { + +// ---- Ok Status ---- +TEST(ErrorUtilsTest, AbslOkToGrpcError) { + grpc_error_handle error = absl_status_to_grpc_error(absl::OkStatus()); + ASSERT_EQ(GRPC_ERROR_NONE, error); + GRPC_ERROR_UNREF(error); +} + +TEST(ErrorUtilsTest, GrpcSpecialErrorNoneToAbslStatus) { + absl::Status status = grpc_error_to_absl_status(GRPC_ERROR_NONE); + ASSERT_TRUE(status.ok()); + ASSERT_EQ(status.message(), ""); +} + +// ---- Asymmetry of conversions of "Special" errors ---- +TEST(ErrorUtilsTest, AbslStatusToGrpcErrorDoesNotReturnSpecialVariables) { + grpc_error_handle error = + absl_status_to_grpc_error(absl::CancelledError("Cancelled")); + ASSERT_NE(error, GRPC_ERROR_CANCELLED); + GRPC_ERROR_UNREF(error); +} + +TEST(ErrorUtilsTest, GrpcSpecialErrorCancelledToAbslStatus) { + absl::Status status = grpc_error_to_absl_status(GRPC_ERROR_CANCELLED); + ASSERT_TRUE(absl::IsCancelled(status)); + ASSERT_EQ(status.message(), "Cancelled"); +} + +TEST(ErrorUtilsTest, GrpcSpecialErrorOOMToAbslStatus) { + absl::Status status = grpc_error_to_absl_status(GRPC_ERROR_OOM); + ASSERT_TRUE(absl::IsResourceExhausted(status)); + ASSERT_EQ(status.message(), "Out of memory"); +} + +// ---- Ordinary statuses ---- +TEST(ErrorUtilsTest, AbslUnavailableToGrpcError) { + grpc_error_handle error = + absl_status_to_grpc_error(absl::UnavailableError("Making tea")); + // Status code checks + intptr_t code; + ASSERT_TRUE(grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &code)); + ASSERT_EQ(static_cast(code), GRPC_STATUS_UNAVAILABLE); + // Status message checks + grpc_slice message; + ASSERT_TRUE(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &message)); + absl::string_view str = grpc_core::StringViewFromSlice(message); + ASSERT_EQ(str, "Making tea"); + grpc_slice_unref(message); + GRPC_ERROR_UNREF(error); +} + +TEST(ErrorUtilsTest, GrpcErrorUnavailableToAbslStatus) { + grpc_error_handle error = grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "weighted_target: all children report state TRANSIENT_FAILURE"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + absl::Status status = grpc_error_to_absl_status(error); + ASSERT_TRUE(absl::IsUnavailable(status)); + ASSERT_EQ(status.message(), + "weighted_target: all children report state TRANSIENT_FAILURE"); + GRPC_ERROR_UNREF(error); +} + +} // namespace + +int main(int argc, char** argv) { + testing::InitGoogleTest(&argc, argv); + grpc::testing::TestEnvironment env(argc, argv); + return RUN_ALL_TESTS(); +}; diff --git a/test/core/transport/stream_owned_slice_test.cc b/test/core/transport/stream_owned_slice_test.cc index 62ce964207a..ca8140ca388 100644 --- a/test/core/transport/stream_owned_slice_test.cc +++ b/test/core/transport/stream_owned_slice_test.cc @@ -23,7 +23,7 @@ #include #include -static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} +static void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); diff --git a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc index 7e49e68e0bc..559709fa43e 100644 --- a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc +++ b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc @@ -236,6 +236,7 @@ class FakeHandshakerService : public HandshakerService::Service { result.mutable_local_identity()->set_service_account("local_identity"); string key(1024, '\0'); result.set_key_data(key); + result.set_max_frame_size(16384); result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_major(2); result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_minor(1); result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_major(2); diff --git a/test/core/tsi/alts/fake_handshaker/handshaker.proto b/test/core/tsi/alts/fake_handshaker/handshaker.proto index 8af9abfbf56..1a53a45cd5a 100644 --- a/test/core/tsi/alts/fake_handshaker/handshaker.proto +++ b/test/core/tsi/alts/fake_handshaker/handshaker.proto @@ -95,6 +95,9 @@ message StartClientHandshakeReq { // (Optional) RPC protocol versions supported by the client. RpcProtocolVersions rpc_versions = 9; + + // (Optional) Maximum frame size supported by the client. + uint32 max_frame_size = 10; } message ServerHandshakeParameters { @@ -133,6 +136,9 @@ message StartServerHandshakeReq { // (Optional) RPC protocol versions supported by the server. RpcProtocolVersions rpc_versions = 6; + + // (Optional) Maximum frame size supported by the server. + uint32 max_frame_size = 7; } message NextHandshakeMessageReq { @@ -180,6 +186,9 @@ message HandshakerResult { // The RPC protocol versions supported by the peer. RpcProtocolVersions peer_rpc_versions = 7; + + // The maximum frame size of the peer. + uint32 max_frame_size = 8; } message HandshakerStatus { diff --git a/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc b/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc index 93f326d3d3e..80c0b5d89e8 100644 --- a/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc +++ b/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc @@ -138,10 +138,7 @@ static grpc_gcp_HandshakerReq* deserialize_handshaker_req( } static bool is_recv_status_op(const grpc_op* op, size_t nops) { - if (nops == 1 && op->op == GRPC_OP_RECV_STATUS_ON_CLIENT) { - return true; - } - return false; + return nops == 1 && op->op == GRPC_OP_RECV_STATUS_ON_CLIENT; } /** diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc index 104ba4d934c..87f8dfb4229 100644 --- a/test/core/tsi/ssl_transport_security_test.cc +++ b/test/core/tsi/ssl_transport_security_test.cc @@ -253,13 +253,13 @@ void check_server0_peer(tsi_peer* peer) { tsi_peer_destruct(peer); } -static bool check_subject_alt_name(tsi_peer* peer, const char* name) { +static bool check_property(tsi_peer* peer, const char* property_name, + const char* property_value) { for (size_t i = 0; i < peer->property_count; i++) { const tsi_peer_property* prop = &peer->properties[i]; - if (strcmp(prop->name, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == - 0) { - if (strlen(name) == prop->value.length && - memcmp(prop->value.data, name, prop->value.length) == 0) { + if (strcmp(prop->name, property_name) == 0) { + if (strlen(property_value) == prop->value.length && + memcmp(prop->value.data, property_value, prop->value.length) == 0) { return true; } } @@ -267,17 +267,25 @@ static bool check_subject_alt_name(tsi_peer* peer, const char* name) { return false; } +static bool check_subject_alt_name(tsi_peer* peer, const char* name) { + return check_property(peer, TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, + name); +} + +static bool check_dns(tsi_peer* peer, const char* name) { + return check_property(peer, TSI_X509_DNS_PEER_PROPERTY, name); +} + static bool check_uri(tsi_peer* peer, const char* name) { - for (size_t i = 0; i < peer->property_count; i++) { - const tsi_peer_property* prop = &peer->properties[i]; - if (strcmp(prop->name, TSI_X509_URI_PEER_PROPERTY) == 0) { - if (strlen(name) == prop->value.length && - memcmp(prop->value.data, name, prop->value.length) == 0) { - return true; - } - } - } - return false; + return check_property(peer, TSI_X509_URI_PEER_PROPERTY, name); +} + +static bool check_email(tsi_peer* peer, const char* name) { + return check_property(peer, TSI_X509_EMAIL_PEER_PROPERTY, name); +} + +static bool check_ip(tsi_peer* peer, const char* name) { + return check_property(peer, TSI_X509_IP_PEER_PROPERTY, name); } void check_server1_peer(tsi_peer* peer) { @@ -329,12 +337,20 @@ static void ssl_test_check_handshaker_peers(tsi_test_fixture* fixture) { // and send an alert to the client as the first application data message. In // TLS 1.2, the client-side handshake will fail if the client sends a bad // certificate. + // + // For OpenSSL versions < 1.1, TLS 1.3 is not supported, so the client-side + // handshake should succeed precisely when the server-side handshake + // succeeds. bool expect_server_success = !(key_cert_lib->use_bad_server_cert || (key_cert_lib->use_bad_client_cert && ssl_fixture->force_client_auth)); +#if OPENSSL_VERSION_NUMBER >= 0x10100000 bool expect_client_success = test_tls_version == tsi_tls_version::TSI_TLS1_2 ? expect_server_success : !key_cert_lib->use_bad_server_cert; +#else + bool expect_client_success = expect_server_success; +#endif if (expect_client_success) { GPR_ASSERT(tsi_handshaker_result_extract_peer( ssl_fixture->base.client_result, &peer) == TSI_OK); @@ -693,7 +709,7 @@ static bool is_slow_build() { #if defined(GPR_ARCH_32) || defined(__APPLE__) return true; #else - return BuiltUnderMsan(); + return BuiltUnderMsan() || BuiltUnderTsan(); #endif } @@ -701,11 +717,11 @@ void ssl_tsi_test_do_round_trip_odd_buffer_size() { gpr_log(GPR_INFO, "ssl_tsi_test_do_round_trip_odd_buffer_size"); const size_t odd_sizes[] = {1025, 2051, 4103, 8207, 16409}; size_t size = sizeof(odd_sizes) / sizeof(size_t); - // 1. avoid test being extremely slow under MSAN - // 2. on 32-bit, the test is much slower (probably due to lack of boringssl - // asm optimizations) so we only run a subset of tests to avoid timeout - // 3. on Mac OS, we have slower testing machines so we only run a subset - // of tests to avoid timeout + // 1. This test is extremely slow under MSAN and TSAN. + // 2. On 32-bit, the test is much slower (probably due to lack of boringssl + // asm optimizations) so we only run a subset of tests to avoid timeout. + // 3. On Mac OS, we have slower testing machines so we only run a subset + // of tests to avoid timeout. if (is_slow_build()) { size = 1; } @@ -902,8 +918,9 @@ void ssl_tsi_test_extract_x509_subject_names() { GPR_ASSERT(tsi_ssl_extract_x509_subject_names_from_pem_cert(cert, &peer) == TSI_OK); // tsi_peer should include one common name, one certificate, one security - // level, seven SAN fields, three URI fields. - size_t expected_property_count = 12; + // level, ten SAN fields, two DNS SAN fields, three URI fields, two email + // addresses and two IP addresses. + size_t expected_property_count = 21; GPR_ASSERT(peer.property_count == expected_property_count); // Check common name const char* expected_cn = "xpigors"; @@ -919,6 +936,8 @@ void ssl_tsi_test_extract_x509_subject_names() { // Check DNS GPR_ASSERT(check_subject_alt_name(&peer, "foo.test.domain.com") == 1); GPR_ASSERT(check_subject_alt_name(&peer, "bar.test.domain.com") == 1); + GPR_ASSERT(check_dns(&peer, "foo.test.domain.com") == 1); + GPR_ASSERT(check_dns(&peer, "bar.test.domain.com") == 1); // Check URI // Note that a valid SPIFFE certificate should only have one URI. GPR_ASSERT(check_subject_alt_name(&peer, "spiffe://foo.com/bar/baz") == 1); @@ -932,6 +951,15 @@ void ssl_tsi_test_extract_x509_subject_names() { // Check email address GPR_ASSERT(check_subject_alt_name(&peer, "foo@test.domain.com") == 1); GPR_ASSERT(check_subject_alt_name(&peer, "bar@test.domain.com") == 1); + GPR_ASSERT(check_email(&peer, "foo@test.domain.com") == 1); + GPR_ASSERT(check_email(&peer, "bar@test.domain.com") == 1); + // Check ip address + GPR_ASSERT(check_subject_alt_name(&peer, "192.168.7.1") == 1); + GPR_ASSERT(check_subject_alt_name(&peer, "13::17") == 1); + GPR_ASSERT(check_ip(&peer, "192.168.7.1") == 1); + GPR_ASSERT(check_ip(&peer, "13::17") == 1); + // Check other fields + GPR_ASSERT(check_subject_alt_name(&peer, "other types of SAN") == 1); // Free memory gpr_free(cert); tsi_peer_destruct(&peer); @@ -956,7 +984,11 @@ void ssl_tsi_test_extract_cert_chain() { X509_INFO* certInfo = sk_X509_INFO_value(certInfos, i); if (certInfo->x509 != nullptr) { GPR_ASSERT(sk_X509_push(cert_chain, certInfo->x509) != 0); +#if OPENSSL_VERSION_NUMBER >= 0x10100000 X509_up_ref(certInfo->x509); +#else + certInfo->x509->references += 1; +#endif } } tsi_peer_property chain_property; diff --git a/test/core/tsi/transport_security_test_lib.cc b/test/core/tsi/transport_security_test_lib.cc index 2975cee1a80..f0c428ab88b 100644 --- a/test/core/tsi/transport_security_test_lib.cc +++ b/test/core/tsi/transport_security_test_lib.cc @@ -50,7 +50,7 @@ typedef struct handshaker_args { bool is_client; bool transferred_data; bool appended_unused_bytes; - grpc_error* error; + grpc_error_handle error; } handshaker_args; static handshaker_args* handshaker_args_create(tsi_test_fixture* fixture, @@ -289,15 +289,14 @@ void tsi_test_frame_protector_receive_message_from_peer( gpr_free(message_buffer); } -grpc_error* on_handshake_next_done(tsi_result result, void* user_data, - const unsigned char* bytes_to_send, - size_t bytes_to_send_size, - tsi_handshaker_result* handshaker_result) { +grpc_error_handle on_handshake_next_done( + tsi_result result, void* user_data, const unsigned char* bytes_to_send, + size_t bytes_to_send_size, tsi_handshaker_result* handshaker_result) { handshaker_args* args = static_cast(user_data); GPR_ASSERT(args != nullptr); GPR_ASSERT(args->fixture != nullptr); tsi_test_fixture* fixture = args->fixture; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; /* Read more data if we need to. */ if (result == TSI_INCOMPLETE_DATA) { GPR_ASSERT(bytes_to_send_size == 0); @@ -341,11 +340,8 @@ static bool is_handshake_finished_properly(handshaker_args* args) { GPR_ASSERT(args != nullptr); GPR_ASSERT(args->fixture != nullptr); tsi_test_fixture* fixture = args->fixture; - if ((args->is_client && fixture->client_result != nullptr) || - (!args->is_client && fixture->server_result != nullptr)) { - return true; - } - return false; + return (args->is_client && fixture->client_result != nullptr) || + (!args->is_client && fixture->server_result != nullptr); } static void do_handshaker_next(handshaker_args* args) { diff --git a/test/core/uri/uri_parser_test.cc b/test/core/uri/uri_parser_test.cc index ec79a6374df..5f8fceeb0cb 100644 --- a/test/core/uri/uri_parser_test.cc +++ b/test/core/uri/uri_parser_test.cc @@ -16,8 +16,6 @@ * */ -// TODO(hork): rewrite with googletest - #include "src/core/lib/uri/uri_parser.h" #include "absl/strings/str_join.h" diff --git a/test/core/util/BUILD b/test/core/util/BUILD index 7dff488bf38..765037e9655 100644 --- a/test/core/util/BUILD +++ b/test/core/util/BUILD @@ -25,7 +25,6 @@ grpc_cc_library( name = "grpc_test_util_base", srcs = [ "cmdline.cc", - "eval_args_mock_endpoint.cc", "fuzzer_util.cc", "grpc_profiler.cc", "histogram.cc", @@ -48,11 +47,12 @@ grpc_cc_library( ], hdrs = [ "cmdline.h", - "eval_args_mock_endpoint.h", + "evaluate_args_test_util.h", "fuzzer_util.h", "grpc_profiler.h", "histogram.h", "memory_counters.h", + "mock_authorization_endpoint.h", "mock_endpoint.h", "parse_hexstring.h", "passthru_endpoint.h", diff --git a/test/core/util/eval_args_mock_endpoint.cc b/test/core/util/eval_args_mock_endpoint.cc deleted file mode 100644 index 6f0de72dd3d..00000000000 --- a/test/core/util/eval_args_mock_endpoint.cc +++ /dev/null @@ -1,119 +0,0 @@ -// 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 - -#include "test/core/util/eval_args_mock_endpoint.h" - -#include - -#include - -#include "absl/strings/str_format.h" - -#include -#include -#include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" - -namespace grpc_core { - -class EvalArgsMockEndpoint { - public: - EvalArgsMockEndpoint(absl::string_view local_uri, absl::string_view peer_uri) - : local_address_(local_uri), peer_(peer_uri) { - base_.vtable = &vtable_; - } - grpc_endpoint* base() const { return const_cast(&base_); } - static void Read(grpc_endpoint* /*ep*/, grpc_slice_buffer* /*slices*/, - grpc_closure* /*cb*/, bool /*unused*/) {} - static void Write(grpc_endpoint* /*ep*/, grpc_slice_buffer* /*slices*/, - grpc_closure* /*cb*/, void* /*unused*/) {} - static void AddToPollset(grpc_endpoint* /*ep*/, grpc_pollset* /*unused*/) {} - static void AddToPollsetSet(grpc_endpoint* /*ep*/, - grpc_pollset_set* /*unused*/) {} - static void DeleteFromPollsetSet(grpc_endpoint* /*ep*/, - grpc_pollset_set* /*unused*/) {} - static void Shutdown(grpc_endpoint* /*ep*/, grpc_error* /*why*/) {} - static void Destroy(grpc_endpoint* ep) { - EvalArgsMockEndpoint* m = reinterpret_cast(ep); - delete m; - } - - static absl::string_view GetPeer(grpc_endpoint* ep) { - EvalArgsMockEndpoint* m = reinterpret_cast(ep); - return m->peer_; - } - - static absl::string_view GetLocalAddress(grpc_endpoint* ep) { - EvalArgsMockEndpoint* m = reinterpret_cast(ep); - return m->local_address_; - } - - static grpc_resource_user* GetResourceUser(grpc_endpoint* /*ep*/) { - return nullptr; - } - - static int GetFd(grpc_endpoint* /*unused*/) { return -1; } - static bool CanTrackErr(grpc_endpoint* /*unused*/) { return false; } - - private: - static constexpr grpc_endpoint_vtable vtable_ = { - EvalArgsMockEndpoint::Read, - EvalArgsMockEndpoint::Write, - EvalArgsMockEndpoint::AddToPollset, - EvalArgsMockEndpoint::AddToPollsetSet, - EvalArgsMockEndpoint::DeleteFromPollsetSet, - EvalArgsMockEndpoint::Shutdown, - EvalArgsMockEndpoint::Destroy, - EvalArgsMockEndpoint::GetResourceUser, - EvalArgsMockEndpoint::GetPeer, - EvalArgsMockEndpoint::GetLocalAddress, - EvalArgsMockEndpoint::GetFd, - EvalArgsMockEndpoint::CanTrackErr}; - grpc_endpoint base_; - std::string local_address_; - std::string peer_; -}; - -constexpr grpc_endpoint_vtable EvalArgsMockEndpoint::vtable_; - -namespace { - -std::string NameAndPortToURI(const char* addr, const int port) { - grpc_sockaddr_in address; - memset(&address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_port = htons(port); - inet_pton(AF_INET, addr, &address.sin_addr); - grpc_resolved_address resolved; - memset(&resolved, 0, sizeof(resolved)); - memcpy(resolved.addr, &address, sizeof(address)); - resolved.len = sizeof(address); - return grpc_sockaddr_to_uri(&resolved); -} - -} // namespace - -grpc_endpoint* CreateEvalArgsMockEndpoint(const char* local_address, - const int local_port, - const char* peer_address, - const int peer_port) { - EvalArgsMockEndpoint* m = - new EvalArgsMockEndpoint(NameAndPortToURI(local_address, local_port), - NameAndPortToURI(peer_address, peer_port)); - return m->base(); -} - -} // namespace grpc_core diff --git a/test/core/util/evaluate_args_test_util.h b/test/core/util/evaluate_args_test_util.h new file mode 100644 index 00000000000..a28f3fd1c0c --- /dev/null +++ b/test/core/util/evaluate_args_test_util.h @@ -0,0 +1,77 @@ +// Copyright 2021 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_TEST_CORE_UTIL_EVALUATE_ARGS_TEST_UTIL_H +#define GRPC_TEST_CORE_UTIL_EVALUATE_ARGS_TEST_UTIL_H + +#include + +#include + +#include + +#include "src/core/lib/security/authorization/evaluate_args.h" +#include "test/core/util/mock_authorization_endpoint.h" + +namespace grpc_core { + +class EvaluateArgsTestUtil { + public: + EvaluateArgsTestUtil() { grpc_metadata_batch_init(&metadata_); } + + ~EvaluateArgsTestUtil() { + grpc_metadata_batch_destroy(&metadata_); + delete channel_args_; + } + + void AddPairToMetadata(const char* key, const char* value) { + metadata_storage_.emplace_back(); + auto& storage = metadata_storage_.back(); + ASSERT_EQ(grpc_metadata_batch_add_tail( + &metadata_, &storage, + grpc_mdelem_from_slices( + grpc_slice_intern(grpc_slice_from_static_string(key)), + grpc_slice_intern(grpc_slice_from_static_string(value)))), + GRPC_ERROR_NONE); + } + + void SetLocalEndpoint(absl::string_view local_uri) { + endpoint_.SetLocalAddress(local_uri); + } + + void SetPeerEndpoint(absl::string_view peer_uri) { + endpoint_.SetPeer(peer_uri); + } + + void AddPropertyToAuthContext(const char* name, const char* value) { + auth_context_.add_cstring_property(name, value); + } + + EvaluateArgs MakeEvaluateArgs() { + channel_args_ = + new EvaluateArgs::PerChannelArgs(&auth_context_, &endpoint_); + return EvaluateArgs(&metadata_, channel_args_); + } + + private: + std::list metadata_storage_; + grpc_metadata_batch metadata_; + MockAuthorizationEndpoint endpoint_{/*local_uri=*/"", /*peer_uri=*/""}; + grpc_auth_context auth_context_{nullptr}; + EvaluateArgs::PerChannelArgs* channel_args_ = nullptr; +}; + +} // namespace grpc_core + +#endif // GRPC_TEST_CORE_UTIL_EVALUATE_ARGS_TEST_UTIL_H diff --git a/test/core/util/mock_authorization_endpoint.h b/test/core/util/mock_authorization_endpoint.h new file mode 100644 index 00000000000..7e6a7128bc6 --- /dev/null +++ b/test/core/util/mock_authorization_endpoint.h @@ -0,0 +1,62 @@ +// Copyright 2021 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_TEST_CORE_UTIL_MOCK_AUTHORIZATION_ENDPOINT_H +#define GRPC_TEST_CORE_UTIL_MOCK_AUTHORIZATION_ENDPOINT_H + +#include + +#include "src/core/lib/iomgr/endpoint.h" + +namespace grpc_core { + +class MockAuthorizationEndpoint : public grpc_endpoint { + public: + MockAuthorizationEndpoint(absl::string_view local_uri, + absl::string_view peer_uri) + : local_address_(local_uri), peer_address_(peer_uri) { + static constexpr grpc_endpoint_vtable vtable = { + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, GetPeer, GetLocalAddress, nullptr, nullptr}; + grpc_endpoint::vtable = &vtable; + } + + static absl::string_view GetPeer(grpc_endpoint* ep) { + MockAuthorizationEndpoint* m = + reinterpret_cast(ep); + return m->peer_address_; + } + + static absl::string_view GetLocalAddress(grpc_endpoint* ep) { + MockAuthorizationEndpoint* m = + reinterpret_cast(ep); + return m->local_address_; + } + + void SetPeer(absl::string_view peer_address) { + peer_address_ = std::string(peer_address); + } + + void SetLocalAddress(absl::string_view local_address) { + local_address_ = std::string(local_address); + } + + private: + std::string local_address_; + std::string peer_address_; +}; + +} // namespace grpc_core + +#endif // GRPC_TEST_CORE_UTIL_MOCK_AUTHORIZATION_ENDPOINT_H diff --git a/test/core/util/mock_endpoint.cc b/test/core/util/mock_endpoint.cc index b62613b8d34..af24d5f9502 100644 --- a/test/core/util/mock_endpoint.cc +++ b/test/core/util/mock_endpoint.cc @@ -76,7 +76,7 @@ static void me_add_to_pollset_set(grpc_endpoint* /*ep*/, static void me_delete_from_pollset_set(grpc_endpoint* /*ep*/, grpc_pollset_set* /*pollset*/) {} -static void me_shutdown(grpc_endpoint* ep, grpc_error* why) { +static void me_shutdown(grpc_endpoint* ep, grpc_error_handle why) { mock_endpoint* m = reinterpret_cast(ep); gpr_mu_lock(&m->mu); if (m->on_read) { diff --git a/test/core/util/passthru_endpoint.cc b/test/core/util/passthru_endpoint.cc index f856481bc65..635b0bac5f2 100644 --- a/test/core/util/passthru_endpoint.cc +++ b/test/core/util/passthru_endpoint.cc @@ -84,7 +84,7 @@ static void me_write(grpc_endpoint* ep, grpc_slice_buffer* slices, grpc_closure* cb, void* /*arg*/) { half* m = other_half(reinterpret_cast(ep)); gpr_mu_lock(&m->parent->mu); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; gpr_atm_no_barrier_fetch_add(&m->parent->stats->num_writes, (gpr_atm)1); if (m->parent->shutdown) { error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Endpoint already shutdown"); @@ -113,7 +113,7 @@ static void me_add_to_pollset_set(grpc_endpoint* /*ep*/, static void me_delete_from_pollset_set(grpc_endpoint* /*ep*/, grpc_pollset_set* /*pollset*/) {} -static void me_shutdown(grpc_endpoint* ep, grpc_error* why) { +static void me_shutdown(grpc_endpoint* ep, grpc_error_handle why) { half* m = reinterpret_cast(ep); gpr_mu_lock(&m->parent->mu); m->parent->shutdown = true; diff --git a/test/core/util/port.cc b/test/core/util/port.cc index eae4fbfb35a..391f472ac68 100644 --- a/test/core/util/port.cc +++ b/test/core/util/port.cc @@ -31,9 +31,9 @@ #include #include +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/http/httpcli.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "test/core/util/port_server_client.h" static int* chosen_ports = nullptr; diff --git a/test/core/util/port_server_client.cc b/test/core/util/port_server_client.cc index 973068dcda2..3747187e5bf 100644 --- a/test/core/util/port_server_client.cc +++ b/test/core/util/port_server_client.cc @@ -40,14 +40,14 @@ typedef struct freereq { int done = 0; } freereq; -static void destroy_pops_and_shutdown(void* p, grpc_error* /*error*/) { +static void destroy_pops_and_shutdown(void* p, grpc_error_handle /*error*/) { grpc_pollset* pollset = grpc_polling_entity_pollset(static_cast(p)); grpc_pollset_destroy(pollset); gpr_free(pollset); } -static void freed_port_from_server(void* arg, grpc_error* /*error*/) { +static void freed_port_from_server(void* arg, grpc_error_handle /*error*/) { freereq* pr = static_cast(arg); gpr_mu_lock(pr->mu); pr->done = 1; @@ -127,7 +127,7 @@ typedef struct portreq { grpc_httpcli_response response = {}; } portreq; -static void got_port_from_server(void* arg, grpc_error* error) { +static void got_port_from_server(void* arg, grpc_error_handle error) { size_t i; int port = 0; portreq* pr = static_cast(arg); @@ -136,9 +136,8 @@ static void got_port_from_server(void* arg, grpc_error* error) { if (error != GRPC_ERROR_NONE) { failed = 1; - const char* msg = grpc_error_string(error); - gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", msg); - + gpr_log(GPR_DEBUG, "failed port pick from server: retrying [%s]", + grpc_error_std_string(error).c_str()); } else if (response->status != 200) { failed = 1; gpr_log(GPR_DEBUG, "failed port pick from server: status=%d", diff --git a/test/core/util/resolve_localhost_ip46.cc b/test/core/util/resolve_localhost_ip46.cc index b465b754ba5..bf3f621c173 100644 --- a/test/core/util/resolve_localhost_ip46.cc +++ b/test/core/util/resolve_localhost_ip46.cc @@ -33,7 +33,7 @@ gpr_once g_resolve_localhost_ipv46 = GPR_ONCE_INIT; void InitResolveLocalhost() { grpc_resolved_addresses* addresses; - grpc_error* err = + grpc_error_handle err = grpc_blocking_resolve_address("localhost", "https", &addresses); GPR_ASSERT(err == GRPC_ERROR_NONE); for (size_t i = 0; i < addresses->naddrs; i++) { diff --git a/test/core/util/test_lb_policies.cc b/test/core/util/test_lb_policies.cc index 32645ae4f5e..452212e9a46 100644 --- a/test/core/util/test_lb_policies.cc +++ b/test/core/util/test_lb_policies.cc @@ -1,20 +1,18 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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. - * - */ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// #include "test/core/util/test_lb_policies.h" @@ -50,14 +48,14 @@ class ForwardingLoadBalancingPolicy : public LoadBalancingPolicy { public: ForwardingLoadBalancingPolicy( std::unique_ptr delegating_helper, Args args, - const std::string& delegate_policy_name, intptr_t initial_refcount = 1) + const char* delegate_policy_name, intptr_t initial_refcount = 1) : LoadBalancingPolicy(std::move(args), initial_refcount) { Args delegate_args; delegate_args.work_serializer = work_serializer(); delegate_args.channel_control_helper = std::move(delegating_helper); delegate_args.args = args.args; delegate_ = LoadBalancingPolicyRegistry::CreateLoadBalancingPolicy( - delegate_policy_name.c_str(), std::move(delegate_args)); + delegate_policy_name, std::move(delegate_args)); grpc_pollset_set_add_pollset_set(delegate_->interested_parties(), interested_parties()); } @@ -99,11 +97,11 @@ constexpr char kTestPickArgsLbPolicyName[] = "test_pick_args_lb"; class TestPickArgsLb : public ForwardingLoadBalancingPolicy { public: - TestPickArgsLb(Args args, TestPickArgsCallback cb) + TestPickArgsLb(Args args, TestPickArgsCallback cb, + const char* delegate_policy_name) : ForwardingLoadBalancingPolicy( absl::make_unique(RefCountedPtr(this), cb), - std::move(args), - /*delegate_policy_name=*/"pick_first", + std::move(args), delegate_policy_name, /*initial_refcount=*/2) {} ~TestPickArgsLb() override = default; @@ -171,23 +169,26 @@ class TestPickArgsLbConfig : public LoadBalancingPolicy::Config { class TestPickArgsLbFactory : public LoadBalancingPolicyFactory { public: - explicit TestPickArgsLbFactory(TestPickArgsCallback cb) - : cb_(std::move(cb)) {} + explicit TestPickArgsLbFactory(TestPickArgsCallback cb, + const char* delegate_policy_name) + : cb_(std::move(cb)), delegate_policy_name_(delegate_policy_name) {} OrphanablePtr CreateLoadBalancingPolicy( LoadBalancingPolicy::Args args) const override { - return MakeOrphanable(std::move(args), cb_); + return MakeOrphanable(std::move(args), cb_, + delegate_policy_name_); } const char* name() const override { return kTestPickArgsLbPolicyName; } RefCountedPtr ParseLoadBalancingConfig( - const Json& /*json*/, grpc_error** /*error*/) const override { + const Json& /*json*/, grpc_error_handle* /*error*/) const override { return MakeRefCounted(); } private: TestPickArgsCallback cb_; + const char* delegate_policy_name_; }; // @@ -279,7 +280,7 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy TrailingMetadataHandler(PickResult* result, InterceptRecvTrailingMetadataCallback cb) : cb_(std::move(cb)) { - result->recv_trailing_metadata_ready = [this](grpc_error* error, + result->recv_trailing_metadata_ready = [this](grpc_error_handle error, MetadataInterface* metadata, CallState* call_state) { RecordRecvTrailingMetadata(error, metadata, call_state); @@ -287,7 +288,7 @@ class InterceptRecvTrailingMetadataLoadBalancingPolicy } private: - void RecordRecvTrailingMetadata(grpc_error* /*error*/, + void RecordRecvTrailingMetadata(grpc_error_handle /*error*/, MetadataInterface* recv_trailing_metadata, CallState* call_state) { TrailingMetadataArgsSeen args_seen; @@ -325,7 +326,7 @@ class InterceptTrailingFactory : public LoadBalancingPolicyFactory { } RefCountedPtr ParseLoadBalancingConfig( - const Json& /*json*/, grpc_error** /*error*/) const override { + const Json& /*json*/, grpc_error_handle* /*error*/) const override { return MakeRefCounted(); } @@ -406,7 +407,7 @@ class AddressTestFactory : public LoadBalancingPolicyFactory { const char* name() const override { return kAddressTestLbPolicyName; } RefCountedPtr ParseLoadBalancingConfig( - const Json& /*json*/, grpc_error** /*error*/) const override { + const Json& /*json*/, grpc_error_handle* /*error*/) const override { return MakeRefCounted(); } @@ -416,9 +417,11 @@ class AddressTestFactory : public LoadBalancingPolicyFactory { } // namespace -void RegisterTestPickArgsLoadBalancingPolicy(TestPickArgsCallback cb) { +void RegisterTestPickArgsLoadBalancingPolicy(TestPickArgsCallback cb, + const char* delegate_policy_name) { LoadBalancingPolicyRegistry::Builder::RegisterLoadBalancingPolicyFactory( - absl::make_unique(std::move(cb))); + absl::make_unique(std::move(cb), + delegate_policy_name)); } void RegisterInterceptRecvTrailingMetadataLoadBalancingPolicy( diff --git a/test/core/util/test_lb_policies.h b/test/core/util/test_lb_policies.h index e125bb88a3b..e583abce5fc 100644 --- a/test/core/util/test_lb_policies.h +++ b/test/core/util/test_lb_policies.h @@ -1,20 +1,18 @@ -/* - * - * Copyright 2018 gRPC authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * 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. - * - */ +// +// Copyright 2018 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// 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_TEST_CORE_UTIL_TEST_LB_POLICIES_H #define GRPC_TEST_CORE_UTIL_TEST_LB_POLICIES_H @@ -32,9 +30,10 @@ struct PickArgsSeen { using TestPickArgsCallback = std::function; -// Registers an LB policy called "test_pick_args_lb" that checks the args -// passed to SubchannelPicker::Pick(). -void RegisterTestPickArgsLoadBalancingPolicy(TestPickArgsCallback cb); +// Registers an LB policy called "test_pick_args_lb" that passes the args +// passed to SubchannelPicker::Pick() to cb. +void RegisterTestPickArgsLoadBalancingPolicy( + TestPickArgsCallback cb, const char* delegate_policy_name = "pick_first"); struct TrailingMetadataArgsSeen { const LoadBalancingPolicy::BackendMetricData* backend_metric_data; diff --git a/test/core/util/test_tcp_server.cc b/test/core/util/test_tcp_server.cc index 9dd1e2af36a..0004369dc9d 100644 --- a/test/core/util/test_tcp_server.cc +++ b/test/core/util/test_tcp_server.cc @@ -34,7 +34,7 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" -static void on_server_destroyed(void* data, grpc_error* /*error*/) { +static void on_server_destroyed(void* data, grpc_error_handle /*error*/) { test_tcp_server* server = static_cast(data); server->shutdown = true; } @@ -64,8 +64,8 @@ void test_tcp_server_start(test_tcp_server* server, int port) { addr->sin_port = grpc_htons(static_cast(port)); memset(&addr->sin_addr, 0, sizeof(addr->sin_addr)); - grpc_error* error = grpc_tcp_server_create(&server->shutdown_complete, - nullptr, &server->tcp_server); + grpc_error_handle error = grpc_tcp_server_create( + &server->shutdown_complete, nullptr, &server->tcp_server); GPR_ASSERT(error == GRPC_ERROR_NONE); error = grpc_tcp_server_add_port(server->tcp_server, &resolved_addr, &port_added); @@ -88,8 +88,8 @@ void test_tcp_server_poll(test_tcp_server* server, int milliseconds) { gpr_mu_unlock(server->mu); } -static void do_nothing(void* /*arg*/, grpc_error* /*error*/) {} -static void finish_pollset(void* arg, grpc_error* /*error*/) { +static void do_nothing(void* /*arg*/, grpc_error_handle /*error*/) {} +static void finish_pollset(void* arg, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(arg)); } diff --git a/test/core/util/trickle_endpoint.cc b/test/core/util/trickle_endpoint.cc index 603b51ab80c..5b5199b7d7a 100644 --- a/test/core/util/trickle_endpoint.cc +++ b/test/core/util/trickle_endpoint.cc @@ -41,7 +41,7 @@ typedef struct { gpr_mu mu; grpc_slice_buffer write_buffer; grpc_slice_buffer writing_buffer; - grpc_error* error; + grpc_error_handle error; bool writing; grpc_closure* write_cb; } trickle_endpoint; @@ -96,7 +96,7 @@ static void te_delete_from_pollset_set(grpc_endpoint* ep, grpc_endpoint_delete_from_pollset_set(te->wrapped, pollset_set); } -static void te_shutdown(grpc_endpoint* ep, grpc_error* why) { +static void te_shutdown(grpc_endpoint* ep, grpc_error_handle why) { trickle_endpoint* te = reinterpret_cast(ep); gpr_mu_lock(&te->mu); if (te->error == GRPC_ERROR_NONE) { @@ -139,7 +139,7 @@ static int te_get_fd(grpc_endpoint* ep) { static bool te_can_track_err(grpc_endpoint* /*ep*/) { return false; } -static void te_finish_write(void* arg, grpc_error* /*error*/) { +static void te_finish_write(void* arg, grpc_error_handle /*error*/) { trickle_endpoint* te = static_cast(arg); gpr_mu_lock(&te->mu); te->writing = false; diff --git a/test/core/xds/certificate_provider_store_test.cc b/test/core/xds/certificate_provider_store_test.cc index 6df39ff321d..211e46ed357 100644 --- a/test/core/xds/certificate_provider_store_test.cc +++ b/test/core/xds/certificate_provider_store_test.cc @@ -58,7 +58,7 @@ class FakeCertificateProviderFactory1 : public CertificateProviderFactory { RefCountedPtr CreateCertificateProviderConfig(const Json& /*config_json*/, - grpc_error** /*error*/) override { + grpc_error_handle* /*error*/) override { return MakeRefCounted(); } @@ -81,7 +81,7 @@ class FakeCertificateProviderFactory2 : public CertificateProviderFactory { RefCountedPtr CreateCertificateProviderConfig(const Json& /*config_json*/, - grpc_error** /*error*/) override { + grpc_error_handle* /*error*/) override { return MakeRefCounted(); } diff --git a/test/core/xds/file_watcher_certificate_provider_factory_test.cc b/test/core/xds/file_watcher_certificate_provider_factory_test.cc index 0ecb0123cae..5157634ec7f 100644 --- a/test/core/xds/file_watcher_certificate_provider_factory_test.cc +++ b/test/core/xds/file_watcher_certificate_provider_factory_test.cc @@ -45,12 +45,12 @@ TEST(FileWatcherConfigTest, Basic) { " \"refresh_interval\": \"%ds\"" "}", kIdentityCertFile, kPrivateKeyFile, kRootCertFile, kRefreshInterval); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(config->identity_cert_file(), kIdentityCertFile); EXPECT_EQ(config->private_key_file(), kPrivateKeyFile); EXPECT_EQ(config->root_cert_file(), kRootCertFile); @@ -65,12 +65,12 @@ TEST(FileWatcherConfigTest, DefaultRefreshInterval) { " \"ca_certificate_file\": \"%s\"" "}", kIdentityCertFile, kPrivateKeyFile, kRootCertFile); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(config->identity_cert_file(), kIdentityCertFile); EXPECT_EQ(config->private_key_file(), kPrivateKeyFile); EXPECT_EQ(config->root_cert_file(), kRootCertFile); @@ -83,12 +83,12 @@ TEST(FileWatcherConfigTest, OnlyRootCertificatesFileProvided) { " \"ca_certificate_file\": \"%s\"" "}", kRootCertFile); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_TRUE(config->identity_cert_file().empty()); EXPECT_TRUE(config->private_key_file().empty()); EXPECT_EQ(config->root_cert_file(), kRootCertFile); @@ -102,12 +102,12 @@ TEST(FileWatcherConfigTest, OnlyIdenityCertificatesAndPrivateKeyProvided) { " \"private_key_file\": \"%s\"" "}", kIdentityCertFile, kPrivateKeyFile); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(config->identity_cert_file(), kIdentityCertFile); EXPECT_EQ(config->private_key_file(), kPrivateKeyFile); EXPECT_TRUE(config->root_cert_file().empty()); @@ -122,12 +122,12 @@ TEST(FileWatcherConfigTest, WrongTypes) { " \"ca_certificate_file\": 123," " \"refresh_interval\": 123" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "field:certificate_file error:type should be STRING.*" "field:private_key_file error:type should be STRING.*" @@ -144,12 +144,12 @@ TEST(FileWatcherConfigTest, IdentityCertProvidedButPrivateKeyMissing) { " \"certificate_file\": \"%s\"" "}", kIdentityCertFile); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "fields \"certificate_file\" and \"private_key_file\" must " "be both set or both unset.")); @@ -162,12 +162,12 @@ TEST(FileWatcherConfigTest, PrivateKeyProvidedButIdentityCertMissing) { " \"private_key_file\": \"%s\"" "}", kPrivateKeyFile); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "fields \"certificate_file\" and \"private_key_file\" must " "be both set or both unset.")); @@ -176,13 +176,13 @@ TEST(FileWatcherConfigTest, PrivateKeyProvidedButIdentityCertMissing) { TEST(FileWatcherConfigTest, EmptyJsonObject) { std::string json_str = absl::StrFormat("{}"); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = FileWatcherCertificateProviderFactory::Config::Parse(json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("At least one of \"certificate_file\" and " "\"ca_certificate_file\" must be specified.")); GRPC_ERROR_UNREF(error); diff --git a/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc b/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc index 8d336c3d3e9..bf72df295b4 100644 --- a/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc +++ b/test/core/xds/google_mesh_ca_certificate_provider_factory_test.cc @@ -67,12 +67,12 @@ TEST(GoogleMeshCaConfigTest, Basic) { "\"https://container.googleapis.com/v1/project/test-project1/locations/" "test-zone2/clusters/test-cluster3\"" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(config->endpoint(), "newmeshca.googleapis.com"); EXPECT_EQ(config->sts_config().token_exchange_service_uri, "newsecuretoken.googleapis.com"); @@ -120,12 +120,12 @@ TEST(GoogleMeshCaConfigTest, Defaults) { "\"https://container.googleapis.com/v1/project/test-project1/locations/" "test-zone2/clusters/test-cluster3\"" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(config->endpoint(), "meshca.googleapis.com"); EXPECT_EQ(config->sts_config().token_exchange_service_uri, "securetoken.googleapis.com"); @@ -172,13 +172,13 @@ TEST(GoogleMeshCaConfigTest, WrongExpectedValues) { "\"https://container.googleapis.com/v1/project/test-project1/locations/" "test-zone2/clusters/test-cluster3\"" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("field:api_type error:Only GRPC is supported.*" "field:key_type error:Only RSA is supported")); GRPC_ERROR_UNREF(error); @@ -215,13 +215,13 @@ TEST(GoogleMeshCaConfigTest, WrongTypes) { " \"key_size\": \"1024\"," " \"location\": 123" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex( "field:server.*field:api_type error:type should be STRING.*" "field:grpc_services.*field:google_grpc.*field:target_uri " @@ -259,13 +259,13 @@ TEST(GoogleMeshCaConfigTest, GrpcServicesNotAnArray) { "\"https://container.googleapis.com/v1/project/test-project1/locations/" "test-zone2/clusters/test-cluster3\"" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex( "field:server.*field:grpc_services error:type should be ARRAY")); GRPC_ERROR_UNREF(error); @@ -284,13 +284,13 @@ TEST(GoogleMeshCaConfigTest, GoogleGrpcNotAnObject) { "\"https://container.googleapis.com/v1/project/test-project1/locations/" "test-zone2/clusters/test-cluster3\"" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("field:server.*field:grpc_services.*field:" "google_grpc error:type should be OBJECT")); GRPC_ERROR_UNREF(error); @@ -311,12 +311,12 @@ TEST(GoogleMeshCaConfigTest, CallCredentialsNotAnArray) { "\"https://container.googleapis.com/v1/project/test-project1/locations/" "test-zone2/clusters/test-cluster3\"" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "field:server.*field:grpc_services.*field:google_grpc.*" "field:call_credentials error:type should be ARRAY")); @@ -340,13 +340,13 @@ TEST(GoogleMeshCaConfigTest, StsServiceNotAnObject) { "\"https://container.googleapis.com/v1/project/test-project1/locations/" "test-zone2/clusters/test-cluster3\"" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); auto config = GoogleMeshCaCertificateProviderFactory::Config::Parse(json, &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex( "field:server.*field:grpc_services.*field:google_grpc.*field:" "call_credentials.*field:sts_service error:type should be OBJECT")); diff --git a/test/core/xds/xds_bootstrap_test.cc b/test/core/xds/xds_bootstrap_test.cc index 3ae2c1a4a2d..09c8dd4c307 100644 --- a/test/core/xds/xds_bootstrap_test.cc +++ b/test/core/xds/xds_bootstrap_test.cc @@ -110,13 +110,14 @@ TEST_P(XdsBootstrapTest, Basic) { " }," " \"ignore\": \"whee\"" " }," + " \"server_listener_resource_name_template\": \"example/resource\"," " \"ignore\": {}" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(bootstrap.server().server_uri, "fake:///lb"); EXPECT_EQ(bootstrap.server().channel_creds_type, "fake"); EXPECT_EQ(bootstrap.server().channel_creds_config.type(), @@ -140,6 +141,8 @@ TEST_P(XdsBootstrapTest, Basic) { ::testing::AllOf( ::testing::Property(&Json::type, Json::Type::NUMBER), ::testing::Property(&Json::string_value, "1"))))); + EXPECT_EQ(bootstrap.server_listener_resource_name_template(), + "example/resource"); } TEST_P(XdsBootstrapTest, ValidWithoutNode) { @@ -152,11 +155,11 @@ TEST_P(XdsBootstrapTest, ValidWithoutNode) { " }" " ]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(bootstrap.server().server_uri, "fake:///lb"); EXPECT_EQ(bootstrap.server().channel_creds_type, "fake"); EXPECT_EQ(bootstrap.node(), nullptr); @@ -172,11 +175,11 @@ TEST_P(XdsBootstrapTest, InsecureCreds) { " }" " ]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(bootstrap.server().server_uri, "fake:///lb"); EXPECT_EQ(bootstrap.server().channel_creds_type, "insecure"); EXPECT_EQ(bootstrap.node(), nullptr); @@ -208,11 +211,11 @@ TEST_P(XdsBootstrapTest, GoogleDefaultCreds) { " }" " ]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); EXPECT_EQ(bootstrap.server().server_uri, "fake:///lb"); EXPECT_EQ(bootstrap.server().channel_creds_type, "google_default"); EXPECT_EQ(bootstrap.node(), nullptr); @@ -227,11 +230,11 @@ TEST_P(XdsBootstrapTest, MissingChannelCreds) { " }" " ]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex("\"channel_creds\" field not present")); GRPC_ERROR_UNREF(error); } @@ -246,22 +249,22 @@ TEST_P(XdsBootstrapTest, NoKnownChannelCreds) { " }" " ]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "no known creds type found in \"channel_creds\"")); GRPC_ERROR_UNREF(error); } TEST_P(XdsBootstrapTest, MissingXdsServers) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse("{}", &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex("\"xds_servers\" field not present")); GRPC_ERROR_UNREF(error); } @@ -271,17 +274,20 @@ TEST_P(XdsBootstrapTest, TopFieldsWrongTypes) { "{" " \"xds_servers\":1," " \"node\":1," + " \"server_listener_resource_name_template\":1," " \"certificate_providers\":1" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex("\"xds_servers\" field is not an array.*" - "\"node\" field is not an object.*")); + "\"node\" field is not an object.*" + "\"server_listener_resource_name_" + "template\" field is not a string.*")); if (GetParam().parse_xds_certificate_providers()) { - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "\"certificate_providers\" field is not an object")); } @@ -293,11 +299,11 @@ TEST_P(XdsBootstrapTest, XdsServerMissingServerUri) { "{" " \"xds_servers\":[{}]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex("errors parsing \"xds_servers\" array.*" "errors parsing index 0.*" "\"server_uri\" field not present")); @@ -314,12 +320,12 @@ TEST_P(XdsBootstrapTest, XdsServerUriAndCredsWrongTypes) { " }" " ]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("errors parsing \"xds_servers\" array.*" "errors parsing index 0.*" "\"server_uri\" field is not a string.*" @@ -342,12 +348,12 @@ TEST_P(XdsBootstrapTest, ChannelCredsFieldsWrongTypes) { " }" " ]" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); EXPECT_THAT( - grpc_error_string(error), + grpc_error_std_string(error), ::testing::ContainsRegex("errors parsing \"xds_servers\" array.*" "errors parsing index 0.*" "errors parsing \"channel_creds\" array.*" @@ -367,11 +373,11 @@ TEST_P(XdsBootstrapTest, NodeFieldsWrongTypes) { " \"metadata\":0" " }" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex("errors parsing \"node\" object.*" "\"id\" field is not a string.*" "\"cluster\" field is not a string.*" @@ -391,11 +397,11 @@ TEST_P(XdsBootstrapTest, LocalityFieldsWrongType) { " }" " }" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex("errors parsing \"node\" object.*" "errors parsing \"locality\" object.*" "\"region\" field is not a string.*" @@ -417,17 +423,17 @@ TEST_P(XdsBootstrapTest, CertificateProvidersElementWrongType) { " \"plugin\":1" " }" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); if (GetParam().parse_xds_certificate_providers()) { - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "errors parsing \"certificate_providers\" object.*" "element \"plugin\" is not an object")); } else { - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); } GRPC_ERROR_UNREF(error); } @@ -447,18 +453,18 @@ TEST_P(XdsBootstrapTest, CertificateProvidersPluginNameWrongType) { " }" " }" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); if (GetParam().parse_xds_certificate_providers()) { - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "errors parsing \"certificate_providers\" object.*" "errors parsing element \"plugin\".*" "\"plugin_name\" field is not a string")); } else { - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); } GRPC_ERROR_UNREF(error); } @@ -489,8 +495,8 @@ class FakeCertificateProviderFactory : public CertificateProviderFactory { RefCountedPtr CreateCertificateProviderConfig(const Json& config_json, - grpc_error** error) override { - std::vector error_list; + grpc_error_handle* error) override { + std::vector error_list; EXPECT_EQ(config_json.type(), Json::Type::OBJECT); auto it = config_json.object_value().find("value"); if (it == config_json.object_value().end()) { @@ -532,18 +538,18 @@ TEST_P(XdsBootstrapTest, CertificateProvidersFakePluginParsingError) { " }" " }" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); if (GetParam().parse_xds_certificate_providers()) { - EXPECT_THAT(grpc_error_string(error), + EXPECT_THAT(grpc_error_std_string(error), ::testing::ContainsRegex( "errors parsing \"certificate_providers\" object.*" "errors parsing element \"fake_plugin\".*" "field:config field:value not of type number")); } else { - EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + EXPECT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); } GRPC_ERROR_UNREF(error); } @@ -568,11 +574,11 @@ TEST_P(XdsBootstrapTest, CertificateProvidersFakePluginParsingSuccess) { " }" " }" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - ASSERT_TRUE(error == GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_TRUE(error == GRPC_ERROR_NONE) << grpc_error_std_string(error); if (GetParam().parse_xds_certificate_providers()) { const CertificateProviderStore::PluginDefinition& fake_plugin = bootstrap.certificate_providers().at("fake_plugin"); @@ -605,11 +611,11 @@ TEST_P(XdsBootstrapTest, CertificateProvidersFakePluginEmptyConfig) { " }" " }" "}"; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; Json json = Json::Parse(json_str, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); XdsBootstrap bootstrap(std::move(json), &error); - ASSERT_TRUE(error == GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_TRUE(error == GRPC_ERROR_NONE) << grpc_error_std_string(error); if (GetParam().parse_xds_certificate_providers()) { const CertificateProviderStore::PluginDefinition& fake_plugin = bootstrap.certificate_providers().at("fake_plugin"); diff --git a/test/core/xds/xds_certificate_provider_test.cc b/test/core/xds/xds_certificate_provider_test.cc index 8f6c8f3ab49..32e2bcb1697 100644 --- a/test/core/xds/xds_certificate_provider_test.cc +++ b/test/core/xds/xds_certificate_provider_test.cc @@ -73,8 +73,8 @@ class TestCertificatesWatcher } } - void OnError(grpc_error* root_cert_error, - grpc_error* identity_cert_error) override { + void OnError(grpc_error_handle root_cert_error, + grpc_error_handle identity_cert_error) override { GRPC_ERROR_UNREF(root_cert_error_); root_cert_error_ = root_cert_error; GRPC_ERROR_UNREF(identity_cert_error_); @@ -87,15 +87,15 @@ class TestCertificatesWatcher return key_cert_pairs_; } - grpc_error* root_cert_error() const { return root_cert_error_; } + grpc_error_handle root_cert_error() const { return root_cert_error_; } - grpc_error* identity_cert_error() const { return identity_cert_error_; } + grpc_error_handle identity_cert_error() const { return identity_cert_error_; } private: absl::optional root_certs_; absl::optional key_cert_pairs_; - grpc_error* root_cert_error_ = GRPC_ERROR_NONE; - grpc_error* identity_cert_error_ = GRPC_ERROR_NONE; + grpc_error_handle root_cert_error_ = GRPC_ERROR_NONE; + grpc_error_handle identity_cert_error_ = GRPC_ERROR_NONE; }; TEST( @@ -149,16 +149,16 @@ TEST( GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); EXPECT_EQ(watcher->root_certs(), kRootCert2); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr(kRootErrorMessage)); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for root certs. Test that the root cert error is reset. root_cert_distributor->SetKeyMaterials("root", kRootCert1, absl::nullopt); EXPECT_EQ(watcher->root_certs(), kRootCert1); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for identity certs. Test that the identity cert error is // reset. @@ -217,16 +217,16 @@ TEST(XdsCertificateProviderTest, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); EXPECT_EQ(watcher->root_certs(), kRootCert2); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr(kRootErrorMessage)); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for root certs. Test that the root cert error is reset. root_cert_distributor->SetKeyMaterials("test", kRootCert1, absl::nullopt); EXPECT_EQ(watcher->root_certs(), kRootCert1); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for identity certs. Test that the identity cert error is // reset. @@ -281,7 +281,7 @@ TEST(XdsCertificateProviderTest, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kRootErrorMessage)); EXPECT_EQ(watcher->root_certs(), kRootCert2); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr(kRootErrorMessage)); EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); distributor->SetErrorForCert( @@ -289,16 +289,16 @@ TEST(XdsCertificateProviderTest, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); EXPECT_EQ(watcher->root_certs(), kRootCert2); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr(kRootErrorMessage)); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for root distributor->SetKeyMaterials("root", kRootCert1, MakeKeyCertPairsType1()); EXPECT_EQ(watcher->root_certs(), kRootCert1); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for identity distributor->SetKeyMaterials("identity", kRootCert2, MakeKeyCertPairsType1()); @@ -345,7 +345,7 @@ TEST(XdsCertificateProviderTest, absl::nullopt); EXPECT_EQ(watcher->root_certs(), kRootCert2); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr(kRootErrorMessage)); EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); // Set error for identity @@ -354,16 +354,16 @@ TEST(XdsCertificateProviderTest, GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); EXPECT_EQ(watcher->root_certs(), kRootCert2); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr(kRootErrorMessage)); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for root distributor->SetKeyMaterials("", kRootCert1, absl::nullopt); EXPECT_EQ(watcher->root_certs(), kRootCert1); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update for identity distributor->SetKeyMaterials("", absl::nullopt, MakeKeyCertPairsType1()); @@ -383,11 +383,11 @@ TEST(XdsCertificateProviderTest, SwapOutDistributorsMultipleTimes) { // Initially there are no certificate providers. EXPECT_EQ(watcher->root_certs(), absl::nullopt); EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr( "No certificate provider available for root certificates")); EXPECT_THAT( - grpc_error_string(watcher->identity_cert_error()), + grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr( "No certificate provider available for identity certificates")); // Update root cert distributor. @@ -396,7 +396,7 @@ TEST(XdsCertificateProviderTest, SwapOutDistributorsMultipleTimes) { EXPECT_EQ(watcher->key_cert_pairs(), absl::nullopt); EXPECT_EQ(watcher->root_cert_error(), GRPC_ERROR_NONE); EXPECT_THAT( - grpc_error_string(watcher->identity_cert_error()), + grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr( "No certificate provider available for identity certificates")); // Update identity cert distributor @@ -417,9 +417,9 @@ TEST(XdsCertificateProviderTest, SwapOutDistributorsMultipleTimes) { GRPC_ERROR_CREATE_FROM_STATIC_STRING(kIdentityErrorMessage)); EXPECT_EQ(watcher->root_certs(), kRootCert2); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr(kRootErrorMessage)); - EXPECT_THAT(grpc_error_string(watcher->identity_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr(kIdentityErrorMessage)); // Send an update again distributor->SetKeyMaterials("", kRootCert1, MakeKeyCertPairsType1()); @@ -432,7 +432,7 @@ TEST(XdsCertificateProviderTest, SwapOutDistributorsMultipleTimes) { distributor->SetKeyMaterials("", kRootCert2, MakeKeyCertPairsType2()); EXPECT_EQ(watcher->root_certs(), kRootCert1); // not updated EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr( "No certificate provider available for root certificates")); EXPECT_EQ(watcher->identity_cert_error(), GRPC_ERROR_NONE); @@ -441,11 +441,11 @@ TEST(XdsCertificateProviderTest, SwapOutDistributorsMultipleTimes) { distributor->SetKeyMaterials("", kRootCert1, MakeKeyCertPairsType1()); EXPECT_EQ(watcher->root_certs(), kRootCert1); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); // not updated - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr( "No certificate provider available for root certificates")); EXPECT_THAT( - grpc_error_string(watcher->identity_cert_error()), + grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr( "No certificate provider available for identity certificates")); // Change certificate names being watched, without any certificate updates. @@ -453,11 +453,11 @@ TEST(XdsCertificateProviderTest, SwapOutDistributorsMultipleTimes) { provider.UpdateIdentityCertNameAndDistributor("", "identity", distributor); EXPECT_EQ(watcher->root_certs(), kRootCert1); EXPECT_EQ(watcher->key_cert_pairs(), MakeKeyCertPairsType2()); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr( "No certificate provider available for root certificates")); EXPECT_THAT( - grpc_error_string(watcher->identity_cert_error()), + grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr( "No certificate provider available for identity certificates")); // Send out certificate updates. @@ -509,11 +509,11 @@ TEST(XdsCertificateProviderTest, MultipleCertNames) { std::unique_ptr(watcher1), "test1", "test1"); EXPECT_EQ(watcher1->root_certs(), absl::nullopt); EXPECT_EQ(watcher1->key_cert_pairs(), absl::nullopt); - EXPECT_THAT(grpc_error_string(watcher1->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher1->root_cert_error()), ::testing::HasSubstr( "No certificate provider available for root certificates")); EXPECT_THAT( - grpc_error_string(watcher1->identity_cert_error()), + grpc_error_std_string(watcher1->identity_cert_error()), ::testing::HasSubstr( "No certificate provider available for identity certificates")); // Add distributor for "test1". This will return data to the watcher. @@ -557,11 +557,11 @@ TEST(XdsCertificateProviderTest, UnknownCertName) { auto* watcher = new TestCertificatesWatcher; provider.distributor()->WatchTlsCertificates( std::unique_ptr(watcher), "test", "test"); - EXPECT_THAT(grpc_error_string(watcher->root_cert_error()), + EXPECT_THAT(grpc_error_std_string(watcher->root_cert_error()), ::testing::HasSubstr( "No certificate provider available for root certificates")); EXPECT_THAT( - grpc_error_string(watcher->identity_cert_error()), + grpc_error_std_string(watcher->identity_cert_error()), ::testing::HasSubstr( "No certificate provider available for identity certificates")); } diff --git a/test/cpp/client/client_channel_stress_test.cc b/test/cpp/client/client_channel_stress_test.cc index 5b61d0e7dba..a3c5ed2d151 100644 --- a/test/cpp/client/client_channel_stress_test.cc +++ b/test/cpp/client/client_channel_stress_test.cc @@ -24,6 +24,7 @@ #include #include +#include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include @@ -40,9 +41,9 @@ #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/thd.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/transport/authority_override.h" @@ -180,8 +181,8 @@ class ClientChannelStressTest { port_ = grpc_pick_unused_port_or_die(); gpr_log(GPR_INFO, "starting %s server on port %d", type_.c_str(), port_); grpc::internal::CondVar cond; - thread_.reset(new std::thread( - std::bind(&ServerThread::Start, this, server_host, &mu, &cond))); + thread_ = absl::make_unique( + std::bind(&ServerThread::Start, this, server_host, &mu, &cond)); cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } @@ -241,7 +242,7 @@ class ClientChannelStressTest { static grpc_core::Resolver::Result MakeResolverResult( const std::vector& balancer_address_data) { grpc_core::Resolver::Result result; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; result.service_config = grpc_core::ServiceConfig::Create( nullptr, "{\"loadBalancingConfig\":[{\"grpclb\":{}}]}", &error); GPR_ASSERT(error == GRPC_ERROR_NONE); diff --git a/test/cpp/client/destroy_grpclb_channel_with_active_connect_stress_test.cc b/test/cpp/client/destroy_grpclb_channel_with_active_connect_stress_test.cc index f58db7ecdd2..ab458d45ec5 100644 --- a/test/cpp/client/destroy_grpclb_channel_with_active_connect_stress_test.cc +++ b/test/cpp/client/destroy_grpclb_channel_with_active_connect_stress_test.cc @@ -40,9 +40,9 @@ #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/thd.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "test/core/util/port.h" @@ -68,10 +68,10 @@ void TryConnectAndDestroy() { grpc_core::ServerAddressList addresses; addresses.emplace_back(address.addr, address.len, nullptr); grpc_core::Resolver::Result lb_address_result; - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; lb_address_result.service_config = grpc_core::ServiceConfig::Create( nullptr, "{\"loadBalancingConfig\":[{\"grpclb\":{}}]}", &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); grpc_arg arg = grpc_core::CreateGrpclbBalancerAddressesArg(&addresses); lb_address_result.args = grpc_channel_args_copy_and_add(nullptr, &arg, 1); response_generator->SetResponse(lb_address_result); diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden index bf456894ff7..6662d7855d9 100644 --- a/test/cpp/codegen/compiler_test_golden +++ b/test/cpp/codegen/compiler_test_golden @@ -130,9 +130,9 @@ class ServiceA final { // MethodA2 trailing comment 1 // Method A3 leading comment 1 #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL - virtual void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::ClientReadReactor< ::grpc::testing::Response>* reactor) = 0; + virtual void MethodA3(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::ClientReadReactor< ::grpc::testing::Response>* reactor) = 0; #else - virtual void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) = 0; + virtual void MethodA3(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) = 0; #endif // Method A3 trailing comment 1 // Method A4 leading comment 1 @@ -165,7 +165,7 @@ class ServiceA final { }; class Stub final : public StubInterface { public: - Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); ::grpc::Status MethodA1(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::testing::Response* response) override; std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>> AsyncMethodA1(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>>(AsyncMethodA1Raw(context, request, cq)); @@ -215,9 +215,9 @@ class ServiceA final { void MethodA2(::grpc::ClientContext* context, ::grpc::testing::Response* response, ::grpc::experimental::ClientWriteReactor< ::grpc::testing::Request>* reactor) override; #endif #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL - void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::ClientReadReactor< ::grpc::testing::Response>* reactor) override; + void MethodA3(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::ClientReadReactor< ::grpc::testing::Response>* reactor) override; #else - void MethodA3(::grpc::ClientContext* context, ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) override; + void MethodA3(::grpc::ClientContext* context, const ::grpc::testing::Request* request, ::grpc::experimental::ClientReadReactor< ::grpc::testing::Response>* reactor) override; #endif #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL void MethodA4(::grpc::ClientContext* context, ::grpc::ClientBidiReactor< ::grpc::testing::Request,::grpc::testing::Response>* reactor) override; @@ -922,7 +922,7 @@ class ServiceB final { }; class Stub final : public StubInterface { public: - Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); + Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); ::grpc::Status MethodB1(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::testing::Response* response) override; std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>> AsyncMethodB1(::grpc::ClientContext* context, const ::grpc::testing::Request& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc::testing::Response>>(AsyncMethodB1Raw(context, request, cq)); diff --git a/test/cpp/common/channel_filter_test.cc b/test/cpp/common/channel_filter_test.cc index 230737e4100..c077930be7a 100644 --- a/test/cpp/common/channel_filter_test.cc +++ b/test/cpp/common/channel_filter_test.cc @@ -28,8 +28,8 @@ class MyChannelData : public ChannelData { public: MyChannelData() {} - grpc_error* Init(grpc_channel_element* /*elem*/, - grpc_channel_element_args* args) override { + grpc_error_handle Init(grpc_channel_element* /*elem*/, + grpc_channel_element_args* args) override { (void)args->channel_args; // Make sure field is available. return GRPC_ERROR_NONE; } @@ -39,8 +39,8 @@ class MyCallData : public CallData { public: MyCallData() {} - grpc_error* Init(grpc_call_element* /*elem*/, - const grpc_call_element_args* args) override { + grpc_error_handle Init(grpc_call_element* /*elem*/, + const grpc_call_element_args* args) override { (void)args->path; // Make sure field is available. return GRPC_ERROR_NONE; } diff --git a/test/cpp/common/time_jump_test.cc b/test/cpp/common/time_jump_test.cc index 4836905bb9b..f6ff40feb69 100644 --- a/test/cpp/common/time_jump_test.cc +++ b/test/cpp/common/time_jump_test.cc @@ -90,7 +90,7 @@ TEST_P(TimeJumpTest, TimerRunning) { grpc_timer timer; grpc_timer_init(&timer, grpc_core::ExecCtx::Get()->Now() + 3000, GRPC_CLOSURE_CREATE( - [](void*, grpc_error* error) { + [](void*, grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_CANCELLED); }, nullptr, grpc_schedule_on_exec_ctx)); diff --git a/test/cpp/common/timer_test.cc b/test/cpp/common/timer_test.cc index 63c0757097f..dca02156820 100644 --- a/test/cpp/common/timer_test.cc +++ b/test/cpp/common/timer_test.cc @@ -84,7 +84,7 @@ TEST_F(TimerTest, OneTimerExpires) { int timer_fired = 0; grpc_timer_init(&timer, grpc_core::ExecCtx::Get()->Now() + 500, GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error*) { + [](void* arg, grpc_error_handle) { int* timer_fired = static_cast(arg); ++*timer_fired; }, @@ -109,7 +109,7 @@ TEST_F(TimerTest, MultipleTimersExpire) { for (int i = 0; i < kNumTimers; ++i) { grpc_timer_init(&timers[i], grpc_core::ExecCtx::Get()->Now() + 500 + i, GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error*) { + [](void* arg, grpc_error_handle) { int* timer_fired = static_cast(arg); ++*timer_fired; }, @@ -136,7 +136,7 @@ TEST_F(TimerTest, CancelSomeTimers) { for (int i = 0; i < kNumTimers; ++i) { grpc_timer_init(&timers[i], grpc_core::ExecCtx::Get()->Now() + 500 + i, GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error* error) { + [](void* arg, grpc_error_handle error) { if (error == GRPC_ERROR_CANCELLED) { return; } @@ -166,7 +166,7 @@ TEST_F(TimerTest, DISABLED_TimerNotCanceled) { grpc_core::ExecCtx exec_ctx; grpc_timer timer; grpc_timer_init(&timer, grpc_core::ExecCtx::Get()->Now() + 10000, - GRPC_CLOSURE_CREATE([](void*, grpc_error*) {}, nullptr, + GRPC_CLOSURE_CREATE([](void*, grpc_error_handle) {}, nullptr, grpc_schedule_on_exec_ctx)); } @@ -181,7 +181,7 @@ TEST_F(TimerTest, DISABLED_CancelRace) { grpc_timer* arg = (i != 0) ? &timers[i - 1] : nullptr; grpc_timer_init(&timers[i], grpc_core::ExecCtx::Get()->Now() + 100, GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error* /*error*/) { + [](void* arg, grpc_error_handle /*error*/) { grpc_timer* timer = static_cast(arg); if (timer) { grpc_timer_cancel(timer); @@ -211,7 +211,7 @@ TEST_F(TimerTest, DISABLED_CancelNextTimer) { } grpc_timer_init(&timers[i], grpc_core::ExecCtx::Get()->Now() + 100, GRPC_CLOSURE_CREATE( - [](void* arg, grpc_error* /*error*/) { + [](void* arg, grpc_error_handle /*error*/) { grpc_timer* timer = static_cast(arg); if (timer) { grpc_timer_cancel(timer); diff --git a/test/cpp/end2end/BUILD b/test/cpp/end2end/BUILD index d381f37b3a6..af4fc4efd3e 100644 --- a/test/cpp/end2end/BUILD +++ b/test/cpp/end2end/BUILD @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -licenses(["notice"]) - load("//bazel:grpc_build_system.bzl", "grpc_cc_binary", "grpc_cc_library", "grpc_cc_test", "grpc_package") +licenses(["notice"]) + grpc_package( name = "test/cpp/end2end", visibility = "public", @@ -240,9 +240,19 @@ grpc_cc_library( grpc_cc_test( name = "channelz_service_test", srcs = ["channelz_service_test.cc"], + data = [ + "//src/core/tsi/test_creds:ca.pem", + "//src/core/tsi/test_creds:client.key", + "//src/core/tsi/test_creds:client.pem", + "//src/core/tsi/test_creds:server1.key", + "//src/core/tsi/test_creds:server1.pem", + ], external_deps = [ "gtest", ], + # TODO(yulin-liang): The test is not able to load the certificate files on + # iOS. Figure out why. + tags = ["no_test_ios"], deps = [ ":test_service_impl", "//:gpr", @@ -528,6 +538,7 @@ grpc_cc_test( "//:grpc", "//:grpc++", "//:grpc_resolver_fake", + "//:grpcpp_csds", "//src/proto/grpc/testing:echo_messages_proto", "//src/proto/grpc/testing:echo_proto", "//src/proto/grpc/testing/duplicate:echo_duplicate_proto", @@ -541,6 +552,8 @@ grpc_cc_test( "//src/proto/grpc/testing/xds/v3:cluster_proto", "//src/proto/grpc/testing/xds/v3:discovery_proto", "//src/proto/grpc/testing/xds/v3:endpoint_proto", + "//src/proto/grpc/testing/xds/v3:fault_common_proto", + "//src/proto/grpc/testing/xds/v3:fault_proto", "//src/proto/grpc/testing/xds/v3:http_connection_manager_proto", "//src/proto/grpc/testing/xds/v3:listener_proto", "//src/proto/grpc/testing/xds/v3:lrs_proto", @@ -860,3 +873,18 @@ grpc_cc_test( "//test/cpp/util:test_util", ], ) + +grpc_cc_test( + name = "admin_services_end2end_test", + srcs = ["admin_services_end2end_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + "//:grpc++", + "//:grpc++_reflection", + "//:grpcpp_admin", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) diff --git a/test/cpp/end2end/admin_services_end2end_test.cc b/test/cpp/end2end/admin_services_end2end_test.cc new file mode 100644 index 00000000000..4d9c3892d1b --- /dev/null +++ b/test/cpp/end2end/admin_services_end2end_test.cc @@ -0,0 +1,102 @@ +// +// +// Copyright 2021 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// + +#include +#include + +#include "absl/strings/str_cat.h" + +#include +#include + +#include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#include + +namespace grpc { +namespace testing { + +class AdminServicesTest : public ::testing::Test { + public: + void SetUp() override { + std::string address = + absl::StrCat("localhost:", grpc_pick_unused_port_or_die()); + // Create admin server + grpc::reflection::InitProtoReflectionServerBuilderPlugin(); + ServerBuilder builder; + builder.AddListeningPort(address, InsecureServerCredentials()); + ::grpc::AddAdminServices(&builder); + server_ = builder.BuildAndStart(); + // Create channel + auto reflection_stub = reflection::v1alpha::ServerReflection::NewStub( + CreateChannel(address, InsecureChannelCredentials())); + stream_ = reflection_stub->ServerReflectionInfo(&reflection_ctx_); + } + + std::vector GetServiceList() { + std::vector services; + reflection::v1alpha::ServerReflectionRequest request; + reflection::v1alpha::ServerReflectionResponse response; + request.set_list_services(""); + stream_->Write(request); + stream_->Read(&response); + for (auto& service : response.list_services_response().service()) { + services.push_back(service.name()); + } + return services; + } + + private: + std::unique_ptr server_; + ClientContext reflection_ctx_; + std::shared_ptr< + ClientReaderWriter> + stream_; +}; + +TEST_F(AdminServicesTest, ValidateRegisteredServices) { + // Using Contains here, because the server builder might register other + // services in certain environments. + EXPECT_THAT( + GetServiceList(), + ::testing::AllOf( + ::testing::Contains("grpc.channelz.v1.Channelz"), + ::testing::Contains("grpc.reflection.v1alpha.ServerReflection"))); +#if defined(GRPC_NO_XDS) || defined(DISABLED_XDS_PROTO_IN_CC) + EXPECT_THAT(GetServiceList(), + ::testing::Not(::testing::Contains( + "envoy.service.status.v3.ClientStatusDiscoveryService"))); +#else + EXPECT_THAT(GetServiceList(), + ::testing::Contains( + "envoy.service.status.v3.ClientStatusDiscoveryService")); +#endif // GRPC_NO_XDS or DISABLED_XDS_PROTO_IN_CC +} + +} // namespace testing +} // namespace grpc + +int main(int argc, char** argv) { + grpc::testing::TestEnvironment env(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + int ret = RUN_ALL_TESTS(); + return ret; +} diff --git a/test/cpp/end2end/channelz_service_test.cc b/test/cpp/end2end/channelz_service_test.cc index 8faeb29f8fa..3b5aa508c90 100644 --- a/test/cpp/end2end/channelz_service_test.cc +++ b/test/cpp/end2end/channelz_service_test.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -32,14 +33,21 @@ #include "absl/memory/memory.h" #include "src/core/lib/gpr/env.h" +#include "src/core/lib/iomgr/load_file.h" +#include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" +#include "src/core/lib/slice/slice_utils.h" +#include "src/cpp/client/secure_credentials.h" #include "src/proto/grpc/channelz/channelz.grpc.pb.h" #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" #include "test/cpp/end2end/test_service_impl.h" +#include "test/cpp/util/test_credentials_provider.h" #include +using grpc::channelz::v1::Address; using grpc::channelz::v1::GetChannelRequest; using grpc::channelz::v1::GetChannelResponse; using grpc::channelz::v1::GetServerRequest; @@ -59,6 +67,14 @@ namespace grpc { namespace testing { namespace { +static bool ValidateAddress(const Address& address) { + if (address.address_case() != Address::kTcpipAddress) { + return true; + } + return address.tcpip_address().ip_address().size() == 4 || + address.tcpip_address().ip_address().size() == 16; +} + // Proxy service supports N backends. Sends RPC to backend dictated by // request->backend_channel_idx(). class Proxy : public ::grpc::testing::EchoTestService::Service { @@ -102,9 +118,75 @@ class Proxy : public ::grpc::testing::EchoTestService::Service { std::vector> stubs_; }; -} // namespace +enum class CredentialsType { + kInsecure = 0, + kTls = 1, + kMtls = 2, +}; + +constexpr char kCaCertPath[] = "src/core/tsi/test_creds/ca.pem"; +constexpr char kServerCertPath[] = "src/core/tsi/test_creds/server1.pem"; +constexpr char kServerKeyPath[] = "src/core/tsi/test_creds/server1.key"; +constexpr char kClientCertPath[] = "src/core/tsi/test_creds/client.pem"; +constexpr char kClientKeyPath[] = "src/core/tsi/test_creds/client.key"; + +std::string ReadFile(const char* file_path) { + grpc_slice slice; + GPR_ASSERT( + GRPC_LOG_IF_ERROR("load_file", grpc_load_file(file_path, 0, &slice))); + std::string file_contents(grpc_core::StringViewFromSlice(slice)); + grpc_slice_unref(slice); + return file_contents; +} + +grpc_core::PemKeyCertPairList ReadTlsIdentityPair(const char* key_path, + const char* cert_path) { + return grpc_core::PemKeyCertPairList{ + grpc_core::PemKeyCertPair(ReadFile(key_path), ReadFile(cert_path))}; +} + +std::shared_ptr GetChannelCredentials( + CredentialsType type, ChannelArguments* args) { + if (type == CredentialsType::kInsecure) { + return InsecureChannelCredentials(); + } + args->SetSslTargetNameOverride("foo.test.google.fr"); + std::vector identity_key_cert_pairs = { + {ReadFile(kClientKeyPath), ReadFile(kClientCertPath)}}; + grpc::experimental::TlsChannelCredentialsOptions options; + options.set_certificate_provider( + std::make_shared( + ReadFile(kCaCertPath), identity_key_cert_pairs)); + if (type == CredentialsType::kMtls) { + options.watch_identity_key_cert_pairs(); + } + options.watch_root_certs(); + return grpc::experimental::TlsCredentials(options); +} + +std::shared_ptr GetServerCredentials( + CredentialsType type) { + if (type == CredentialsType::kInsecure) { + return InsecureServerCredentials(); + } + std::vector identity_key_cert_pairs = { + {ReadFile(kServerKeyPath), ReadFile(kServerCertPath)}}; + auto certificate_provider = + std::make_shared( + ReadFile(kCaCertPath), identity_key_cert_pairs); + grpc::experimental::TlsServerCredentialsOptions options(certificate_provider); + options.watch_root_certs(); + options.watch_identity_key_cert_pairs(); + options.set_cert_request_type(GRPC_SSL_REQUEST_CLIENT_CERTIFICATE_AND_VERIFY); + return grpc::experimental::TlsServerCredentials(options); +} + +std::string RemoveWhitespaces(std::string input) { + input.erase(remove_if(input.begin(), input.end(), isspace), input.end()); + return input; +} -class ChannelzServerTest : public ::testing::Test { +class ChannelzServerTest : public ::testing::TestWithParam { public: ChannelzServerTest() {} static void SetUpTestCase() { @@ -122,7 +204,7 @@ class ChannelzServerTest : public ::testing::Test { ServerBuilder proxy_builder; std::string proxy_server_address = "localhost:" + to_string(proxy_port_); proxy_builder.AddListeningPort(proxy_server_address, - InsecureServerCredentials()); + GetServerCredentials(GetParam())); // forces channelz and channel tracing to be enabled. proxy_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 1); proxy_builder.AddChannelArgument( @@ -141,7 +223,7 @@ class ChannelzServerTest : public ::testing::Test { std::string backend_server_address = "localhost:" + to_string(backends_[i].port); backend_builder.AddListeningPort(backend_server_address, - InsecureServerCredentials()); + GetServerCredentials(GetParam())); backends_[i].service = absl::make_unique(); // ensure that the backend itself has channelz disabled. backend_builder.AddChannelArgument(GRPC_ARG_ENABLE_CHANNELZ, 0); @@ -154,7 +236,8 @@ class ChannelzServerTest : public ::testing::Test { args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 1); args.SetInt(GRPC_ARG_MAX_CHANNEL_TRACE_EVENT_MEMORY_PER_NODE, 1024); std::shared_ptr channel_to_backend = ::grpc::CreateCustomChannel( - backend_server_address, InsecureChannelCredentials(), args); + backend_server_address, GetChannelCredentials(GetParam(), &args), + args); proxy_service_.AddChannelToBackend(channel_to_backend); } } @@ -164,8 +247,8 @@ class ChannelzServerTest : public ::testing::Test { ChannelArguments args; // disable channelz. We only want to focus on proxy to backend outbound. args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); - std::shared_ptr channel = - ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args); + std::shared_ptr channel = ::grpc::CreateCustomChannel( + target, GetChannelCredentials(GetParam(), &args), args); channelz_stub_ = grpc::channelz::v1::Channelz::NewStub(channel); echo_stub_ = grpc::testing::EchoTestService::NewStub(channel); } @@ -177,8 +260,8 @@ class ChannelzServerTest : public ::testing::Test { args.SetInt(GRPC_ARG_ENABLE_CHANNELZ, 0); // This ensures that gRPC will not do connection sharing. args.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, true); - std::shared_ptr channel = - ::grpc::CreateCustomChannel(target, InsecureChannelCredentials(), args); + std::shared_ptr channel = ::grpc::CreateCustomChannel( + target, GetChannelCredentials(GetParam(), &args), args); return grpc::testing::EchoTestService::NewStub(channel); } @@ -260,7 +343,7 @@ class ChannelzServerTest : public ::testing::Test { std::vector backends_; }; -TEST_F(ChannelzServerTest, BasicTest) { +TEST_P(ChannelzServerTest, BasicTest) { ResetStubs(); ConfigureProxy(1); GetTopChannelsRequest request; @@ -272,7 +355,7 @@ TEST_F(ChannelzServerTest, BasicTest) { EXPECT_EQ(response.channel_size(), 1); } -TEST_F(ChannelzServerTest, HighStartId) { +TEST_P(ChannelzServerTest, HighStartId) { ResetStubs(); ConfigureProxy(1); GetTopChannelsRequest request; @@ -284,7 +367,7 @@ TEST_F(ChannelzServerTest, HighStartId) { EXPECT_EQ(response.channel_size(), 0); } -TEST_F(ChannelzServerTest, SuccessfulRequestTest) { +TEST_P(ChannelzServerTest, SuccessfulRequestTest) { ResetStubs(); ConfigureProxy(1); SendSuccessfulEcho(0); @@ -299,7 +382,7 @@ TEST_F(ChannelzServerTest, SuccessfulRequestTest) { EXPECT_EQ(response.channel().data().calls_failed(), 0); } -TEST_F(ChannelzServerTest, FailedRequestTest) { +TEST_P(ChannelzServerTest, FailedRequestTest) { ResetStubs(); ConfigureProxy(1); SendFailedEcho(0); @@ -314,7 +397,7 @@ TEST_F(ChannelzServerTest, FailedRequestTest) { EXPECT_EQ(response.channel().data().calls_failed(), 1); } -TEST_F(ChannelzServerTest, ManyRequestsTest) { +TEST_P(ChannelzServerTest, ManyRequestsTest) { ResetStubs(); ConfigureProxy(1); // send some RPCs @@ -338,7 +421,7 @@ TEST_F(ChannelzServerTest, ManyRequestsTest) { EXPECT_EQ(response.channel().data().calls_failed(), kNumFailed); } -TEST_F(ChannelzServerTest, ManyChannels) { +TEST_P(ChannelzServerTest, ManyChannels) { ResetStubs(); const int kNumChannels = 4; ConfigureProxy(kNumChannels); @@ -351,7 +434,7 @@ TEST_F(ChannelzServerTest, ManyChannels) { EXPECT_EQ(response.channel_size(), kNumChannels); } -TEST_F(ChannelzServerTest, ManyRequestsManyChannels) { +TEST_P(ChannelzServerTest, ManyRequestsManyChannels) { ResetStubs(); const int kNumChannels = 4; ConfigureProxy(kNumChannels); @@ -420,7 +503,7 @@ TEST_F(ChannelzServerTest, ManyRequestsManyChannels) { } } -TEST_F(ChannelzServerTest, ManySubchannels) { +TEST_P(ChannelzServerTest, ManySubchannels) { ResetStubs(); const int kNumChannels = 4; ConfigureProxy(kNumChannels); @@ -468,7 +551,7 @@ TEST_F(ChannelzServerTest, ManySubchannels) { } } -TEST_F(ChannelzServerTest, BasicServerTest) { +TEST_P(ChannelzServerTest, BasicServerTest) { ResetStubs(); ConfigureProxy(1); GetServersRequest request; @@ -480,7 +563,7 @@ TEST_F(ChannelzServerTest, BasicServerTest) { EXPECT_EQ(response.server_size(), 1); } -TEST_F(ChannelzServerTest, BasicGetServerTest) { +TEST_P(ChannelzServerTest, BasicGetServerTest) { ResetStubs(); ConfigureProxy(1); GetServersRequest get_servers_request; @@ -503,7 +586,7 @@ TEST_F(ChannelzServerTest, BasicGetServerTest) { get_server_response.server().ref().server_id()); } -TEST_F(ChannelzServerTest, ServerCallTest) { +TEST_P(ChannelzServerTest, ServerCallTest) { ResetStubs(); ConfigureProxy(1); const int kNumSuccess = 10; @@ -530,7 +613,7 @@ TEST_F(ChannelzServerTest, ServerCallTest) { kNumSuccess + kNumFailed + 1); } -TEST_F(ChannelzServerTest, ManySubchannelsAndSockets) { +TEST_P(ChannelzServerTest, ManySubchannelsAndSockets) { ResetStubs(); const int kNumChannels = 4; ConfigureProxy(kNumChannels); @@ -596,10 +679,24 @@ TEST_F(ChannelzServerTest, ManySubchannelsAndSockets) { // calls succeeded == messages received. EXPECT_EQ(get_subchannel_resp.subchannel().data().calls_succeeded(), get_socket_resp.socket().data().messages_received()); + switch (GetParam()) { + case CredentialsType::kInsecure: + EXPECT_FALSE(get_socket_resp.socket().has_security()); + break; + case CredentialsType::kTls: + case CredentialsType::kMtls: + EXPECT_TRUE(get_socket_resp.socket().has_security()); + EXPECT_TRUE(get_socket_resp.socket().security().has_tls()); + EXPECT_EQ( + RemoveWhitespaces( + get_socket_resp.socket().security().tls().remote_certificate()), + RemoveWhitespaces(ReadFile(kServerCertPath))); + break; + } } } -TEST_F(ChannelzServerTest, StreamingRPC) { +TEST_P(ChannelzServerTest, StreamingRPC) { ResetStubs(); ConfigureProxy(1); const int kNumMessages = 5; @@ -647,9 +744,24 @@ TEST_F(ChannelzServerTest, StreamingRPC) { EXPECT_EQ(get_socket_response.socket().data().messages_sent(), kNumMessages); EXPECT_EQ(get_socket_response.socket().data().messages_received(), kNumMessages); + switch (GetParam()) { + case CredentialsType::kInsecure: + EXPECT_FALSE(get_socket_response.socket().has_security()); + break; + case CredentialsType::kTls: + case CredentialsType::kMtls: + EXPECT_TRUE(get_socket_response.socket().has_security()); + EXPECT_TRUE(get_socket_response.socket().security().has_tls()); + EXPECT_EQ(RemoveWhitespaces(get_socket_response.socket() + .security() + .tls() + .remote_certificate()), + RemoveWhitespaces(ReadFile(kServerCertPath))); + break; + } } -TEST_F(ChannelzServerTest, GetServerSocketsTest) { +TEST_P(ChannelzServerTest, GetServerSocketsTest) { ResetStubs(); ConfigureProxy(1); GetServersRequest get_server_request; @@ -672,9 +784,43 @@ TEST_F(ChannelzServerTest, GetServerSocketsTest) { EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); EXPECT_EQ(get_server_sockets_response.socket_ref_size(), 1); EXPECT_TRUE(get_server_sockets_response.socket_ref(0).name().find("http")); + // Get the socket to verify security information. + GetSocketRequest get_socket_request; + GetSocketResponse get_socket_response; + ClientContext get_socket_context; + get_socket_request.set_socket_id( + get_server_sockets_response.socket_ref(0).socket_id()); + s = channelz_stub_->GetSocket(&get_socket_context, get_socket_request, + &get_socket_response); + EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + EXPECT_TRUE(ValidateAddress(get_socket_response.socket().remote())); + EXPECT_TRUE(ValidateAddress(get_socket_response.socket().local())); + switch (GetParam()) { + case CredentialsType::kInsecure: + EXPECT_FALSE(get_socket_response.socket().has_security()); + break; + case CredentialsType::kTls: + case CredentialsType::kMtls: + EXPECT_TRUE(get_socket_response.socket().has_security()); + EXPECT_TRUE(get_socket_response.socket().security().has_tls()); + if (GetParam() == CredentialsType::kMtls) { + EXPECT_EQ(RemoveWhitespaces(get_socket_response.socket() + .security() + .tls() + .remote_certificate()), + RemoveWhitespaces(ReadFile(kClientCertPath))); + } else { + EXPECT_TRUE(get_socket_response.socket() + .security() + .tls() + .remote_certificate() + .empty()); + } + break; + } } -TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) { +TEST_P(ChannelzServerTest, GetServerSocketsPaginationTest) { ResetStubs(); ConfigureProxy(1); std::vector> stubs; @@ -735,7 +881,7 @@ TEST_F(ChannelzServerTest, GetServerSocketsPaginationTest) { } } -TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { +TEST_P(ChannelzServerTest, GetServerListenSocketsTest) { ResetStubs(); ConfigureProxy(1); GetServersRequest get_server_request; @@ -760,6 +906,9 @@ TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { s = channelz_stub_->GetSocket(&get_socket_context_1, get_socket_request, &get_socket_response); EXPECT_TRUE(s.ok()) << "s.error_message() = " << s.error_message(); + + EXPECT_TRUE(ValidateAddress(get_socket_response.socket().remote())); + EXPECT_TRUE(ValidateAddress(get_socket_response.socket().local())); if (listen_socket_size == 2) { get_socket_request.set_socket_id( get_server_response.server(0).listen_socket(1).socket_id()); @@ -772,6 +921,12 @@ TEST_F(ChannelzServerTest, GetServerListenSocketsTest) { } } +INSTANTIATE_TEST_SUITE_P(ChannelzServer, ChannelzServerTest, + ::testing::ValuesIn(std::vector( + {CredentialsType::kInsecure, CredentialsType::kTls, + CredentialsType::kMtls}))); + +} // namespace } // namespace testing } // namespace grpc diff --git a/test/cpp/end2end/client_callback_end2end_test.cc b/test/cpp/end2end/client_callback_end2end_test.cc index 69973bb7a68..45f30eb525a 100644 --- a/test/cpp/end2end/client_callback_end2end_test.cc +++ b/test/cpp/end2end/client_callback_end2end_test.cc @@ -121,10 +121,14 @@ class ClientCallbackEnd2endTest is_server_started_ = true; } - void ResetStub() { + void ResetStub( + std::unique_ptr + interceptor = nullptr) { ChannelArguments args; auto channel_creds = GetCredentialsProvider()->GetChannelCredentials( GetParam().credentials_type, &args); + auto interceptors = CreatePhonyClientInterceptors(); + if (interceptor != nullptr) interceptors.push_back(std::move(interceptor)); switch (GetParam().protocol) { case Protocol::TCP: if (!GetParam().use_interceptors) { @@ -133,7 +137,7 @@ class ClientCallbackEnd2endTest } else { channel_ = CreateCustomChannelWithInterceptors( server_address_.str(), channel_creds, args, - CreatePhonyClientInterceptors()); + std::move(interceptors)); } break; case Protocol::INPROC: @@ -141,7 +145,7 @@ class ClientCallbackEnd2endTest channel_ = server_->InProcessChannel(args); } else { channel_ = server_->experimental().InProcessChannelWithInterceptors( - args, CreatePhonyClientInterceptors()); + args, std::move(interceptors)); } break; default: @@ -212,7 +216,8 @@ class ClientCallbackEnd2endTest } } - void SendRpcsGeneric(int num_rpcs, bool maybe_except) { + void SendRpcsGeneric(int num_rpcs, bool maybe_except, + const char* suffix_for_stats) { const std::string kMethodName("/grpc.testing.EchoTestService/Echo"); std::string test_string(""); for (int i = 0; i < num_rpcs; i++) { @@ -228,8 +233,9 @@ class ClientCallbackEnd2endTest std::mutex mu; std::condition_variable cv; bool done = false; + StubOptions options(suffix_for_stats); generic_stub_->experimental().UnaryCall( - &cli_ctx, kMethodName, send_buf.get(), &recv_buf, + &cli_ctx, kMethodName, options, send_buf.get(), &recv_buf, [&request, &recv_buf, &done, &mu, &cv, maybe_except](Status s) { GPR_ASSERT(s.ok()); @@ -241,7 +247,7 @@ class ClientCallbackEnd2endTest cv.notify_one(); #if GRPC_ALLOW_EXCEPTIONS if (maybe_except) { - throw - 1; + throw -1; } #else GPR_ASSERT(!maybe_except); @@ -254,7 +260,8 @@ class ClientCallbackEnd2endTest } } - void SendGenericEchoAsBidi(int num_rpcs, int reuses, bool do_writes_done) { + void SendGenericEchoAsBidi(int num_rpcs, int reuses, bool do_writes_done, + const char* suffix_for_stats) { const std::string kMethodName("/grpc.testing.EchoTestService/Echo"); std::string test_string(""); for (int i = 0; i < num_rpcs; i++) { @@ -263,14 +270,16 @@ class ClientCallbackEnd2endTest ByteBuffer> { public: Client(ClientCallbackEnd2endTest* test, const std::string& method_name, - const std::string& test_str, int reuses, bool do_writes_done) + const char* suffix_for_stats, const std::string& test_str, + int reuses, bool do_writes_done) : reuses_remaining_(reuses), do_writes_done_(do_writes_done) { - activate_ = [this, test, method_name, test_str] { + activate_ = [this, test, method_name, suffix_for_stats, test_str] { if (reuses_remaining_ > 0) { cli_ctx_ = absl::make_unique(); reuses_remaining_--; + StubOptions options(suffix_for_stats); test->generic_stub_->experimental().PrepareBidiStreamingCall( - cli_ctx_.get(), method_name, this); + cli_ctx_.get(), method_name, options, this); request_.set_message(test_str); send_buf_ = SerializeToByteBuffer(&request_); StartWrite(send_buf_.get()); @@ -317,7 +326,8 @@ class ClientCallbackEnd2endTest const bool do_writes_done_; }; - Client rpc(this, kMethodName, test_string, reuses, do_writes_done); + Client rpc(this, kMethodName, suffix_for_stats, test_string, reuses, + do_writes_done); rpc.Await(); } @@ -501,29 +511,46 @@ TEST_P(ClientCallbackEnd2endTest, SequentialRpcsWithVariedBinaryMetadataValue) { } TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcs) { - ResetStub(); - SendRpcsGeneric(10, false); + ResetStub(absl::make_unique( + "/grpc.testing.EchoTestService/Echo", nullptr)); + SendRpcsGeneric(10, false, /*suffix_for_stats=*/nullptr); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsWithSuffix) { + ResetStub(absl::make_unique( + "/grpc.testing.EchoTestService/Echo", "TestSuffix")); + SendRpcsGeneric(10, false, "TestSuffix"); } TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidi) { - ResetStub(); - SendGenericEchoAsBidi(10, 1, /*do_writes_done=*/true); + ResetStub(absl::make_unique( + "/grpc.testing.EchoTestService/Echo", nullptr)); + SendGenericEchoAsBidi(10, 1, /*do_writes_done=*/true, + /*suffix_for_stats=*/nullptr); +} + +TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidiWithSuffix) { + ResetStub(absl::make_unique( + "/grpc.testing.EchoTestService/Echo", "TestSuffix")); + SendGenericEchoAsBidi(10, 1, /*do_writes_done=*/true, "TestSuffix"); } TEST_P(ClientCallbackEnd2endTest, SequentialGenericRpcsAsBidiWithReactorReuse) { ResetStub(); - SendGenericEchoAsBidi(10, 10, /*do_writes_done=*/true); + SendGenericEchoAsBidi(10, 10, /*do_writes_done=*/true, + /*suffix_for_stats=*/nullptr); } TEST_P(ClientCallbackEnd2endTest, GenericRpcNoWritesDone) { ResetStub(); - SendGenericEchoAsBidi(1, 1, /*do_writes_done=*/false); + SendGenericEchoAsBidi(1, 1, /*do_writes_done=*/false, + /*suffix_for_stats=*/nullptr); } #if GRPC_ALLOW_EXCEPTIONS TEST_P(ClientCallbackEnd2endTest, ExceptingRpc) { ResetStub(); - SendRpcsGeneric(10, true); + SendRpcsGeneric(10, true, nullptr); } #endif @@ -822,18 +849,22 @@ TEST_P(ClientCallbackEnd2endTest, UnaryReactor) { } TEST_P(ClientCallbackEnd2endTest, GenericUnaryReactor) { - ResetStub(); const std::string kMethodName("/grpc.testing.EchoTestService/Echo"); + constexpr char kSuffixForStats[] = "TestSuffixForStats"; + ResetStub( + absl::make_unique(kMethodName, kSuffixForStats)); class UnaryClient : public grpc::experimental::ClientUnaryReactor { public: - UnaryClient(grpc::GenericStub* stub, const std::string& method_name) { + UnaryClient(grpc::GenericStub* stub, const std::string& method_name, + const char* suffix_for_stats) { cli_ctx_.AddMetadata("key1", "val1"); cli_ctx_.AddMetadata("key2", "val2"); request_.mutable_param()->set_echo_metadata_initially(true); request_.set_message("Hello metadata"); send_buf_ = SerializeToByteBuffer(&request_); - stub->experimental().PrepareUnaryCall(&cli_ctx_, method_name, + StubOptions options(suffix_for_stats); + stub->experimental().PrepareUnaryCall(&cli_ctx_, method_name, options, send_buf_.get(), &recv_buf_, this); StartCall(); } @@ -878,7 +909,7 @@ TEST_P(ClientCallbackEnd2endTest, GenericUnaryReactor) { bool initial_metadata_done_{false}; }; - UnaryClient test{generic_stub_.get(), kMethodName}; + UnaryClient test{generic_stub_.get(), kMethodName, kSuffixForStats}; test.Await(); // Make sure that the server interceptors were not notified of a cancel if (GetParam().use_interceptors) { diff --git a/test/cpp/end2end/client_interceptors_end2end_test.cc b/test/cpp/end2end/client_interceptors_end2end_test.cc index 5d9451c1518..79b272cbe63 100644 --- a/test/cpp/end2end/client_interceptors_end2end_test.cc +++ b/test/cpp/end2end/client_interceptors_end2end_test.cc @@ -76,6 +76,7 @@ class HijackingInterceptor : public experimental::Interceptor { info_ = info; // Make sure it is the right method EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); + EXPECT_EQ(info->suffix_for_stats(), nullptr); EXPECT_EQ(info->type(), experimental::ClientRpcInfo::Type::UNARY); } @@ -183,6 +184,7 @@ class HijackingInterceptorMakesAnotherCall : public experimental::Interceptor { info_ = info; // Make sure it is the right method EXPECT_EQ(strcmp("/grpc.testing.EchoTestService/Echo", info->method()), 0); + EXPECT_EQ(strcmp("TestSuffixForStats", info->suffix_for_stats()), 0); } void Intercept(experimental::InterceptorBatchMethods* methods) override { @@ -304,6 +306,7 @@ class BidiStreamingRpcHijackingInterceptor : public experimental::Interceptor { explicit BidiStreamingRpcHijackingInterceptor( experimental::ClientRpcInfo* info) { info_ = info; + EXPECT_EQ(info->suffix_for_stats(), nullptr); } void Intercept(experimental::InterceptorBatchMethods* methods) override { @@ -375,6 +378,10 @@ class ClientStreamingRpcHijackingInterceptor explicit ClientStreamingRpcHijackingInterceptor( experimental::ClientRpcInfo* info) { info_ = info; + EXPECT_EQ( + strcmp("/grpc.testing.EchoTestService/RequestStream", info->method()), + 0); + EXPECT_EQ(strcmp("TestSuffixForStats", info->suffix_for_stats()), 0); } void Intercept(experimental::InterceptorBatchMethods* methods) override { bool hijack = false; @@ -431,6 +438,7 @@ class ServerStreamingRpcHijackingInterceptor experimental::ClientRpcInfo* info) { info_ = info; got_failed_message_ = false; + EXPECT_EQ(info->suffix_for_stats(), nullptr); } void Intercept(experimental::InterceptorBatchMethods* methods) override { @@ -931,7 +939,7 @@ TEST_F(ClientInterceptorsEnd2endTest, auto channel = server_->experimental().InProcessChannelWithInterceptors( args, std::move(creators)); - MakeCall(channel); + MakeCall(channel, StubOptions("TestSuffixForStats")); // Make sure all interceptors were run once, since the hijacking interceptor // makes an RPC on the intercepted channel EXPECT_EQ(PhonyInterceptor::GetNumTimesRun(), 12); @@ -1059,7 +1067,8 @@ TEST_F(ClientInterceptorsStreamingEnd2endTest, ClientStreamingHijackingTest) { auto channel = experimental::CreateCustomChannelWithInterceptors( server_address_, InsecureChannelCredentials(), args, std::move(creators)); - auto stub = grpc::testing::EchoTestService::NewStub(channel); + auto stub = grpc::testing::EchoTestService::NewStub( + channel, StubOptions("TestSuffixForStats")); ClientContext ctx; EchoRequest req; EchoResponse resp; diff --git a/test/cpp/end2end/client_lb_end2end_test.cc b/test/cpp/end2end/client_lb_end2end_test.cc index f6ca7d66aef..33f882bda0c 100644 --- a/test/cpp/end2end/client_lb_end2end_test.cc +++ b/test/cpp/end2end/client_lb_end2end_test.cc @@ -45,12 +45,12 @@ #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/cpp/client/secure_credentials.h" diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index edc3e4e3181..4af06c6235c 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -38,6 +38,7 @@ #include #include "absl/memory/memory.h" +#include "absl/strings/match.h" #include "absl/strings/str_format.h" #include "src/core/ext/filters/client_channel/backup_poller.h" @@ -1459,13 +1460,11 @@ TEST_P(End2endTest, ExpectErrorTest) { EXPECT_EQ(iter->code(), s.error_code()); EXPECT_EQ(iter->error_message(), s.error_message()); EXPECT_EQ(iter->binary_error_details(), s.error_details()); - EXPECT_TRUE(context.debug_error_string().find("created") != - std::string::npos); - EXPECT_TRUE(context.debug_error_string().find("file") != std::string::npos); - EXPECT_TRUE(context.debug_error_string().find("line") != std::string::npos); - EXPECT_TRUE(context.debug_error_string().find("status") != - std::string::npos); - EXPECT_TRUE(context.debug_error_string().find("13") != std::string::npos); + EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "created")); + EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "file")); + EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "line")); + EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "status")); + EXPECT_TRUE(absl::StrContains(context.debug_error_string(), "13")); } } diff --git a/test/cpp/end2end/exception_test.cc b/test/cpp/end2end/exception_test.cc index cd29eb8a10b..404abfad376 100644 --- a/test/cpp/end2end/exception_test.cc +++ b/test/cpp/end2end/exception_test.cc @@ -41,7 +41,7 @@ class ExceptingServiceImpl : public ::grpc::testing::EchoTestService::Service { public: Status Echo(ServerContext* /*server_context*/, const EchoRequest* /*request*/, EchoResponse* /*response*/) override { - throw - 1; + throw -1; } Status RequestStream(ServerContext* /*context*/, ServerReader* /*reader*/, diff --git a/test/cpp/end2end/filter_end2end_test.cc b/test/cpp/end2end/filter_end2end_test.cc index 0d8f1d787bc..535ee295a62 100644 --- a/test/cpp/end2end/filter_end2end_test.cc +++ b/test/cpp/end2end/filter_end2end_test.cc @@ -101,8 +101,8 @@ int GetCallCounterValue() { class ChannelDataImpl : public ChannelData { public: - grpc_error* Init(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) override { + grpc_error_handle Init(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) override { IncrementConnectionCounter(); return GRPC_ERROR_NONE; } diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc index b9de77bac46..8b6affa2361 100644 --- a/test/cpp/end2end/grpclb_end2end_test.cc +++ b/test/cpp/end2end/grpclb_end2end_test.cc @@ -24,6 +24,7 @@ #include #include +#include "absl/memory/memory.h" #include "absl/strings/str_cat.h" #include "absl/strings/str_format.h" @@ -43,9 +44,9 @@ #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/service_config.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/transport/authority_override.h" @@ -563,7 +564,7 @@ class GrpclbEnd2endTest : public ::testing::Test { grpc_core::Resolver::Result result; result.addresses = CreateLbAddressesFromAddressDataList(backend_address_data); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; result.service_config = grpc_core::ServiceConfig::Create(nullptr, service_config_json, &error); GPR_ASSERT(error == GRPC_ERROR_NONE); @@ -603,8 +604,8 @@ class GrpclbEnd2endTest : public ::testing::Test { response_generator_->SetReresolutionResponse(std::move(result)); } - const std::vector GetBackendPorts(size_t start_index = 0, - size_t stop_index = 0) const { + std::vector GetBackendPorts(size_t start_index = 0, + size_t stop_index = 0) const { if (stop_index == 0) stop_index = backends_.size(); std::vector backend_ports; for (size_t i = start_index; i < stop_index; ++i) { @@ -696,8 +697,8 @@ class GrpclbEnd2endTest : public ::testing::Test { // by ServerThread::Serve from firing before the wait below is hit. grpc::internal::MutexLock lock(&mu); grpc::internal::CondVar cond; - thread_.reset(new std::thread( - std::bind(&ServerThread::Serve, this, server_host, &mu, &cond))); + thread_ = absl::make_unique( + std::bind(&ServerThread::Serve, this, server_host, &mu, &cond)); cond.Wait(&mu); gpr_log(GPR_INFO, "%s server startup complete", type_.c_str()); } diff --git a/test/cpp/end2end/interceptors_util.cc b/test/cpp/end2end/interceptors_util.cc index 875ae8fd41e..b90c8dcde74 100644 --- a/test/cpp/end2end/interceptors_util.cc +++ b/test/cpp/end2end/interceptors_util.cc @@ -27,8 +27,9 @@ std::atomic PhonyInterceptor::num_times_run_; std::atomic PhonyInterceptor::num_times_run_reverse_; std::atomic PhonyInterceptor::num_times_cancel_; -void MakeCall(const std::shared_ptr& channel) { - auto stub = grpc::testing::EchoTestService::NewStub(channel); +void MakeCall(const std::shared_ptr& channel, + const StubOptions& options) { + auto stub = grpc::testing::EchoTestService::NewStub(channel, options); ClientContext ctx; EchoRequest req; req.mutable_param()->set_echo_metadata(true); diff --git a/test/cpp/end2end/interceptors_util.h b/test/cpp/end2end/interceptors_util.h index b6ffd7e6640..2c394bf6182 100644 --- a/test/cpp/end2end/interceptors_util.h +++ b/test/cpp/end2end/interceptors_util.h @@ -82,6 +82,42 @@ class PhonyInterceptorFactory } }; +/* This interceptor can be used to test the interception mechanism. */ +class TestInterceptor : public experimental::Interceptor { + public: + TestInterceptor(const std::string& method, const char* suffix_for_stats, + experimental::ClientRpcInfo* info) { + EXPECT_EQ(info->method(), method); + + if (suffix_for_stats == nullptr || info->suffix_for_stats() == nullptr) { + EXPECT_EQ(info->suffix_for_stats(), suffix_for_stats); + } else { + EXPECT_EQ(strcmp(info->suffix_for_stats(), suffix_for_stats), 0); + } + } + + void Intercept(experimental::InterceptorBatchMethods* methods) override { + methods->Proceed(); + } +}; + +class TestInterceptorFactory + : public experimental::ClientInterceptorFactoryInterface { + public: + TestInterceptorFactory(const std::string& method, + const char* suffix_for_stats) + : method_(method), suffix_for_stats_(suffix_for_stats) {} + + experimental::Interceptor* CreateClientInterceptor( + experimental::ClientRpcInfo* info) override { + return new TestInterceptor(method_, suffix_for_stats_, info); + } + + private: + std::string method_; + const char* suffix_for_stats_; +}; + /* This interceptor factory returns nullptr on interceptor creation */ class NullInterceptorFactory : public experimental::ClientInterceptorFactoryInterface, @@ -164,7 +200,8 @@ class EchoTestServiceStreamingImpl : public EchoTestService::Service { constexpr int kNumStreamingMessages = 10; -void MakeCall(const std::shared_ptr& channel); +void MakeCall(const std::shared_ptr& channel, + const StubOptions& options = StubOptions()); void MakeClientStreamingCall(const std::shared_ptr& channel); diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc index f7d23e83678..1e83ad50533 100644 --- a/test/cpp/end2end/mock_test.cc +++ b/test/cpp/end2end/mock_test.cc @@ -288,7 +288,7 @@ class TestServiceImpl : public EchoTestService::Service { } private: - const vector split(const std::string& input) { + vector split(const std::string& input) { std::string buff(""); vector result; diff --git a/test/cpp/end2end/port_sharing_end2end_test.cc b/test/cpp/end2end/port_sharing_end2end_test.cc index f342bd00a85..e9fa8269bf9 100644 --- a/test/cpp/end2end/port_sharing_end2end_test.cc +++ b/test/cpp/end2end/port_sharing_end2end_test.cc @@ -148,7 +148,7 @@ class TestTcpServer { self->OnConnect(tcp, accepting_pollset, acceptor); } - static void OnFdReleased(void* arg, grpc_error* err) { + static void OnFdReleased(void* arg, grpc_error_handle err) { auto* self = static_cast(arg); self->OnFdReleased(err); } @@ -165,7 +165,7 @@ class TestTcpServer { grpc_tcp_destroy_and_release_fd(tcp, &fd_, &on_fd_released_); } - void OnFdReleased(grpc_error* err) { + void OnFdReleased(grpc_error_handle err) { EXPECT_EQ(GRPC_ERROR_NONE, err); experimental::ExternalConnectionAcceptor::NewConnectionParameters p; p.listener_fd = listener_fd_; diff --git a/test/cpp/end2end/service_config_end2end_test.cc b/test/cpp/end2end/service_config_end2end_test.cc index ceae2ed7bb8..67e02bc72a1 100644 --- a/test/cpp/end2end/service_config_end2end_test.cc +++ b/test/cpp/end2end/service_config_end2end_test.cc @@ -45,11 +45,11 @@ #include "src/core/ext/filters/client_channel/global_subchannel_pool.h" #include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/cpp/client/secure_credentials.h" diff --git a/test/cpp/end2end/xds_end2end_test.cc b/test/cpp/end2end/xds_end2end_test.cc index 276cadc55c2..ee31d09f86a 100644 --- a/test/cpp/end2end/xds_end2end_test.cc +++ b/test/cpp/end2end/xds_end2end_test.cc @@ -56,43 +56,47 @@ #include "src/core/ext/xds/xds_api.h" #include "src/core/ext/xds/xds_channel_args.h" #include "src/core/ext/xds/xds_client.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/time_precise.h" #include "src/core/lib/gpr/tmpfile.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" #include "src/core/lib/gprpp/time_util.h" #include "src/core/lib/iomgr/load_file.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/cpp/client/secure_credentials.h" #include "src/cpp/server/secure_server_credentials.h" - -#include "test/core/util/port.h" -#include "test/core/util/resolve_localhost_ip46.h" -#include "test/core/util/test_config.h" -#include "test/cpp/end2end/test_service_impl.h" - #include "src/proto/grpc/testing/echo.grpc.pb.h" #include "src/proto/grpc/testing/xds/ads_for_test.grpc.pb.h" #include "src/proto/grpc/testing/xds/cds_for_test.grpc.pb.h" #include "src/proto/grpc/testing/xds/eds_for_test.grpc.pb.h" #include "src/proto/grpc/testing/xds/lds_rds_for_test.grpc.pb.h" #include "src/proto/grpc/testing/xds/lrs_for_test.grpc.pb.h" - #include "src/proto/grpc/testing/xds/v3/ads.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/aggregate_cluster.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/discovery.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/endpoint.grpc.pb.h" +#include "src/proto/grpc/testing/xds/v3/fault.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/http_connection_manager.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/listener.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/lrs.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/route.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/router.grpc.pb.h" #include "src/proto/grpc/testing/xds/v3/tls.grpc.pb.h" +#include "test/core/util/port.h" +#include "test/core/util/resolve_localhost_ip46.h" +#include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_service_impl.h" + +#ifndef DISABLED_XDS_PROTO_IN_CC +#include "src/cpp/server/csds/csds.h" +#include "src/proto/grpc/testing/xds/v3/csds.grpc.pb.h" +#endif // DISABLED_XDS_PROTO_IN_CC namespace grpc { namespace testing { @@ -100,17 +104,24 @@ namespace { using std::chrono::system_clock; +#ifndef DISABLED_XDS_PROTO_IN_CC +using ::envoy::admin::v3::ClientResourceStatus; +#endif // DISABLED_XDS_PROTO_IN_CC using ::envoy::config::cluster::v3::CircuitBreakers; using ::envoy::config::cluster::v3::Cluster; using ::envoy::config::cluster::v3::CustomClusterType; using ::envoy::config::cluster::v3::RoutingPriority; using ::envoy::config::endpoint::v3::ClusterLoadAssignment; using ::envoy::config::endpoint::v3::HealthStatus; +using ::envoy::config::listener::v3::FilterChainMatch; using ::envoy::config::listener::v3::Listener; using ::envoy::config::route::v3::RouteConfiguration; using ::envoy::extensions::clusters::aggregate::v3::ClusterConfig; +using ::envoy::extensions::filters::http::fault::v3::HTTPFault; using ::envoy::extensions::filters::network::http_connection_manager::v3:: HttpConnectionManager; +using ::envoy::extensions::filters::network::http_connection_manager::v3:: + HttpFilter; using ::envoy::extensions::transport_sockets::tls::v3::DownstreamTlsContext; using ::envoy::extensions::transport_sockets::tls::v3::UpstreamTlsContext; using ::envoy::type::matcher::v3::StringMatcher; @@ -195,6 +206,8 @@ constexpr char kBootstrapFileV3[] = " \"sub_zone\": \"mp3\"\n" " }\n" " },\n" + " \"server_listener_resource_name_template\": " + "\"grpc/server?xds.resource.listening_address=%s\",\n" " \"certificate_providers\": {\n" " \"fake_plugin1\": {\n" " \"plugin_name\": \"fake1\"\n" @@ -467,22 +480,30 @@ class AdsServiceImpl : public std::enable_shared_from_this { }; struct EdsResourceArgs { + struct Endpoint { + explicit Endpoint(int port, + HealthStatus health_status = HealthStatus::UNKNOWN, + int lb_weight = 1) + : port(port), health_status(health_status), lb_weight(lb_weight) {} + + int port; + HealthStatus health_status; + int lb_weight; + }; + struct Locality { - Locality(std::string sub_zone, std::vector ports, + Locality(std::string sub_zone, std::vector endpoints, int lb_weight = kDefaultLocalityWeight, - int priority = kDefaultLocalityPriority, - std::vector health_statuses = {}) + int priority = kDefaultLocalityPriority) : sub_zone(std::move(sub_zone)), - ports(std::move(ports)), + endpoints(std::move(endpoints)), lb_weight(lb_weight), - priority(priority), - health_statuses(std::move(health_statuses)) {} + priority(priority) {} const std::string sub_zone; - std::vector ports; + std::vector endpoints; int lb_weight; int priority; - std::vector health_statuses; }; EdsResourceArgs() = default; @@ -1301,6 +1322,20 @@ class LrsServiceImpl : public std::enable_shared_from_this { class TestType { public: + enum FilterConfigSetup { + // Set the fault injection filter directly from LDS + kHTTPConnectionManagerOriginal, + // Enable the fault injection filter in LDS, but override the filter config + // in route. + kRouteOverride, + }; + + enum BootstrapSource { + kBootstrapFromChannelArg, + kBootstrapFromFile, + kBootstrapFromEnvVar, + }; + TestType& set_use_fake_resolver() { use_fake_resolver_ = true; return *this; @@ -1326,11 +1361,29 @@ class TestType { return *this; } + TestType& set_use_csds_streaming() { + use_csds_streaming_ = true; + return *this; + } + + TestType& set_filter_config_setup(FilterConfigSetup setup) { + filter_config_setup_ = setup; + return *this; + } + + TestType& set_bootstrap_source(BootstrapSource bootstrap_source) { + bootstrap_source_ = bootstrap_source; + return *this; + } + bool use_fake_resolver() const { return use_fake_resolver_; } bool enable_load_reporting() const { return enable_load_reporting_; } bool enable_rds_testing() const { return enable_rds_testing_; } bool use_v2() const { return use_v2_; } bool use_xds_credentials() const { return use_xds_credentials_; } + bool use_csds_streaming() const { return use_csds_streaming_; } + FilterConfigSetup filter_config_setup() const { return filter_config_setup_; } + BootstrapSource bootstrap_source() const { return bootstrap_source_; } std::string AsString() const { std::string retval = (use_fake_resolver_ ? "FakeResolver" : "XdsResolver"); @@ -1338,6 +1391,15 @@ class TestType { if (enable_load_reporting_) retval += "WithLoadReporting"; if (enable_rds_testing_) retval += "Rds"; if (use_xds_credentials_) retval += "XdsCreds"; + if (use_csds_streaming_) retval += "CsdsStreaming"; + if (filter_config_setup_ == kRouteOverride) { + retval += "FilterPerRouteOverride"; + } + if (bootstrap_source_ == kBootstrapFromFile) { + retval += "BootstrapFromFile"; + } else if (bootstrap_source_ == kBootstrapFromEnvVar) { + retval += "BootstrapFromEnvVar"; + } return retval; } @@ -1347,6 +1409,9 @@ class TestType { bool enable_rds_testing_ = false; bool use_v2_ = false; bool use_xds_credentials_ = false; + bool use_csds_streaming_ = false; + FilterConfigSetup filter_config_setup_ = kHTTPConnectionManagerOriginal; + BootstrapSource bootstrap_source_ = kBootstrapFromChannelArg; }; std::string ReadFile(const char* file_path) { @@ -1385,7 +1450,7 @@ class FakeCertificateProvider final : public grpc_tls_certificate_provider { if (!root_being_watched && !identity_being_watched) return; auto it = cert_data_map_.find(cert_name); if (it == cert_data_map_.end()) { - grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_COPIED_STRING( absl::StrCat("No certificates available for cert_name \"", cert_name, "\"") .c_str()); @@ -1446,7 +1511,7 @@ class FakeCertificateProviderFactory grpc_core::RefCountedPtr CreateCertificateProviderConfig(const grpc_core::Json& /*config_json*/, - grpc_error** /*error*/) override { + grpc_error_handle* /*error*/) override { return grpc_core::MakeRefCounted(name_); } @@ -1498,27 +1563,102 @@ std::shared_ptr CreateTlsFallbackCredentials() { return channel_creds; } -namespace { +// A No-op HTTP filter used for verifying parsing logic. +class NoOpHttpFilter : public grpc_core::XdsHttpFilterImpl { + public: + NoOpHttpFilter(std::string name, bool supported_on_clients, + bool supported_on_servers) + : name_(std::move(name)), + supported_on_clients_(supported_on_clients), + supported_on_servers_(supported_on_servers) {} -void* response_generator_arg_copy(void* p) { - auto* generator = static_cast(p); - generator->Ref().release(); - return p; -} + void PopulateSymtab(upb_symtab* /* symtab */) const override {} -void response_generator_arg_destroy(void* p) { - auto* generator = static_cast(p); - generator->Unref(); -} + absl::StatusOr + GenerateFilterConfig(upb_strview /* serialized_filter_config */, + upb_arena* /* arena */) const override { + return grpc_core::XdsHttpFilterImpl::FilterConfig{name_, grpc_core::Json()}; + } -int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); } + absl::StatusOr + GenerateFilterConfigOverride(upb_strview /*serialized_filter_config*/, + upb_arena* /*arena*/) const override { + return grpc_core::XdsHttpFilterImpl::FilterConfig{name_, grpc_core::Json()}; + } -const grpc_arg_pointer_vtable - kLogicalDnsClusterResolverResponseGeneratorVtable = { - response_generator_arg_copy, response_generator_arg_destroy, - response_generator_cmp}; + const grpc_channel_filter* channel_filter() const override { return nullptr; } -} // namespace + absl::StatusOr + GenerateServiceConfig( + const FilterConfig& /*hcm_filter_config*/, + const FilterConfig* /*filter_config_override*/) const override { + return grpc_core::XdsHttpFilterImpl::ServiceConfigJsonEntry{name_, ""}; + } + + bool IsSupportedOnClients() const override { return supported_on_clients_; } + + bool IsSupportedOnServers() const override { return supported_on_servers_; } + + private: + const std::string name_; + const bool supported_on_clients_; + const bool supported_on_servers_; +}; + +// There is slight difference between time fetched by GPR and by C++ system +// clock API. It's unclear if they are using the same syscall, but we do know +// GPR round the number at millisecond-level. This creates a 1ms difference, +// which could cause flake. +grpc_millis NowFromCycleCounter() { + gpr_cycle_counter now = gpr_get_cycle_counter(); + return grpc_cycle_counter_to_millis_round_up(now); +} + +// Returns the number of RPCs needed to pass error_tolerance at 99.99% chance. +// Rolling dices in drop/fault-injection generates a binomial distribution (if +// our code is not horribly wrong). Let's make "n" the number of samples, "p" +// the probabilty. If we have np>5 & n(1-p)>5, we can approximately treat the +// binomial distribution as a normal distribution. +// +// For normal distribution, we can easily look up how many standard deviation we +// need to reach 99.99%. Based on Wiki's table +// https://en.wikipedia.org/wiki/Standard_normal_table, we need 3.89 sigma +// (standard deviation) to cover the probability area of 99.99%. In another +// word, for a sample with size "n" probability "p" error-tolerance "k", we want +// the error always land within 3.89 sigma. The sigma of binominal distribution +// and be computed as sqrt(np(1-p)). Hence, we have the equation: +// +// kn <= 3.89 * sqrt(np(1-p)) +// +// E.g., with p=0.5 k=0.1, n >= 378; with p=0.5 k=0.05, n >= 1513; with p=0.5 +// k=0.01, n >= 37830. +size_t ComputeIdealNumRpcs(double p, double error_tolerance) { + GPR_ASSERT(p >= 0 && p <= 1); + size_t num_rpcs = + ceil(p * (1 - p) * 3.89 * 3.89 / error_tolerance / error_tolerance); + gpr_log(GPR_INFO, + "Sending %" PRIuPTR " RPCs for percentage=%.3f error_tolerance=%.3f", + num_rpcs, p, error_tolerance); + return num_rpcs; +} + +// Channel arg pointer vtable for storing xDS channel args in the parent +// channel's channel args. +void* ChannelArgsArgCopy(void* p) { + auto* args = static_cast(p); + return grpc_channel_args_copy(args); +} +void ChannelArgsArgDestroy(void* p) { + auto* args = static_cast(p); + grpc_channel_args_destroy(args); +} +int ChannelArgsArgCmp(void* a, void* b) { + auto* args_a = static_cast(a); + auto* args_b = static_cast(b); + return grpc_channel_args_compare(args_a, args_b); +} +const grpc_arg_pointer_vtable kChannelArgsArgVtable = { + ChannelArgsArgCopy, ChannelArgsArgDestroy, ChannelArgsArgCmp}; class XdsEnd2endTest : public ::testing::TestWithParam { protected: @@ -1533,24 +1673,14 @@ class XdsEnd2endTest : public ::testing::TestWithParam { // balancers that it needs, so that we aren't wasting resources. XdsEnd2endTest(size_t num_backends, size_t num_balancers, int client_load_reporting_interval_seconds = 100, - bool use_xds_enabled_server = false, - bool bootstrap_contents_from_env_var = false) + bool use_xds_enabled_server = false) : num_backends_(num_backends), num_balancers_(num_balancers), client_load_reporting_interval_seconds_( client_load_reporting_interval_seconds), - use_xds_enabled_server_(use_xds_enabled_server), - bootstrap_contents_from_env_var_(bootstrap_contents_from_env_var) {} + use_xds_enabled_server_(use_xds_enabled_server) {} void SetUp() override { - if (bootstrap_contents_from_env_var_) { - gpr_setenv("GRPC_XDS_BOOTSTRAP_CONFIG", - GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3); - } else { - gpr_setenv("GRPC_XDS_BOOTSTRAP", GetParam().use_v2() - ? g_bootstrap_file_v2 - : g_bootstrap_file_v3); - } bool localhost_resolves_to_ipv4 = false; bool localhost_resolves_to_ipv6 = false; grpc_core::LocalhostResolves(&localhost_resolves_to_ipv4, @@ -1560,10 +1690,12 @@ class XdsEnd2endTest : public ::testing::TestWithParam { // Construct LDS resource. default_listener_.set_name(kServerName); HttpConnectionManager http_connection_manager; - auto* filter = http_connection_manager.add_http_filters(); - filter->set_name("router"); - filter->mutable_typed_config()->PackFrom( - envoy::extensions::filters::http::router::v3::Router()); + if (!GetParam().use_v2()) { + auto* filter = http_connection_manager.add_http_filters(); + filter->set_name("router"); + filter->mutable_typed_config()->PackFrom( + envoy::extensions::filters::http::router::v3::Router()); + } default_listener_.mutable_api_listener()->mutable_api_listener()->PackFrom( http_connection_manager); // Construct RDS resource. @@ -1585,28 +1717,29 @@ class XdsEnd2endTest : public ::testing::TestWithParam { } // Start the load balancers. for (size_t i = 0; i < num_balancers_; ++i) { - balancers_.emplace_back( - new BalancerServerThread(GetParam().enable_load_reporting() - ? client_load_reporting_interval_seconds_ - : 0)); + balancers_.emplace_back(new BalancerServerThread( + this, GetParam().enable_load_reporting() + ? client_load_reporting_interval_seconds_ + : 0)); balancers_.back()->Start(); // Initialize resources. SetListenerAndRouteConfiguration(i, default_listener_, default_route_config_); balancers_.back()->ads_service()->SetCdsResource(default_cluster_); } - // Initialize XdsClient state. - response_generator_ = + // Create fake resolver response generators used by client. + if (GetParam().use_fake_resolver()) { + response_generator_ = + grpc_core::MakeRefCounted(); + } + logical_dns_cluster_resolver_response_generator_ = grpc_core::MakeRefCounted(); - // Inject xDS channel response generator. lb_channel_response_generator_ = grpc_core::MakeRefCounted(); + // Construct channel args for XdsClient. xds_channel_args_to_add_.emplace_back( grpc_core::FakeResolverResponseGenerator::MakeChannelArg( lb_channel_response_generator_.get())); - // Inject xDS logical cluster resolver response generator. - logical_dns_cluster_resolver_response_generator_ = - grpc_core::MakeRefCounted(); if (xds_resource_does_not_exist_timeout_ms_ > 0) { xds_channel_args_to_add_.emplace_back(grpc_channel_arg_integer_create( const_cast(GRPC_ARG_XDS_RESOURCE_DOES_NOT_EXIST_TIMEOUT_MS), @@ -1614,18 +1747,36 @@ class XdsEnd2endTest : public ::testing::TestWithParam { } xds_channel_args_.num_args = xds_channel_args_to_add_.size(); xds_channel_args_.args = xds_channel_args_to_add_.data(); - grpc_core::internal::SetXdsChannelArgsForTest(&xds_channel_args_); - // Make sure each test creates a new XdsClient instance rather than - // reusing the one from the previous test. This avoids spurious failures - // caused when a load reporting test runs after a non-load reporting test - // and the XdsClient is still talking to the old LRS server, which fails - // because it's not expecting the client to connect. It also - // ensures that each test can independently set the global channel - // args for the xDS channel. - grpc_core::internal::UnsetGlobalXdsClientForTest(); + // Initialize XdsClient state. + // TODO(roth): Consider changing this to dynamically generate the + // bootstrap config in each individual test instead of hard-coding + // the contents here. That would allow us to use an ipv4: or ipv6: + // URI for the xDS server instead of using the fake resolver. + if (GetParam().bootstrap_source() == TestType::kBootstrapFromEnvVar) { + gpr_setenv("GRPC_XDS_BOOTSTRAP_CONFIG", + GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3); + } else if (GetParam().bootstrap_source() == TestType::kBootstrapFromFile) { + gpr_setenv("GRPC_XDS_BOOTSTRAP", GetParam().use_v2() + ? g_bootstrap_file_v2 + : g_bootstrap_file_v3); + } + if (GetParam().bootstrap_source() != TestType::kBootstrapFromChannelArg) { + // If getting bootstrap from channel arg, we'll pass these args in + // via the parent channel args in CreateChannel() instead. + grpc_core::internal::SetXdsChannelArgsForTest(&xds_channel_args_); + // Make sure each test creates a new XdsClient instance rather than + // reusing the one from the previous test. This avoids spurious failures + // caused when a load reporting test runs after a non-load reporting test + // and the XdsClient is still talking to the old LRS server, which fails + // because it's not expecting the client to connect. It also + // ensures that each test can independently set the global channel + // args for the xDS channel. + grpc_core::internal::UnsetGlobalXdsClientForTest(); + } // Start the backends. for (size_t i = 0; i < num_backends_; ++i) { - backends_.emplace_back(new BackendServerThread(use_xds_enabled_server_)); + backends_.emplace_back( + new BackendServerThread(this, use_xds_enabled_server_)); backends_.back()->Start(); } // Create channel and stub. @@ -1668,7 +1819,8 @@ class XdsEnd2endTest : public ::testing::TestWithParam { std::shared_ptr CreateChannel( int failover_timeout = 0, const char* server_name = kServerName, - grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) { + grpc_core::FakeResolverResponseGenerator* response_generator = nullptr, + grpc_channel_args* xds_channel_args = nullptr) { ChannelArguments args; if (failover_timeout > 0) { args.SetInt(GRPC_ARG_PRIORITY_FAILOVER_TIMEOUT_MS, failover_timeout); @@ -1679,13 +1831,25 @@ class XdsEnd2endTest : public ::testing::TestWithParam { if (response_generator == nullptr) { response_generator = response_generator_.get(); } - args.SetPointer(GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, - response_generator); + args.SetPointerWithVtable( + GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR, response_generator, + &grpc_core::FakeResolverResponseGenerator::kChannelArgPointerVtable); + } + if (GetParam().bootstrap_source() == TestType::kBootstrapFromChannelArg) { + // We're getting the bootstrap from a channel arg, so we do the + // same thing for the response generator to use for the xDS + // channel and the xDS resource-does-not-exist timeout value. + args.SetString(GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG, + GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3); + if (xds_channel_args == nullptr) xds_channel_args = &xds_channel_args_; + args.SetPointerWithVtable( + GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS, + xds_channel_args, &kChannelArgsArgVtable); } args.SetPointerWithVtable( GRPC_ARG_XDS_LOGICAL_DNS_CLUSTER_FAKE_RESOLVER_RESPONSE_GENERATOR, logical_dns_cluster_resolver_response_generator_.get(), - &kLogicalDnsClusterResolverResponseGeneratorVtable); + &grpc_core::FakeResolverResponseGenerator::kChannelArgPointerVtable); std::string uri = absl::StrCat( GetParam().use_fake_resolver() ? "fake" : "xds", ":///", server_name); std::shared_ptr channel_creds = @@ -1715,6 +1879,8 @@ class XdsEnd2endTest : public ::testing::TestWithParam { bool wait_for_ready = false; bool server_fail = false; std::vector> metadata; + int client_cancel_after_us = 0; + bool skip_cancelled_check = false; RpcOptions() {} @@ -1743,11 +1909,45 @@ class XdsEnd2endTest : public ::testing::TestWithParam { return *this; } + RpcOptions& set_skip_cancelled_check(bool rpc_skip_cancelled_check) { + skip_cancelled_check = rpc_skip_cancelled_check; + return *this; + } + RpcOptions& set_metadata( std::vector> rpc_metadata) { metadata = std::move(rpc_metadata); return *this; } + + RpcOptions& set_client_cancel_after_us(int rpc_client_cancel_after_us) { + client_cancel_after_us = rpc_client_cancel_after_us; + return *this; + } + + // Populates context and request. + void SetupRpc(ClientContext* context, EchoRequest* request) const { + for (const auto& item : metadata) { + context->AddMetadata(item.first, item.second); + } + if (timeout_ms != 0) { + context->set_deadline( + grpc_timeout_milliseconds_to_deadline(timeout_ms)); + } + if (wait_for_ready) context->set_wait_for_ready(true); + request->set_message(kRequestMessage); + if (server_fail) { + request->mutable_param()->mutable_expected_error()->set_code( + GRPC_STATUS_FAILED_PRECONDITION); + } + if (client_cancel_after_us != 0) { + request->mutable_param()->set_client_cancel_after_us( + client_cancel_after_us); + } + if (skip_cancelled_check) { + request->mutable_param()->set_skip_cancelled_check(true); + } + } }; template @@ -1762,6 +1962,7 @@ class XdsEnd2endTest : public ::testing::TestWithParam { case METHOD_ECHO2: return (*stub)->Echo2(context, request, response); } + GPR_UNREACHABLE_CODE(); } void ResetBackendCounters(size_t start_index = 0, size_t stop_index = 0) { @@ -1773,26 +1974,34 @@ class XdsEnd2endTest : public ::testing::TestWithParam { } } + bool SeenBackend(size_t backend_idx, + const RpcService rpc_service = SERVICE_ECHO) { + switch (rpc_service) { + case SERVICE_ECHO: + if (backends_[backend_idx]->backend_service()->request_count() == 0) { + return false; + } + break; + case SERVICE_ECHO1: + if (backends_[backend_idx]->backend_service1()->request_count() == 0) { + return false; + } + break; + case SERVICE_ECHO2: + if (backends_[backend_idx]->backend_service2()->request_count() == 0) { + return false; + } + break; + } + return true; + } + bool SeenAllBackends(size_t start_index = 0, size_t stop_index = 0, - const RpcOptions& rpc_options = RpcOptions()) { + const RpcService rpc_service = SERVICE_ECHO) { if (stop_index == 0) stop_index = backends_.size(); for (size_t i = start_index; i < stop_index; ++i) { - switch (rpc_options.service) { - case SERVICE_ECHO: - if (backends_[i]->backend_service()->request_count() == 0) { - return false; - } - break; - case SERVICE_ECHO1: - if (backends_[i]->backend_service1()->request_count() == 0) { - return false; - } - break; - case SERVICE_ECHO2: - if (backends_[i]->backend_service2()->request_count() == 0) { - return false; - } - break; + if (!SeenBackend(i, rpc_service)) { + return false; } } return true; @@ -1800,12 +2009,14 @@ class XdsEnd2endTest : public ::testing::TestWithParam { void SendRpcAndCount(int* num_total, int* num_ok, int* num_failure, int* num_drops, - const RpcOptions& rpc_options = RpcOptions()) { + const RpcOptions& rpc_options = RpcOptions(), + const char* drop_error_message = + "Call dropped by load balancing policy") { const Status status = SendRpc(rpc_options); if (status.ok()) { ++*num_ok; } else { - if (status.error_message() == "Call dropped by load balancing policy") { + if (status.error_message() == drop_error_message) { ++*num_drops; } else { ++*num_failure; @@ -1814,39 +2025,58 @@ class XdsEnd2endTest : public ::testing::TestWithParam { ++*num_total; } + struct WaitForBackendOptions { + bool reset_counters = true; + bool allow_failures = false; + + WaitForBackendOptions() {} + + WaitForBackendOptions& set_reset_counters(bool enable) { + reset_counters = enable; + return *this; + } + + WaitForBackendOptions& set_allow_failures(bool enable) { + allow_failures = enable; + return *this; + } + }; + std::tuple WaitForAllBackends( - size_t start_index = 0, size_t stop_index = 0, bool reset_counters = true, - const RpcOptions& rpc_options = RpcOptions(), - bool allow_failures = false) { + size_t start_index = 0, size_t stop_index = 0, + const WaitForBackendOptions& wait_options = WaitForBackendOptions(), + const RpcOptions& rpc_options = RpcOptions()) { int num_ok = 0; int num_failure = 0; int num_drops = 0; int num_total = 0; - while (!SeenAllBackends(start_index, stop_index, rpc_options)) { + while (!SeenAllBackends(start_index, stop_index, rpc_options.service)) { SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_drops, rpc_options); } - if (reset_counters) ResetBackendCounters(); + if (wait_options.reset_counters) ResetBackendCounters(); gpr_log(GPR_INFO, "Performed %d warm up requests against the backends. " "%d succeeded, %d failed, %d dropped.", num_total, num_ok, num_failure, num_drops); - if (!allow_failures) EXPECT_EQ(num_failure, 0); + if (!wait_options.allow_failures) EXPECT_EQ(num_failure, 0); return std::make_tuple(num_ok, num_failure, num_drops); } - void WaitForBackend(size_t backend_idx, bool reset_counters = true, - bool require_success = false) { + void WaitForBackend( + size_t backend_idx, + const WaitForBackendOptions& wait_options = WaitForBackendOptions(), + const RpcOptions& rpc_options = RpcOptions()) { gpr_log(GPR_INFO, "========= WAITING FOR BACKEND %lu ==========", static_cast(backend_idx)); do { - Status status = SendRpc(); - if (require_success) { + Status status = SendRpc(rpc_options); + if (!wait_options.allow_failures) { EXPECT_TRUE(status.ok()) << "code=" << status.error_code() << " message=" << status.error_message(); } - } while (backends_[backend_idx]->backend_service()->request_count() == 0); - if (reset_counters) ResetBackendCounters(); + } while (!SeenBackend(backend_idx, rpc_options.service)); + if (wait_options.reset_counters) ResetBackendCounters(); gpr_log(GPR_INFO, "========= BACKEND %lu READY ==========", static_cast(backend_idx)); } @@ -1872,14 +2102,14 @@ class XdsEnd2endTest : public ::testing::TestWithParam { grpc_core::ExecCtx exec_ctx; grpc_core::Resolver::Result result; result.addresses = CreateAddressListFromPortList(ports); - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; const char* service_config_json = GetParam().enable_load_reporting() ? kDefaultServiceConfig : kDefaultServiceConfigWithoutLoadReporting; result.service_config = grpc_core::ServiceConfig::Create(nullptr, service_config_json, &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_NE(result.service_config.get(), nullptr); if (response_generator == nullptr) { response_generator = response_generator_.get(); @@ -1889,26 +2119,29 @@ class XdsEnd2endTest : public ::testing::TestWithParam { void SetNextResolutionForLbChannelAllBalancers( const char* service_config_json = nullptr, - const char* expected_targets = nullptr) { + const char* expected_targets = nullptr, + grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) { std::vector ports; for (size_t i = 0; i < balancers_.size(); ++i) { ports.emplace_back(balancers_[i]->port()); } - SetNextResolutionForLbChannel(ports, service_config_json, expected_targets); + SetNextResolutionForLbChannel(ports, service_config_json, expected_targets, + response_generator); } - void SetNextResolutionForLbChannel(const std::vector& ports, - const char* service_config_json = nullptr, - const char* expected_targets = nullptr) { + void SetNextResolutionForLbChannel( + const std::vector& ports, const char* service_config_json = nullptr, + const char* expected_targets = nullptr, + grpc_core::FakeResolverResponseGenerator* response_generator = nullptr) { grpc_core::ExecCtx exec_ctx; grpc_core::Resolver::Result result; result.addresses = CreateAddressListFromPortList(ports); if (service_config_json != nullptr) { - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; result.service_config = grpc_core::ServiceConfig::Create( nullptr, service_config_json, &error); ASSERT_NE(result.service_config.get(), nullptr); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); } if (expected_targets != nullptr) { grpc_arg expected_targets_arg = grpc_channel_arg_string_create( @@ -1917,7 +2150,10 @@ class XdsEnd2endTest : public ::testing::TestWithParam { result.args = grpc_channel_args_copy_and_add(nullptr, &expected_targets_arg, 1); } - lb_channel_response_generator_->SetResponse(std::move(result)); + if (response_generator == nullptr) { + response_generator = lb_channel_response_generator_.get(); + } + response_generator->SetResponse(std::move(result)); } void SetNextReresolutionResponse(const std::vector& ports) { @@ -1927,8 +2163,8 @@ class XdsEnd2endTest : public ::testing::TestWithParam { response_generator_->SetReresolutionResponse(std::move(result)); } - const std::vector GetBackendPorts(size_t start_index = 0, - size_t stop_index = 0) const { + std::vector GetBackendPorts(size_t start_index = 0, + size_t stop_index = 0) const { if (stop_index == 0) stop_index = backends_.size(); std::vector backend_ports; for (size_t i = start_index; i < stop_index; ++i) { @@ -1941,21 +2177,9 @@ class XdsEnd2endTest : public ::testing::TestWithParam { EchoResponse* response = nullptr) { const bool local_response = (response == nullptr); if (local_response) response = new EchoResponse; - EchoRequest request; ClientContext context; - for (const auto& metadata : rpc_options.metadata) { - context.AddMetadata(metadata.first, metadata.second); - } - if (rpc_options.timeout_ms != 0) { - context.set_deadline( - grpc_timeout_milliseconds_to_deadline(rpc_options.timeout_ms)); - } - if (rpc_options.wait_for_ready) context.set_wait_for_ready(true); - request.set_message(kRequestMessage); - if (rpc_options.server_fail) { - request.mutable_param()->mutable_expected_error()->set_code( - GRPC_STATUS_FAILED_PRECONDITION); - } + EchoRequest request; + rpc_options.SetupRpc(&context, &request); Status status; switch (rpc_options.service) { case SERVICE_ECHO: @@ -2012,6 +2236,23 @@ class XdsEnd2endTest : public ::testing::TestWithParam { return listener; } + std::vector + CreateEndpointsForBackends(size_t start_index = 0, size_t stop_index = 0, + HealthStatus health_status = HealthStatus::UNKNOWN, + int lb_weight = 1) { + if (stop_index == 0) stop_index = backends_.size(); + std::vector endpoints; + for (size_t i = start_index; i < stop_index; ++i) { + endpoints.emplace_back(backends_[i]->port(), health_status, lb_weight); + } + return endpoints; + } + + AdsServiceImpl::EdsResourceArgs::Endpoint MakeNonExistantEndpoint() { + return AdsServiceImpl::EdsResourceArgs::Endpoint( + grpc_pick_unused_port_or_die()); + } + ClusterLoadAssignment BuildEdsResource( const AdsServiceImpl::EdsResourceArgs& args, const char* eds_service_name = kDefaultEdsServiceName) { @@ -2024,12 +2265,12 @@ class XdsEnd2endTest : public ::testing::TestWithParam { endpoints->mutable_locality()->set_region(kDefaultLocalityRegion); endpoints->mutable_locality()->set_zone(kDefaultLocalityZone); endpoints->mutable_locality()->set_sub_zone(locality.sub_zone); - for (size_t i = 0; i < locality.ports.size(); ++i) { - const int& port = locality.ports[i]; + for (size_t i = 0; i < locality.endpoints.size(); ++i) { + const int& port = locality.endpoints[i].port; auto* lb_endpoints = endpoints->add_lb_endpoints(); - if (locality.health_statuses.size() > i && - locality.health_statuses[i] != HealthStatus::UNKNOWN) { - lb_endpoints->set_health_status(locality.health_statuses[i]); + if (locality.endpoints.size() > i && + locality.endpoints[i].health_status != HealthStatus::UNKNOWN) { + lb_endpoints->set_health_status(locality.endpoints[i].health_status); } auto* endpoint = lb_endpoints->mutable_endpoint(); auto* address = endpoint->mutable_address(); @@ -2100,10 +2341,37 @@ class XdsEnd2endTest : public ::testing::TestWithParam { } protected: + class XdsServingStatusNotifier + : public grpc::experimental::XdsServerServingStatusNotifierInterface { + public: + void OnServingStatusUpdate(std::string uri, grpc::Status status) override { + grpc_core::MutexLock lock(&mu_); + status_map[uri] = status; + cond_.Signal(); + } + + void WaitOnServingStatusChange(std::string uri, + grpc::StatusCode expected_status) { + grpc_core::MutexLock lock(&mu_); + std::map::iterator it; + while ((it = status_map.find(uri)) == status_map.end() || + it->second.error_code() != expected_status) { + cond_.Wait(&mu_); + } + } + + private: + grpc_core::Mutex mu_; + grpc_core::CondVar cond_; + std::map status_map; + }; + class ServerThread { public: - explicit ServerThread(bool use_xds_enabled_server = false) - : port_(grpc_pick_unused_port_or_die()), + explicit ServerThread(XdsEnd2endTest* test_obj, + bool use_xds_enabled_server = false) + : test_obj_(test_obj), + port_(grpc_pick_unused_port_or_die()), use_xds_enabled_server_(use_xds_enabled_server) {} virtual ~ServerThread(){}; @@ -2131,6 +2399,12 @@ class XdsEnd2endTest : public ::testing::TestWithParam { server_address << "localhost:" << port_; if (use_xds_enabled_server_) { experimental::XdsServerBuilder builder; + if (GetParam().bootstrap_source() == + TestType::kBootstrapFromChannelArg) { + builder.SetOption( + absl::make_unique(test_obj_)); + } + builder.set_status_notifier(¬ifier_); builder.AddListeningPort(server_address.str(), Credentials()); RegisterAllServices(&builder); server_ = builder.BuildAndStart(); @@ -2162,15 +2436,42 @@ class XdsEnd2endTest : public ::testing::TestWithParam { bool use_xds_enabled_server() const { return use_xds_enabled_server_; } + XdsServingStatusNotifier* notifier() { return ¬ifier_; } + private: + class XdsChannelArgsServerBuilderOption + : public ::grpc::ServerBuilderOption { + public: + explicit XdsChannelArgsServerBuilderOption(XdsEnd2endTest* test_obj) + : test_obj_(test_obj) {} + + void UpdateArguments(grpc::ChannelArguments* args) override { + args->SetString( + GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_BOOTSTRAP_CONFIG, + GetParam().use_v2() ? kBootstrapFileV2 : kBootstrapFileV3); + args->SetPointerWithVtable( + GRPC_ARG_TEST_ONLY_DO_NOT_USE_IN_PROD_XDS_CLIENT_CHANNEL_ARGS, + &test_obj_->xds_channel_args_, &kChannelArgsArgVtable); + } + + void UpdatePlugins( + std::vector>* /*plugins*/) + override {} + + private: + XdsEnd2endTest* test_obj_; + }; + virtual void RegisterAllServices(ServerBuilder* builder) = 0; virtual void StartAllServices() = 0; virtual void ShutdownAllServices() = 0; virtual const char* Type() = 0; + XdsEnd2endTest* test_obj_; const int port_; std::unique_ptr server_; + XdsServingStatusNotifier notifier_; std::unique_ptr thread_; bool running_ = false; const bool use_xds_enabled_server_; @@ -2178,8 +2479,9 @@ class XdsEnd2endTest : public ::testing::TestWithParam { class BackendServerThread : public ServerThread { public: - explicit BackendServerThread(bool use_xds_enabled_server) - : ServerThread(use_xds_enabled_server) {} + explicit BackendServerThread(XdsEnd2endTest* test_obj, + bool use_xds_enabled_server) + : ServerThread(test_obj, use_xds_enabled_server) {} BackendServiceImpl<::grpc::testing::EchoTestService::Service>* backend_service() { @@ -2253,8 +2555,10 @@ class XdsEnd2endTest : public ::testing::TestWithParam { class BalancerServerThread : public ServerThread { public: - explicit BalancerServerThread(int client_load_reporting_interval = 0) - : ads_service_(new AdsServiceImpl()), + explicit BalancerServerThread(XdsEnd2endTest* test_obj, + int client_load_reporting_interval = 0) + : ServerThread(test_obj), + ads_service_(new AdsServiceImpl()), lrs_service_(new LrsServiceImpl(client_load_reporting_interval)) {} AdsServiceImpl* ads_service() { return ads_service_.get(); } @@ -2284,28 +2588,98 @@ class XdsEnd2endTest : public ::testing::TestWithParam { std::shared_ptr lrs_service_; }; +#ifndef DISABLED_XDS_PROTO_IN_CC + class AdminServerThread : public ServerThread { + public: + explicit AdminServerThread(XdsEnd2endTest* test_obj) + : ServerThread(test_obj) {} + + private: + void RegisterAllServices(ServerBuilder* builder) override { + builder->RegisterService(&csds_service_); + } + void StartAllServices() override {} + void ShutdownAllServices() override {} + + const char* Type() override { return "Admin"; } + + grpc::xds::experimental::ClientStatusDiscoveryService csds_service_; + }; +#endif // DISABLED_XDS_PROTO_IN_CC + class LongRunningRpc { public: - void StartRpc(grpc::testing::EchoTestService::Stub* stub) { - sender_thread_ = std::thread([this, stub]() { - EchoResponse response; + void StartRpc(grpc::testing::EchoTestService::Stub* stub, + const RpcOptions& rpc_options = + RpcOptions().set_timeout_ms(0).set_client_cancel_after_us( + 1 * 1000 * 1000)) { + sender_thread_ = std::thread([this, stub, rpc_options]() { EchoRequest request; - request.mutable_param()->set_client_cancel_after_us(1 * 1000 * 1000); - request.set_message(kRequestMessage); - (void)stub->Echo(&context_, request, &response); + EchoResponse response; + rpc_options.SetupRpc(&context_, &request); + status_ = stub->Echo(&context_, request, &response); }); } void CancelRpc() { context_.TryCancel(); - sender_thread_.join(); + if (sender_thread_.joinable()) sender_thread_.join(); + } + + Status GetStatus() { + if (sender_thread_.joinable()) sender_thread_.join(); + return status_; } private: std::thread sender_thread_; ClientContext context_; + Status status_; }; + struct ConcurrentRpc { + ClientContext context; + Status status; + grpc_millis elapsed_time; + EchoResponse response; + }; + + std::vector SendConcurrentRpcs( + grpc::testing::EchoTestService::Stub* stub, size_t num_rpcs, + const RpcOptions& rpc_options) { + // Variables for RPCs. + std::vector rpcs(num_rpcs); + EchoRequest request; + // Variables for synchronization + absl::Mutex mu; + absl::CondVar cv; + size_t completed = 0; + // Set-off callback RPCs + for (size_t i = 0; i < num_rpcs; i++) { + ConcurrentRpc* rpc = &rpcs[i]; + rpc_options.SetupRpc(&rpc->context, &request); + grpc_millis t0 = NowFromCycleCounter(); + stub->experimental_async()->Echo( + &rpc->context, &request, &rpc->response, + [rpc, &mu, &completed, &cv, num_rpcs, t0](Status s) { + rpc->status = s; + rpc->elapsed_time = NowFromCycleCounter() - t0; + bool done; + { + absl::MutexLock lock(&mu); + done = (++completed) == num_rpcs; + } + if (done) cv.Signal(); + }); + } + { + absl::MutexLock lock(&mu); + cv.Wait(&mu); + } + EXPECT_EQ(completed, num_rpcs); + return rpcs; + } + const size_t num_backends_; const size_t num_balancers_; const int client_load_reporting_interval_seconds_; @@ -2345,7 +2719,7 @@ TEST_P(BasicTest, Vanilla) { SetNextResolutionForLbChannelAllBalancers(); const size_t kNumRpcsPerAddress = 100; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -2371,12 +2745,11 @@ TEST_P(BasicTest, IgnoresUnhealthyEndpoints) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); const size_t kNumRpcsPerAddress = 100; + auto endpoints = CreateEndpointsForBackends(); + endpoints[0].health_status = HealthStatus::DRAINING; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", - GetBackendPorts(), - kDefaultLocalityWeight, - kDefaultLocalityPriority, - {HealthStatus::DRAINING}}, + {"locality0", std::move(endpoints), kDefaultLocalityWeight, + kDefaultLocalityPriority}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -2399,9 +2772,10 @@ TEST_P(BasicTest, SameBackendListedMultipleTimes) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Same backend listed twice. - std::vector ports(2, backends_[0]->port()); + auto endpoints = CreateEndpointsForBackends(0, 1); + endpoints.push_back(endpoints.front()); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", ports}, + {"locality0", endpoints}, }); const size_t kNumRpcsPerAddress = 10; balancers_[0]->ads_service()->SetEdsResource( @@ -2409,9 +2783,9 @@ TEST_P(BasicTest, SameBackendListedMultipleTimes) { // We need to wait for the backend to come online. WaitForBackend(0); // Send kNumRpcsPerAddress RPCs per server. - CheckRpcSendOk(kNumRpcsPerAddress * ports.size()); + CheckRpcSendOk(kNumRpcsPerAddress * endpoints.size()); // Backend should have gotten 20 requests. - EXPECT_EQ(kNumRpcsPerAddress * ports.size(), + EXPECT_EQ(kNumRpcsPerAddress * endpoints.size(), backends_[0]->backend_service()->request_count()); // And they should have come from a single client port, because of // subchannel sharing. @@ -2433,7 +2807,7 @@ TEST_P(BasicTest, InitiallyEmptyServerlist) { BuildEdsResource(args, DefaultEdsServiceName())); // Send non-empty serverlist only after kServerlistDelayMs. args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); std::thread delayed_resource_setter(std::bind( &BasicTest::SetEdsResourceWithDelay, this, 0, @@ -2456,20 +2830,25 @@ TEST_P(BasicTest, InitiallyEmptyServerlist) { // Tests that RPCs will fail with UNAVAILABLE instead of DEADLINE_EXCEEDED if // all the servers are unreachable. TEST_P(BasicTest, AllServersUnreachableFailFast) { + // Set Rpc timeout to 5 seconds to ensure there is enough time + // for communication with the xDS server to take place upon test start up. + const uint32_t kRpcTimeoutMs = 5000; SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); const size_t kNumUnreachableServers = 5; - std::vector ports; + std::vector endpoints; for (size_t i = 0; i < kNumUnreachableServers; ++i) { - ports.push_back(grpc_pick_unused_port_or_die()); + endpoints.emplace_back(grpc_pick_unused_port_or_die()); } AdsServiceImpl::EdsResourceArgs args({ - {"locality0", ports}, + {"locality0", endpoints}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); - const Status status = SendRpc(); - // The error shouldn't be DEADLINE_EXCEEDED. + const Status status = SendRpc(RpcOptions().set_timeout_ms(kRpcTimeoutMs)); + // The error shouldn't be DEADLINE_EXCEEDED because timeout is set to 5 + // seconds, and we should disocver in that time that the target backend is + // down. EXPECT_EQ(StatusCode::UNAVAILABLE, status.error_code()); } @@ -2479,7 +2858,7 @@ TEST_P(BasicTest, BackendsRestart) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -2506,7 +2885,7 @@ TEST_P(BasicTest, IgnoresDuplicateUpdates) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -2535,7 +2914,7 @@ TEST_P(XdsResolverOnlyTest, ResourceTypeVersionPersistsAcrossStreamRestarts) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // Wait for backends to come online. @@ -2550,7 +2929,7 @@ TEST_P(XdsResolverOnlyTest, ResourceTypeVersionPersistsAcrossStreamRestarts) { // Update backend, just so we can be sure that the client has // reconnected to the balancer. AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args2)); // Restart balancer. @@ -2566,14 +2945,14 @@ TEST_P(XdsResolverOnlyTest, ChangeClusters) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 2)}, + {"locality0", CreateEndpointsForBackends(0, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // We need to wait for all backends to come online. WaitForAllBackends(0, 2); // Populate new EDS resource. AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 4)}, + {"locality0", CreateEndpointsForBackends(2, 4)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args2, kNewEdsServiceName)); @@ -2601,7 +2980,7 @@ TEST_P(XdsResolverOnlyTest, ClusterRemoved) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // We need to wait for all backends to come online. @@ -2637,7 +3016,7 @@ TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 2)}, + {"locality0", CreateEndpointsForBackends(0, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // We need to wait for all backends to come online. @@ -2651,7 +3030,7 @@ TEST_P(XdsResolverOnlyTest, RestartsRequestsUponReconnection) { CheckRpcSendOk(100); // Populate new EDS resource. AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 4)}, + {"locality0", CreateEndpointsForBackends(2, 4)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args2, kNewEdsServiceName)); @@ -2684,7 +3063,7 @@ TEST_P(XdsResolverOnlyTest, DefaultRouteSpecifiesSlashPrefix) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // We need to wait for all backends to come online. @@ -2692,13 +3071,12 @@ TEST_P(XdsResolverOnlyTest, DefaultRouteSpecifiesSlashPrefix) { } TEST_P(XdsResolverOnlyTest, CircuitBreaking) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_CIRCUIT_BREAKING", "true"); constexpr size_t kMaxConcurrentRequests = 10; SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // Update CDS resource to set max concurrent request. @@ -2734,15 +3112,13 @@ TEST_P(XdsResolverOnlyTest, CircuitBreaking) { // Make sure RPCs go to the correct backend: EXPECT_EQ(kMaxConcurrentRequests + 1, backends_[0]->backend_service()->request_count()); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_CIRCUIT_BREAKING"); } TEST_P(XdsResolverOnlyTest, CircuitBreakingMultipleChannelsShareCallCounter) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_CIRCUIT_BREAKING", "true"); constexpr size_t kMaxConcurrentRequests = 10; // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // Update CDS resource to set max concurrent request. @@ -2755,14 +3131,21 @@ TEST_P(XdsResolverOnlyTest, CircuitBreakingMultipleChannelsShareCallCounter) { // Create second channel. auto response_generator2 = grpc_core::MakeRefCounted(); + auto lb_response_generator2 = + grpc_core::MakeRefCounted(); + grpc_arg xds_arg = grpc_core::FakeResolverResponseGenerator::MakeChannelArg( + lb_response_generator2.get()); + grpc_channel_args xds_channel_args2 = {1, &xds_arg}; auto channel2 = CreateChannel( /*failover_timeout=*/0, /*server_name=*/kServerName, - response_generator2.get()); + response_generator2.get(), &xds_channel_args2); auto stub2 = grpc::testing::EchoTestService::NewStub(channel2); // Set resolution results for both channels and for the xDS channel. SetNextResolution({}); SetNextResolution({}, response_generator2.get()); SetNextResolutionForLbChannelAllBalancers(); + SetNextResolutionForLbChannelAllBalancers(nullptr, nullptr, + lb_response_generator2.get()); // Send exactly max_concurrent_requests long RPCs, alternating between // the two channels. LongRunningRpc rpcs[kMaxConcurrentRequests]; @@ -2790,48 +3173,11 @@ TEST_P(XdsResolverOnlyTest, CircuitBreakingMultipleChannelsShareCallCounter) { // Make sure RPCs go to the correct backend: EXPECT_EQ(kMaxConcurrentRequests + 1, backends_[0]->backend_service()->request_count()); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_CIRCUIT_BREAKING"); } -TEST_P(XdsResolverOnlyTest, CircuitBreakingDisabled) { - constexpr size_t kMaxConcurrentRequests = 10; - SetNextResolution({}); - SetNextResolutionForLbChannelAllBalancers(); - // Populate new EDS resources. - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, - }); - balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); - // Update CDS resource to set max concurrent request. - CircuitBreakers circuit_breaks; - Cluster cluster = default_cluster_; - auto* threshold = cluster.mutable_circuit_breakers()->add_thresholds(); - threshold->set_priority(RoutingPriority::DEFAULT); - threshold->mutable_max_requests()->set_value(kMaxConcurrentRequests); - balancers_[0]->ads_service()->SetCdsResource(cluster); - // Send exactly max_concurrent_requests long RPCs. - LongRunningRpc rpcs[kMaxConcurrentRequests]; - for (size_t i = 0; i < kMaxConcurrentRequests; ++i) { - rpcs[i].StartRpc(stub_.get()); - } - // Wait for all RPCs to be in flight. - while (backends_[0]->backend_service()->RpcsWaitingForClientCancel() < - kMaxConcurrentRequests) { - gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), - gpr_time_from_micros(1 * 1000, GPR_TIMESPAN))); - } - // Sending a RPC now should not fail as circuit breaking is disabled. - Status status = SendRpc(); - EXPECT_TRUE(status.ok()); - for (size_t i = 0; i < kMaxConcurrentRequests; ++i) { - rpcs[i].CancelRpc(); - } - // Make sure RPCs go to the correct backend: - EXPECT_EQ(kMaxConcurrentRequests + 1, - backends_[0]->backend_service()->request_count()); -} +using GlobalXdsClientTest = BasicTest; -TEST_P(XdsResolverOnlyTest, MultipleChannelsShareXdsClient) { +TEST_P(GlobalXdsClientTest, MultipleChannelsShareXdsClient) { const char* kNewServerName = "new-server.example.com"; Listener listener = default_listener_; listener.set_name(kNewServerName); @@ -2839,7 +3185,7 @@ TEST_P(XdsResolverOnlyTest, MultipleChannelsShareXdsClient) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); WaitForAllBackends(); @@ -2852,6 +3198,38 @@ TEST_P(XdsResolverOnlyTest, MultipleChannelsShareXdsClient) { EXPECT_EQ(1UL, balancers_[0]->ads_service()->clients().size()); } +// Tests that the NACK for multiple bad LDS resources includes both errors. +TEST_P(GlobalXdsClientTest, MultipleBadResources) { + constexpr char kServerName2[] = "server.other.com"; + auto listener = default_listener_; + listener.clear_api_listener(); + balancers_[0]->ads_service()->SetLdsResource(listener); + listener.set_name(kServerName2); + balancers_[0]->ads_service()->SetLdsResource(listener); + SetNextResolutionForLbChannelAllBalancers(); + CheckRpcSendFailure(); + // Need to create a second channel to subscribe to a second LDS resource. + auto channel2 = CreateChannel(0, kServerName2); + auto stub2 = grpc::testing::EchoTestService::NewStub(channel2); + ClientContext context; + EchoRequest request; + request.set_message(kRequestMessage); + EchoResponse response; + grpc::Status status = stub2->Echo(&context, request, &response); + EXPECT_FALSE(status.ok()); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT( + response_state.error_message, + ::testing::AllOf( + ::testing::HasSubstr(absl::StrCat( + kServerName, ": Listener has neither address nor ApiListener")), + ::testing::HasSubstr( + absl::StrCat(kServerName2, + ": Listener has neither address nor ApiListener")))); +} + class XdsResolverLoadReportingOnlyTest : public XdsEnd2endTest { public: XdsResolverLoadReportingOnlyTest() : XdsEnd2endTest(4, 1, 3) {} @@ -2867,12 +3245,12 @@ TEST_P(XdsResolverLoadReportingOnlyTest, ChangeClusters) { SetNextResolutionForLbChannelAllBalancers(); // cluster kDefaultClusterName -> locality0 -> backends 0 and 1 AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 2)}, + {"locality0", CreateEndpointsForBackends(0, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // cluster kNewClusterName -> locality1 -> backends 2 and 3 AdsServiceImpl::EdsResourceArgs args2({ - {"locality1", GetBackendPorts(2, 4)}, + {"locality1", CreateEndpointsForBackends(2, 4)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args2, kNewEdsServiceName)); @@ -2992,7 +3370,7 @@ TEST_P(SecureNamingTest, TargetNameIsExpected) { SetNextResolution({}); SetNextResolutionForLbChannel({balancers_[0]->port()}, nullptr, "xds_server"); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -3006,7 +3384,7 @@ TEST_P(SecureNamingTest, TargetNameIsUnexpected) { SetNextResolutionForLbChannel({balancers_[0]->port()}, nullptr, "incorrect_server_name"); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -3105,55 +3483,30 @@ TEST_P(LdsTest, RdsConfigSourceDoesNotSpecifyAds) { "HttpConnectionManager ConfigSource for RDS does not specify ADS.")); } -// Tests that the NACK for multiple bad LDS resources includes both errors. -TEST_P(LdsTest, MultipleBadResources) { - constexpr char kServerName2[] = "server.other.com"; - auto listener = default_listener_; - listener.clear_api_listener(); - balancers_[0]->ads_service()->SetLdsResource(listener); - listener.set_name(kServerName2); - balancers_[0]->ads_service()->SetLdsResource(listener); - SetNextResolutionForLbChannelAllBalancers(); - CheckRpcSendFailure(); - // Need to create a second channel to subscribe to a second LDS resource. - auto channel2 = CreateChannel(0, kServerName2); - auto stub2 = grpc::testing::EchoTestService::NewStub(channel2); - ClientContext context; - EchoRequest request; - request.set_message(kRequestMessage); - EchoResponse response; - grpc::Status status = stub2->Echo(&context, request, &response); - EXPECT_FALSE(status.ok()); - const auto response_state = - balancers_[0]->ads_service()->lds_response_state(); - EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); - EXPECT_THAT( - response_state.error_message, - ::testing::AllOf( - ::testing::HasSubstr(absl::StrCat( - kServerName, ": Listener has neither address nor ApiListener")), - ::testing::HasSubstr( - absl::StrCat(kServerName2, - ": Listener has neither address nor ApiListener")))); -} - -// TODO(roth): Remove this test when we remove the -// GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION environment variable guard. -TEST_P(LdsTest, HttpFiltersEnabled) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); +// Tests that we ignore filters after the router filter. +TEST_P(LdsTest, IgnoresHttpFiltersAfterRouterFilter) { SetNextResolutionForLbChannelAllBalancers(); + auto listener = default_listener_; + HttpConnectionManager http_connection_manager; + listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( + &http_connection_manager); + auto* filter = http_connection_manager.add_http_filters(); + filter->set_name("unknown"); + filter->mutable_typed_config()->set_type_url( + "grpc.testing.client_only_http_filter"); + listener.mutable_api_listener()->mutable_api_listener()->PackFrom( + http_connection_manager); + SetListenerAndRouteConfiguration(0, listener, default_route_config_); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); WaitForAllBackends(); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we fail RPCs if there is no router filter. TEST_P(LdsTest, FailRpcsIfNoHttpRouterFilter) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); SetNextResolutionForLbChannelAllBalancers(); auto listener = default_listener_; HttpConnectionManager http_connection_manager; @@ -3164,7 +3517,7 @@ TEST_P(LdsTest, FailRpcsIfNoHttpRouterFilter) { http_connection_manager); SetListenerAndRouteConfiguration(0, listener, default_route_config_); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -3179,15 +3532,10 @@ TEST_P(LdsTest, FailRpcsIfNoHttpRouterFilter) { const auto response_state = balancers_[0]->ads_service()->lds_response_state(); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } -// TODO(lidiz): As part of adding the fault injection filter, add a test -// that we ignore filters after the router filter. - // Test that we NACK empty filter names. TEST_P(LdsTest, RejectsEmptyHttpFilterName) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); auto listener = default_listener_; HttpConnectionManager http_connection_manager; listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( @@ -3209,12 +3557,10 @@ TEST_P(LdsTest, RejectsEmptyHttpFilterName) { EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); EXPECT_THAT(response_state.error_message, ::testing::HasSubstr("empty filter name at index 1")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we NACK duplicate HTTP filter names. TEST_P(LdsTest, RejectsDuplicateHttpFilterName) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); auto listener = default_listener_; HttpConnectionManager http_connection_manager; listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( @@ -3236,12 +3582,10 @@ TEST_P(LdsTest, RejectsDuplicateHttpFilterName) { EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); EXPECT_THAT(response_state.error_message, ::testing::HasSubstr("duplicate HTTP filter name: router")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we NACK unknown filter types. TEST_P(LdsTest, RejectsUnknownHttpFilterType) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); auto listener = default_listener_; HttpConnectionManager http_connection_manager; listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( @@ -3265,12 +3609,10 @@ TEST_P(LdsTest, RejectsUnknownHttpFilterType) { EXPECT_THAT(response_state.error_message, ::testing::HasSubstr("no filter registered for config type " "envoy.config.listener.v3.Listener")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we ignore optional unknown filter types. TEST_P(LdsTest, IgnoresOptionalUnknownHttpFilterType) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); auto listener = default_listener_; HttpConnectionManager http_connection_manager; listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( @@ -3283,7 +3625,56 @@ TEST_P(LdsTest, IgnoresOptionalUnknownHttpFilterType) { http_connection_manager); SetListenerAndRouteConfiguration(0, listener, default_route_config_); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + SetNextResolutionForLbChannelAllBalancers(); + WaitForAllBackends(); + EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state, + AdsServiceImpl::ResponseState::ACKED); +} + +// Test that we NACK filters without configs. +TEST_P(LdsTest, RejectsHttpFilterWithoutConfig) { + auto listener = default_listener_; + HttpConnectionManager http_connection_manager; + listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( + &http_connection_manager); + auto* filter = http_connection_manager.add_http_filters(); + filter->set_name("unknown"); + listener.mutable_api_listener()->mutable_api_listener()->PackFrom( + http_connection_manager); + SetListenerAndRouteConfiguration(0, listener, default_route_config_); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr( + "no filter config specified for filter name unknown")); +} + +// Test that we ignore optional filters without configs. +TEST_P(LdsTest, IgnoresOptionalHttpFilterWithoutConfig) { + auto listener = default_listener_; + HttpConnectionManager http_connection_manager; + listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( + &http_connection_manager); + auto* filter = http_connection_manager.add_http_filters(); + filter->set_name("unknown"); + filter->set_is_optional(true); + listener.mutable_api_listener()->mutable_api_listener()->PackFrom( + http_connection_manager); + SetListenerAndRouteConfiguration(0, listener, default_route_config_); + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -3291,12 +3682,10 @@ TEST_P(LdsTest, IgnoresOptionalUnknownHttpFilterType) { WaitForAllBackends(); EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state, AdsServiceImpl::ResponseState::ACKED); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we NACK unparseable filter configs. TEST_P(LdsTest, RejectsUnparseableHttpFilterType) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); auto listener = default_listener_; HttpConnectionManager http_connection_manager; listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( @@ -3324,7 +3713,87 @@ TEST_P(LdsTest, RejectsUnparseableHttpFilterType) { ::testing::HasSubstr( "filter config for type " "envoy.extensions.filters.http.router.v3.Router failed to parse")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); +} + +// Test that we NACK HTTP filters unsupported on client-side. +TEST_P(LdsTest, RejectsHttpFiltersNotSupportedOnClients) { + auto listener = default_listener_; + HttpConnectionManager http_connection_manager; + listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( + &http_connection_manager); + auto* filter = http_connection_manager.add_http_filters(); + filter->set_name("grpc.testing.server_only_http_filter"); + filter->mutable_typed_config()->set_type_url( + "grpc.testing.server_only_http_filter"); + listener.mutable_api_listener()->mutable_api_listener()->PackFrom( + http_connection_manager); + SetListenerAndRouteConfiguration(0, listener, default_route_config_); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT( + response_state.error_message, + ::testing::HasSubstr("Filter grpc.testing.server_only_http_filter is not " + "supported on clients")); +} + +// Test that we ignore optional HTTP filters unsupported on client-side. +TEST_P(LdsTest, IgnoresOptionalHttpFiltersNotSupportedOnClients) { + auto listener = default_listener_; + HttpConnectionManager http_connection_manager; + listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( + &http_connection_manager); + auto* filter = http_connection_manager.add_http_filters(); + filter->set_name("grpc.testing.server_only_http_filter"); + filter->mutable_typed_config()->set_type_url( + "grpc.testing.server_only_http_filter"); + filter->set_is_optional(true); + listener.mutable_api_listener()->mutable_api_listener()->PackFrom( + http_connection_manager); + SetListenerAndRouteConfiguration(0, listener, default_route_config_); + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends(0, 1)}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + WaitForBackend(0); + EXPECT_EQ(balancers_[0]->ads_service()->lds_response_state().state, + AdsServiceImpl::ResponseState::ACKED); +} + +using LdsV2Test = LdsTest; + +// Tests that we ignore the HTTP filter list in v2. +// TODO(roth): The test framework is not set up to allow us to test +// the server sending v2 resources when the client requests v3, so this +// just tests a pure v2 setup. When we have time, fix this. +TEST_P(LdsV2Test, IgnoresHttpFilters) { + auto listener = default_listener_; + HttpConnectionManager http_connection_manager; + listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( + &http_connection_manager); + auto* filter = http_connection_manager.add_http_filters(); + filter->set_name("unknown"); + filter->mutable_typed_config()->PackFrom(Listener()); + listener.mutable_api_listener()->mutable_api_listener()->PackFrom( + http_connection_manager); + SetListenerAndRouteConfiguration(0, listener, default_route_config_); + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends(0, 1)}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + SetNextResolutionForLbChannelAllBalancers(); + CheckRpcSendOk(); } using LdsRdsTest = BasicTest; @@ -3349,7 +3818,7 @@ TEST_P(LdsRdsTest, ListenerRemoved) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); // We need to wait for all backends to come online. @@ -3813,13 +4282,13 @@ TEST_P(LdsRdsTest, XdsRoutingPathMatching) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 2)}, + {"locality0", CreateEndpointsForBackends(0, 2)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(3, 4)}, + {"locality0", CreateEndpointsForBackends(3, 4)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -3888,13 +4357,13 @@ TEST_P(LdsRdsTest, XdsRoutingPathMatchingCaseInsensitive) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -3953,13 +4422,13 @@ TEST_P(LdsRdsTest, XdsRoutingPrefixMatching) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 2)}, + {"locality0", CreateEndpointsForBackends(0, 2)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(3, 4)}, + {"locality0", CreateEndpointsForBackends(3, 4)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4023,13 +4492,13 @@ TEST_P(LdsRdsTest, XdsRoutingPrefixMatchingCaseInsensitive) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4088,13 +4557,13 @@ TEST_P(LdsRdsTest, XdsRoutingPathRegexMatching) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 2)}, + {"locality0", CreateEndpointsForBackends(0, 2)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(3, 4)}, + {"locality0", CreateEndpointsForBackends(3, 4)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4160,13 +4629,13 @@ TEST_P(LdsRdsTest, XdsRoutingPathRegexMatchingCaseInsensitive) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4221,21 +4690,25 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedCluster) { const char* kNewCluster2Name = "new_cluster_2"; const char* kNewEdsService2Name = "new_eds_service_name_2"; const char* kNotUsedClusterName = "not_used_cluster"; - const size_t kNumEcho1Rpcs = 1000; - const size_t kNumEchoRpcs = 10; + const size_t kNumEchoRpcs = 10; // RPCs that will go to a fixed backend. const size_t kWeight75 = 75; const size_t kWeight25 = 25; + const double kErrorTolerance = 0.05; + const double kWeight75Percent = static_cast(kWeight75) / 100; + const double kWeight25Percent = static_cast(kWeight25) / 100; + const size_t kNumEcho1Rpcs = + ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance); SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4279,7 +4752,8 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedCluster) { default_route->mutable_route()->set_cluster(kDefaultClusterName); SetRouteConfiguration(0, new_route_config); WaitForAllBackends(0, 1); - WaitForAllBackends(1, 3, true, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + WaitForAllBackends(1, 3, WaitForBackendOptions(), + RpcOptions().set_rpc_service(SERVICE_ECHO1)); CheckRpcSendOk(kNumEchoRpcs); CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1)); // Make sure RPCs all go to the correct backend. @@ -4291,24 +4765,12 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedCluster) { EXPECT_EQ(0, backends_[2]->backend_service()->request_count()); const int weight_25_request_count = backends_[2]->backend_service1()->request_count(); - const double kErrorTolerance = 0.2; - EXPECT_THAT( - weight_75_request_count, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 + kErrorTolerance)))); - // TODO(@donnadionne): Reduce tolerance: increased the tolerance to keep the - // test from flaking while debugging potential root cause. - const double kErrorToleranceSmallLoad = 0.3; gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs", weight_75_request_count, weight_25_request_count); - EXPECT_THAT(weight_25_request_count, - ::testing::AllOf( - ::testing::Ge(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 - kErrorToleranceSmallLoad)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 + kErrorToleranceSmallLoad)))); + EXPECT_THAT(static_cast(weight_75_request_count) / kNumEcho1Rpcs, + ::testing::DoubleNear(kWeight75Percent, kErrorTolerance)); + EXPECT_THAT(static_cast(weight_25_request_count) / kNumEcho1Rpcs, + ::testing::DoubleNear(kWeight25Percent, kErrorTolerance)); } TEST_P(LdsRdsTest, RouteActionWeightedTargetDefaultRoute) { @@ -4316,20 +4778,24 @@ TEST_P(LdsRdsTest, RouteActionWeightedTargetDefaultRoute) { const char* kNewEdsService1Name = "new_eds_service_name_1"; const char* kNewCluster2Name = "new_cluster_2"; const char* kNewEdsService2Name = "new_eds_service_name_2"; - const size_t kNumEchoRpcs = 1000; const size_t kWeight75 = 75; const size_t kWeight25 = 25; + const double kErrorTolerance = 0.05; + const double kWeight75Percent = static_cast(kWeight75) / 100; + const double kWeight25Percent = static_cast(kWeight25) / 100; + const size_t kNumEchoRpcs = + ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance); SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4372,24 +4838,12 @@ TEST_P(LdsRdsTest, RouteActionWeightedTargetDefaultRoute) { backends_[1]->backend_service()->request_count(); const int weight_25_request_count = backends_[2]->backend_service()->request_count(); - const double kErrorTolerance = 0.2; - EXPECT_THAT( - weight_75_request_count, - ::testing::AllOf(::testing::Ge(static_cast(kNumEchoRpcs) * - kWeight75 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEchoRpcs) * - kWeight75 / 100 * (1 + kErrorTolerance)))); - // TODO(@donnadionne): Reduce tolerance: increased the tolerance to keep the - // test from flaking while debugging potential root cause. - const double kErrorToleranceSmallLoad = 0.3; gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs", weight_75_request_count, weight_25_request_count); - EXPECT_THAT(weight_25_request_count, - ::testing::AllOf( - ::testing::Ge(static_cast(kNumEchoRpcs) * kWeight25 / - 100 * (1 - kErrorToleranceSmallLoad)), - ::testing::Le(static_cast(kNumEchoRpcs) * kWeight25 / - 100 * (1 + kErrorToleranceSmallLoad)))); + EXPECT_THAT(static_cast(weight_75_request_count) / kNumEchoRpcs, + ::testing::DoubleNear(kWeight75Percent, kErrorTolerance)); + EXPECT_THAT(static_cast(weight_25_request_count) / kNumEchoRpcs, + ::testing::DoubleNear(kWeight25Percent, kErrorTolerance)); } TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) { @@ -4399,25 +4853,32 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) { const char* kNewEdsService2Name = "new_eds_service_name_2"; const char* kNewCluster3Name = "new_cluster_3"; const char* kNewEdsService3Name = "new_eds_service_name_3"; - const size_t kNumEcho1Rpcs = 1000; const size_t kNumEchoRpcs = 10; const size_t kWeight75 = 75; const size_t kWeight25 = 25; const size_t kWeight50 = 50; + const double kErrorTolerance = 0.05; + const double kWeight75Percent = static_cast(kWeight75) / 100; + const double kWeight25Percent = static_cast(kWeight25) / 100; + const double kWeight50Percent = static_cast(kWeight50) / 100; + const size_t kNumEcho1Rpcs7525 = + ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance); + const size_t kNumEcho1Rpcs5050 = + ComputeIdealNumRpcs(kWeight50Percent, kErrorTolerance); SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); AdsServiceImpl::EdsResourceArgs args3({ - {"locality0", GetBackendPorts(3, 4)}, + {"locality0", CreateEndpointsForBackends(3, 4)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4463,9 +4924,11 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) { default_route->mutable_route()->set_cluster(kDefaultClusterName); SetRouteConfiguration(0, new_route_config); WaitForAllBackends(0, 1); - WaitForAllBackends(1, 3, true, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + WaitForAllBackends(1, 3, WaitForBackendOptions(), + RpcOptions().set_rpc_service(SERVICE_ECHO1)); CheckRpcSendOk(kNumEchoRpcs); - CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + CheckRpcSendOk(kNumEcho1Rpcs7525, + RpcOptions().set_rpc_service(SERVICE_ECHO1)); // Make sure RPCs all go to the correct backend. EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count()); EXPECT_EQ(0, backends_[0]->backend_service1()->request_count()); @@ -4478,24 +4941,12 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) { backends_[2]->backend_service1()->request_count(); EXPECT_EQ(0, backends_[3]->backend_service()->request_count()); EXPECT_EQ(0, backends_[3]->backend_service1()->request_count()); - const double kErrorTolerance = 0.2; - EXPECT_THAT( - weight_75_request_count, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 + kErrorTolerance)))); - // TODO(@donnadionne): Reduce tolerance: increased the tolerance to keep the - // test from flaking while debugging potential root cause. - const double kErrorToleranceSmallLoad = 0.3; gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs", weight_75_request_count, weight_25_request_count); - EXPECT_THAT(weight_25_request_count, - ::testing::AllOf( - ::testing::Ge(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 - kErrorToleranceSmallLoad)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 + kErrorToleranceSmallLoad)))); + EXPECT_THAT(static_cast(weight_75_request_count) / kNumEcho1Rpcs7525, + ::testing::DoubleNear(kWeight75Percent, kErrorTolerance)); + EXPECT_THAT(static_cast(weight_25_request_count) / kNumEcho1Rpcs7525, + ::testing::DoubleNear(kWeight25Percent, kErrorTolerance)); // Change Route Configurations: same clusters different weights. weighted_cluster1->mutable_weight()->set_value(kWeight50); weighted_cluster2->mutable_weight()->set_value(kWeight50); @@ -4506,7 +4957,8 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) { ResetBackendCounters(); WaitForAllBackends(3, 4); CheckRpcSendOk(kNumEchoRpcs); - CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + CheckRpcSendOk(kNumEcho1Rpcs5050, + RpcOptions().set_rpc_service(SERVICE_ECHO1)); // Make sure RPCs all go to the correct backend. EXPECT_EQ(0, backends_[0]->backend_service()->request_count()); EXPECT_EQ(0, backends_[0]->backend_service1()->request_count()); @@ -4519,17 +4971,11 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateWeights) { EXPECT_EQ(kNumEchoRpcs, backends_[3]->backend_service()->request_count()); EXPECT_EQ(0, backends_[3]->backend_service1()->request_count()); EXPECT_THAT( - weight_50_request_count_1, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 + kErrorTolerance)))); + static_cast(weight_50_request_count_1) / kNumEcho1Rpcs5050, + ::testing::DoubleNear(kWeight50Percent, kErrorTolerance)); EXPECT_THAT( - weight_50_request_count_2, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 + kErrorTolerance)))); + static_cast(weight_50_request_count_2) / kNumEcho1Rpcs5050, + ::testing::DoubleNear(kWeight50Percent, kErrorTolerance)); } TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) { @@ -4539,25 +4985,32 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) { const char* kNewEdsService2Name = "new_eds_service_name_2"; const char* kNewCluster3Name = "new_cluster_3"; const char* kNewEdsService3Name = "new_eds_service_name_3"; - const size_t kNumEcho1Rpcs = 1000; const size_t kNumEchoRpcs = 10; const size_t kWeight75 = 75; const size_t kWeight25 = 25; const size_t kWeight50 = 50; + const double kErrorTolerance = 0.05; + const double kWeight75Percent = static_cast(kWeight75) / 100; + const double kWeight25Percent = static_cast(kWeight25) / 100; + const double kWeight50Percent = static_cast(kWeight50) / 100; + const size_t kNumEcho1Rpcs7525 = + ComputeIdealNumRpcs(kWeight75Percent, kErrorTolerance); + const size_t kNumEcho1Rpcs5050 = + ComputeIdealNumRpcs(kWeight50Percent, kErrorTolerance); SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); AdsServiceImpl::EdsResourceArgs args3({ - {"locality0", GetBackendPorts(3, 4)}, + {"locality0", CreateEndpointsForBackends(3, 4)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4602,10 +5055,12 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) { default_route->mutable_match()->set_prefix(""); default_route->mutable_route()->set_cluster(kDefaultClusterName); SetRouteConfiguration(0, new_route_config); - WaitForAllBackends(0, 1); - WaitForAllBackends(1, 2, true, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + WaitForBackend(0); + WaitForBackend(1, WaitForBackendOptions(), + RpcOptions().set_rpc_service(SERVICE_ECHO1)); CheckRpcSendOk(kNumEchoRpcs); - CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + CheckRpcSendOk(kNumEcho1Rpcs7525, + RpcOptions().set_rpc_service(SERVICE_ECHO1)); // Make sure RPCs all go to the correct backend. EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count()); int weight_25_request_count = @@ -4617,33 +5072,23 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) { EXPECT_EQ(0, backends_[2]->backend_service1()->request_count()); EXPECT_EQ(0, backends_[3]->backend_service()->request_count()); EXPECT_EQ(0, backends_[3]->backend_service1()->request_count()); - const double kErrorTolerance = 0.2; - EXPECT_THAT( - weight_75_request_count, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 + kErrorTolerance)))); - // TODO(@donnadionne): Reduce tolerance: increased the tolerance to keep the - // test from flaking while debugging potential root cause. - const double kErrorToleranceSmallLoad = 0.3; gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs", weight_75_request_count, weight_25_request_count); - EXPECT_THAT(weight_25_request_count, - ::testing::AllOf( - ::testing::Ge(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 - kErrorToleranceSmallLoad)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 + kErrorToleranceSmallLoad)))); + EXPECT_THAT(static_cast(weight_75_request_count) / kNumEcho1Rpcs7525, + ::testing::DoubleNear(kWeight75Percent, kErrorTolerance)); + EXPECT_THAT(static_cast(weight_25_request_count) / kNumEcho1Rpcs7525, + ::testing::DoubleNear(kWeight25Percent, kErrorTolerance)); // Change Route Configurations: new set of clusters with different weights. weighted_cluster1->mutable_weight()->set_value(kWeight50); weighted_cluster2->set_name(kNewCluster2Name); weighted_cluster2->mutable_weight()->set_value(kWeight50); SetRouteConfiguration(0, new_route_config); ResetBackendCounters(); - WaitForAllBackends(2, 3, true, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + WaitForBackend(2, WaitForBackendOptions(), + RpcOptions().set_rpc_service(SERVICE_ECHO1)); CheckRpcSendOk(kNumEchoRpcs); - CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + CheckRpcSendOk(kNumEcho1Rpcs5050, + RpcOptions().set_rpc_service(SERVICE_ECHO1)); // Make sure RPCs all go to the correct backend. EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count()); EXPECT_EQ(0, backends_[0]->backend_service1()->request_count()); @@ -4656,26 +5101,22 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) { EXPECT_EQ(0, backends_[3]->backend_service()->request_count()); EXPECT_EQ(0, backends_[3]->backend_service1()->request_count()); EXPECT_THAT( - weight_50_request_count_1, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 + kErrorTolerance)))); + static_cast(weight_50_request_count_1) / kNumEcho1Rpcs5050, + ::testing::DoubleNear(kWeight50Percent, kErrorTolerance)); EXPECT_THAT( - weight_50_request_count_2, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight50 / 100 * (1 + kErrorTolerance)))); + static_cast(weight_50_request_count_2) / kNumEcho1Rpcs5050, + ::testing::DoubleNear(kWeight50Percent, kErrorTolerance)); // Change Route Configurations. weighted_cluster1->mutable_weight()->set_value(kWeight75); weighted_cluster2->set_name(kNewCluster3Name); weighted_cluster2->mutable_weight()->set_value(kWeight25); SetRouteConfiguration(0, new_route_config); ResetBackendCounters(); - WaitForAllBackends(3, 4, true, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + WaitForBackend(3, WaitForBackendOptions(), + RpcOptions().set_rpc_service(SERVICE_ECHO1)); CheckRpcSendOk(kNumEchoRpcs); - CheckRpcSendOk(kNumEcho1Rpcs, RpcOptions().set_rpc_service(SERVICE_ECHO1)); + CheckRpcSendOk(kNumEcho1Rpcs7525, + RpcOptions().set_rpc_service(SERVICE_ECHO1)); // Make sure RPCs all go to the correct backend. EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count()); EXPECT_EQ(0, backends_[0]->backend_service1()->request_count()); @@ -4685,22 +5126,12 @@ TEST_P(LdsRdsTest, XdsRoutingWeightedClusterUpdateClusters) { EXPECT_EQ(0, backends_[2]->backend_service1()->request_count()); EXPECT_EQ(0, backends_[3]->backend_service()->request_count()); weight_25_request_count = backends_[3]->backend_service1()->request_count(); - EXPECT_THAT( - weight_75_request_count, - ::testing::AllOf(::testing::Ge(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * - kWeight75 / 100 * (1 + kErrorTolerance)))); - // TODO(@donnadionne): Reduce tolerance: increased the tolerance to keep the - // test from flaking while debugging potential root cause. gpr_log(GPR_INFO, "target_75 received %d rpcs and target_25 received %d rpcs", weight_75_request_count, weight_25_request_count); - EXPECT_THAT(weight_25_request_count, - ::testing::AllOf( - ::testing::Ge(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 - kErrorToleranceSmallLoad)), - ::testing::Le(static_cast(kNumEcho1Rpcs) * kWeight25 / - 100 * (1 + kErrorToleranceSmallLoad)))); + EXPECT_THAT(static_cast(weight_75_request_count) / kNumEcho1Rpcs7525, + ::testing::DoubleNear(kWeight75Percent, kErrorTolerance)); + EXPECT_THAT(static_cast(weight_25_request_count) / kNumEcho1Rpcs7525, + ::testing::DoubleNear(kWeight25Percent, kErrorTolerance)); } TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClusters) { @@ -4711,10 +5142,10 @@ TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClusters) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4750,10 +5181,10 @@ TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClustersWithPickingDelays) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -4787,7 +5218,9 @@ TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClustersWithPickingDelays) { 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); + WaitForBackend( + 1, WaitForBackendOptions().set_reset_counters(false).set_allow_failures( + true)); // Bring up the previous backend: 0, this will allow the delayed RPC to // finally call on_call_committed upon completion. StartBackend(0); @@ -4798,7 +5231,6 @@ TEST_P(LdsRdsTest, XdsRoutingClusterUpdateClustersWithPickingDelays) { } TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT", "true"); const int64_t kTimeoutMillis = 500; const int64_t kTimeoutNano = kTimeoutMillis * 1000000; const int64_t kTimeoutGrpcTimeoutHeaderMaxSecond = 1; @@ -4814,18 +5246,14 @@ TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); - AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); - AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); - AdsServiceImpl::EdsResourceArgs args3({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", {MakeNonExistantEndpoint()}}}); + AdsServiceImpl::EdsResourceArgs args1( + {{"locality0", {MakeNonExistantEndpoint()}}}); + AdsServiceImpl::EdsResourceArgs args2( + {{"locality0", {MakeNonExistantEndpoint()}}}); + AdsServiceImpl::EdsResourceArgs args3( + {{"locality0", {MakeNonExistantEndpoint()}}}); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args1, kNewEdsService1Name)); @@ -4892,8 +5320,7 @@ TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) { // Set listener and route config. SetListenerAndRouteConfiguration(0, std::move(listener), new_route_config); // Test grpc_timeout_header_max of 1.5 seconds applied - gpr_cycle_counter now = gpr_get_cycle_counter(); - grpc_millis t0 = grpc_cycle_counter_to_millis_round_up(now); + grpc_millis t0 = NowFromCycleCounter(); grpc_millis t1 = t0 + kTimeoutGrpcTimeoutHeaderMaxSecond * 1000 + kTimeoutMillis; grpc_millis t2 = t0 + kTimeoutMaxStreamDurationSecond * 1000 + kTimeoutMillis; @@ -4904,13 +5331,11 @@ TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) { .set_wait_for_ready(true) .set_timeout_ms(kTimeoutApplicationSecond * 1000), StatusCode::DEADLINE_EXCEEDED); - now = gpr_get_cycle_counter(); - t0 = grpc_cycle_counter_to_millis_round_up(now); + t0 = NowFromCycleCounter(); EXPECT_GE(t0, t1); EXPECT_LT(t0, t2); // Test max_stream_duration of 2.5 seconds applied - now = gpr_get_cycle_counter(); - t0 = grpc_cycle_counter_to_millis_round_up(now); + t0 = NowFromCycleCounter(); t1 = t0 + kTimeoutMaxStreamDurationSecond * 1000 + kTimeoutMillis; t2 = t0 + kTimeoutHttpMaxStreamDurationSecond * 1000 + kTimeoutMillis; CheckRpcSendFailure(1, @@ -4920,106 +5345,23 @@ TEST_P(LdsRdsTest, XdsRoutingApplyXdsTimeout) { .set_wait_for_ready(true) .set_timeout_ms(kTimeoutApplicationSecond * 1000), StatusCode::DEADLINE_EXCEEDED); - now = gpr_get_cycle_counter(); - t0 = grpc_cycle_counter_to_millis_round_up(now); + t0 = NowFromCycleCounter(); EXPECT_GE(t0, t1); EXPECT_LT(t0, t2); // Test http_stream_duration of 3.5 seconds applied - now = gpr_get_cycle_counter(); - t0 = grpc_cycle_counter_to_millis_round_up(now); + t0 = NowFromCycleCounter(); t1 = t0 + kTimeoutHttpMaxStreamDurationSecond * 1000 + kTimeoutMillis; t2 = t0 + kTimeoutApplicationSecond * 1000 + kTimeoutMillis; CheckRpcSendFailure(1, RpcOptions().set_wait_for_ready(true).set_timeout_ms( kTimeoutApplicationSecond * 1000), StatusCode::DEADLINE_EXCEEDED); - now = gpr_get_cycle_counter(); - t0 = grpc_cycle_counter_to_millis_round_up(now); + t0 = NowFromCycleCounter(); EXPECT_GE(t0, t1); EXPECT_LT(t0, t2); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT"); -} - -TEST_P(LdsRdsTest, XdsRoutingXdsTimeoutDisabled) { - const int64_t kTimeoutMillis = 500; - const int64_t kTimeoutNano = kTimeoutMillis * 1000000; - const int64_t kTimeoutGrpcTimeoutHeaderMaxSecond = 1; - const int64_t kTimeoutApplicationSecond = 4; - SetNextResolution({}); - SetNextResolutionForLbChannelAllBalancers(); - // Populate new EDS resources. - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); - balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); - RouteConfiguration new_route_config = default_route_config_; - // route 1: Set grpc_timeout_header_max of 1.5 - auto* route1 = new_route_config.mutable_virtual_hosts(0)->mutable_routes(0); - auto* max_stream_duration = - route1->mutable_route()->mutable_max_stream_duration(); - auto* duration = max_stream_duration->mutable_grpc_timeout_header_max(); - duration->set_seconds(kTimeoutGrpcTimeoutHeaderMaxSecond); - duration->set_nanos(kTimeoutNano); - SetRouteConfiguration(0, new_route_config); - // Test grpc_timeout_header_max of 1.5 seconds is not applied - gpr_timespec t0 = gpr_now(GPR_CLOCK_MONOTONIC); - gpr_timespec est_timeout_time = gpr_time_add( - t0, gpr_time_from_millis( - kTimeoutGrpcTimeoutHeaderMaxSecond * 1000 + kTimeoutMillis, - GPR_TIMESPAN)); - CheckRpcSendFailure(1, - RpcOptions() - .set_rpc_service(SERVICE_ECHO1) - .set_rpc_method(METHOD_ECHO1) - .set_wait_for_ready(true) - .set_timeout_ms(kTimeoutApplicationSecond * 1000), - StatusCode::DEADLINE_EXCEEDED); - gpr_timespec timeout_time = gpr_now(GPR_CLOCK_MONOTONIC); - EXPECT_GT(gpr_time_cmp(timeout_time, est_timeout_time), 0); -} - -TEST_P(LdsRdsTest, XdsRoutingHttpTimeoutDisabled) { - const int64_t kTimeoutMillis = 500; - const int64_t kTimeoutNano = kTimeoutMillis * 1000000; - const int64_t kTimeoutHttpMaxStreamDurationSecond = 3; - const int64_t kTimeoutApplicationSecond = 4; - SetNextResolution({}); - SetNextResolutionForLbChannelAllBalancers(); - // Populate new EDS resources. - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); - // Construct listener. - auto listener = default_listener_; - HttpConnectionManager http_connection_manager; - listener.mutable_api_listener()->mutable_api_listener()->UnpackTo( - &http_connection_manager); - // Set up HTTP max_stream_duration of 3.5 seconds - auto* duration = - http_connection_manager.mutable_common_http_protocol_options() - ->mutable_max_stream_duration(); - duration->set_seconds(kTimeoutHttpMaxStreamDurationSecond); - duration->set_nanos(kTimeoutNano); - listener.mutable_api_listener()->mutable_api_listener()->PackFrom( - http_connection_manager); - SetListenerAndRouteConfiguration(0, std::move(listener), - default_route_config_); - // Test http_stream_duration of 3.5 seconds is not applied - auto t0 = gpr_now(GPR_CLOCK_MONOTONIC); - auto est_timeout_time = gpr_time_add( - t0, gpr_time_from_millis( - kTimeoutHttpMaxStreamDurationSecond * 1000 + kTimeoutMillis, - GPR_TIMESPAN)); - CheckRpcSendFailure(1, - RpcOptions().set_wait_for_ready(true).set_timeout_ms( - kTimeoutApplicationSecond * 1000), - StatusCode::DEADLINE_EXCEEDED); - auto timeout_time = gpr_now(GPR_CLOCK_MONOTONIC); - EXPECT_GT(gpr_time_cmp(timeout_time, est_timeout_time), 0); } TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenXdsTimeoutExplicit0) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT", "true"); const int64_t kTimeoutNano = 500000000; const int64_t kTimeoutMaxStreamDurationSecond = 2; const int64_t kTimeoutHttpMaxStreamDurationSecond = 3; @@ -5031,15 +5373,12 @@ TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenXdsTimeoutExplicit0) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); - AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); - AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", {MakeNonExistantEndpoint()}}}); + AdsServiceImpl::EdsResourceArgs args1( + {{"locality0", {MakeNonExistantEndpoint()}}}); + AdsServiceImpl::EdsResourceArgs args2( + {{"locality0", {MakeNonExistantEndpoint()}}}); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args1, kNewEdsService1Name)); @@ -5121,18 +5460,15 @@ TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenXdsTimeoutExplicit0) { system_clock::now() - t0); EXPECT_GT(ellapsed_nano_seconds.count(), kTimeoutApplicationSecond * 1000000000); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT"); } TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenHttpTimeoutExplicit0) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT", "true"); const int64_t kTimeoutApplicationSecond = 4; SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", {MakeNonExistantEndpoint()}}}); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); auto listener = default_listener_; HttpConnectionManager http_connection_manager; @@ -5160,20 +5496,17 @@ TEST_P(LdsRdsTest, XdsRoutingApplyApplicationTimeoutWhenHttpTimeoutExplicit0) { t0); EXPECT_GT(ellapsed_nano_seconds.count(), kTimeoutApplicationSecond * 1000000000); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT"); } // Test to ensure application-specified deadline won't be affected when // the xDS config does not specify a timeout. TEST_P(LdsRdsTest, XdsRoutingWithOnlyApplicationTimeout) { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT", "true"); const int64_t kTimeoutApplicationSecond = 4; SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {grpc_pick_unused_port_or_die()}}, - }); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", {MakeNonExistantEndpoint()}}}); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); auto t0 = system_clock::now(); CheckRpcSendFailure(1, @@ -5185,7 +5518,6 @@ TEST_P(LdsRdsTest, XdsRoutingWithOnlyApplicationTimeout) { t0); EXPECT_GT(ellapsed_nano_seconds.count(), kTimeoutApplicationSecond * 1000000000); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_ENABLE_TIMEOUT"); } TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) { @@ -5197,10 +5529,10 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -5258,8 +5590,8 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatching) { .set_rpc_method(METHOD_ECHO1) .set_metadata(std::move(metadata)); // Make sure all backends are up. - WaitForAllBackends(0, 1); - WaitForAllBackends(1, 2, true, header_match_rpc_options); + WaitForBackend(0); + WaitForBackend(1, WaitForBackendOptions(), header_match_rpc_options); // Send RPCs. CheckRpcSendOk(kNumEchoRpcs); CheckRpcSendOk(kNumEcho1Rpcs, header_match_rpc_options); @@ -5281,10 +5613,10 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderContentType) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -5323,37 +5655,25 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialHeaderContentType) { TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) { const char* kNewCluster1Name = "new_cluster_1"; const char* kNewEdsService1Name = "new_eds_service_name_1"; - const char* kNewCluster2Name = "new_cluster_2"; - const char* kNewEdsService2Name = "new_eds_service_name_2"; const size_t kNumEchoRpcs = 100; SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, - }); - AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args1, kNewEdsService1Name)); - balancers_[0]->ads_service()->SetEdsResource( - BuildEdsResource(args2, kNewEdsService2Name)); // Populate new CDS resources. Cluster new_cluster1 = default_cluster_; new_cluster1.set_name(kNewCluster1Name); new_cluster1.mutable_eds_cluster_config()->set_service_name( kNewEdsService1Name); balancers_[0]->ads_service()->SetCdsResource(new_cluster1); - Cluster new_cluster2 = default_cluster_; - new_cluster2.set_name(kNewCluster2Name); - new_cluster2.mutable_eds_cluster_config()->set_service_name( - kNewEdsService2Name); - balancers_[0]->ads_service()->SetCdsResource(new_cluster2); // Populating Route Configurations for LDS. RouteConfiguration route_config = default_route_config_; auto* route1 = route_config.mutable_virtual_hosts(0)->mutable_routes(0); @@ -5362,12 +5682,6 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) { header_matcher1->set_name("grpc-foo-bin"); header_matcher1->set_present_match(true); route1->mutable_route()->set_cluster(kNewCluster1Name); - auto route2 = route_config.mutable_virtual_hosts(0)->add_routes(); - route2->mutable_match()->set_prefix(""); - auto* header_matcher2 = route2->mutable_match()->add_headers(); - header_matcher2->set_name("grpc-previous-rpc-attempts"); - header_matcher2->set_present_match(true); - route2->mutable_route()->set_cluster(kNewCluster2Name); auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); default_route->mutable_match()->set_prefix(""); default_route->mutable_route()->set_cluster(kDefaultClusterName); @@ -5375,7 +5689,6 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) { // Send headers which will mismatch each route std::vector> metadata = { {"grpc-foo-bin", "grpc-foo-bin"}, - {"grpc-previous-rpc-attempts", "grpc-previous-rpc-attempts"}, }; WaitForAllBackends(0, 1); CheckRpcSendOk(kNumEchoRpcs, RpcOptions().set_metadata(metadata)); @@ -5383,7 +5696,6 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) { // were mismatched. EXPECT_EQ(kNumEchoRpcs, backends_[0]->backend_service()->request_count()); EXPECT_EQ(0, backends_[1]->backend_service()->request_count()); - EXPECT_EQ(0, backends_[2]->backend_service()->request_count()); const auto response_state = RouteConfigurationResponseState(0); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED); } @@ -5391,15 +5703,20 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingSpecialCasesToIgnore) { TEST_P(LdsRdsTest, XdsRoutingRuntimeFractionMatching) { const char* kNewClusterName = "new_cluster"; const char* kNewEdsServiceName = "new_eds_service_name"; - const size_t kNumRpcs = 1000; + const double kErrorTolerance = 0.05; + const size_t kRouteMatchNumerator = 25; + const double kRouteMatchPercent = + static_cast(kRouteMatchNumerator) / 100; + const size_t kNumRpcs = + ComputeIdealNumRpcs(kRouteMatchPercent, kErrorTolerance); SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -5416,7 +5733,7 @@ TEST_P(LdsRdsTest, XdsRoutingRuntimeFractionMatching) { route1->mutable_match() ->mutable_runtime_fraction() ->mutable_default_value() - ->set_numerator(25); + ->set_numerator(kRouteMatchNumerator); route1->mutable_route()->set_cluster(kNewClusterName); auto* default_route = route_config.mutable_virtual_hosts(0)->add_routes(); default_route->mutable_match()->set_prefix(""); @@ -5428,19 +5745,10 @@ TEST_P(LdsRdsTest, XdsRoutingRuntimeFractionMatching) { backends_[0]->backend_service()->request_count(); const int matched_backend_count = backends_[1]->backend_service()->request_count(); - const double kErrorTolerance = 0.2; - EXPECT_THAT( - default_backend_count, - ::testing::AllOf(::testing::Ge(static_cast(kNumRpcs) * 75 / 100 * - (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumRpcs) * 75 / 100 * - (1 + kErrorTolerance)))); - EXPECT_THAT( - matched_backend_count, - ::testing::AllOf(::testing::Ge(static_cast(kNumRpcs) * 25 / 100 * - (1 - kErrorTolerance)), - ::testing::Le(static_cast(kNumRpcs) * 25 / 100 * - (1 + kErrorTolerance)))); + EXPECT_THAT(static_cast(default_backend_count) / kNumRpcs, + ::testing::DoubleNear(1 - kRouteMatchPercent, kErrorTolerance)); + EXPECT_THAT(static_cast(matched_backend_count) / kNumRpcs, + ::testing::DoubleNear(kRouteMatchPercent, kErrorTolerance)); const auto response_state = RouteConfigurationResponseState(0); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED); } @@ -5458,16 +5766,16 @@ TEST_P(LdsRdsTest, XdsRoutingHeadersMatchingUnmatchCases) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); AdsServiceImpl::EdsResourceArgs args3({ - {"locality0", GetBackendPorts(3, 4)}, + {"locality0", CreateEndpointsForBackends(3, 4)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -5551,10 +5859,10 @@ TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); balancers_[0]->ads_service()->SetEdsResource( @@ -5576,9 +5884,11 @@ TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) { SetRouteConfiguration(0, route_config); // Make sure all backends are up and that requests for each RPC // service go to the right backends. - WaitForAllBackends(0, 1, false); - WaitForAllBackends(1, 2, false, RpcOptions().set_rpc_service(SERVICE_ECHO1)); - WaitForAllBackends(0, 1, false, RpcOptions().set_rpc_service(SERVICE_ECHO2)); + WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false)); + WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false), + RpcOptions().set_rpc_service(SERVICE_ECHO1)); + WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false), + RpcOptions().set_rpc_service(SERVICE_ECHO2)); // Requests for services Echo and Echo2 should have gone to backend 0. EXPECT_EQ(1, backends_[0]->backend_service()->request_count()); EXPECT_EQ(0, backends_[0]->backend_service1()->request_count()); @@ -5591,12 +5901,15 @@ TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) { // different RPC service, and wait for the client to make the change. route1->mutable_match()->set_prefix("/grpc.testing.EchoTest2Service/"); SetRouteConfiguration(0, route_config); - WaitForAllBackends(1, 2, true, RpcOptions().set_rpc_service(SERVICE_ECHO2)); + WaitForBackend(1, WaitForBackendOptions(), + RpcOptions().set_rpc_service(SERVICE_ECHO2)); // Now repeat the earlier test, making sure all traffic goes to the // right place. - WaitForAllBackends(0, 1, false); - WaitForAllBackends(0, 1, false, RpcOptions().set_rpc_service(SERVICE_ECHO1)); - WaitForAllBackends(1, 2, false, RpcOptions().set_rpc_service(SERVICE_ECHO2)); + WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false)); + WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false), + RpcOptions().set_rpc_service(SERVICE_ECHO1)); + WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false), + RpcOptions().set_rpc_service(SERVICE_ECHO2)); // Requests for services Echo and Echo1 should have gone to backend 0. EXPECT_EQ(1, backends_[0]->backend_service()->request_count()); EXPECT_EQ(1, backends_[0]->backend_service1()->request_count()); @@ -5610,7 +5923,6 @@ TEST_P(LdsRdsTest, XdsRoutingChangeRoutesWithoutChangingClusters) { // Test that we NACK unknown filter types in VirtualHost. TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* per_filter_config = route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); @@ -5628,13 +5940,11 @@ TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInVirtualHost) { EXPECT_THAT(response_state.error_message, ::testing::HasSubstr("no filter registered for config type " "envoy.config.listener.v3.Listener")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we ignore optional unknown filter types in VirtualHost. TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* per_filter_config = route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); @@ -5644,7 +5954,7 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) { (*per_filter_config)["unknown"].PackFrom(filter_config); SetListenerAndRouteConfiguration(0, default_listener_, route_config); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -5653,18 +5963,15 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInVirtualHost) { WaitForAllBackends(); EXPECT_EQ(RouteConfigurationResponseState(0).state, AdsServiceImpl::ResponseState::ACKED); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } -// Test that we NACK unparseable filter types in VirtualHost. -TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) { +// Test that we NACK filters without configs in VirtualHost. +TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInVirtualHost) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* per_filter_config = route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); - (*per_filter_config)["unknown"].PackFrom( - envoy::extensions::filters::http::router::v3::Router()); + (*per_filter_config)["unknown"]; SetListenerAndRouteConfiguration(0, default_listener_, route_config); SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); @@ -5675,16 +5982,82 @@ TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) { AdsServiceImpl::ResponseState::SENT); const auto response_state = RouteConfigurationResponseState(0); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); - EXPECT_THAT( - response_state.error_message, - ::testing::HasSubstr("router filter does not support config override")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr( + "no filter config specified for filter name unknown")); +} + +// Test that we NACK filters without configs in FilterConfig in VirtualHost. +TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInVirtualHost) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* per_filter_config = + route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); + (*per_filter_config)["unknown"].PackFrom( + ::envoy::config::route::v3::FilterConfig()); + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (RouteConfigurationResponseState(0).state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = RouteConfigurationResponseState(0); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr( + "no filter config specified for filter name unknown")); +} + +// Test that we ignore optional filters without configs in VirtualHost. +TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInVirtualHost) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* per_filter_config = + route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); + ::envoy::config::route::v3::FilterConfig filter_config; + filter_config.set_is_optional(true); + (*per_filter_config)["unknown"].PackFrom(filter_config); + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + WaitForAllBackends(); + EXPECT_EQ(RouteConfigurationResponseState(0).state, + AdsServiceImpl::ResponseState::ACKED); +} + +// Test that we NACK unparseable filter types in VirtualHost. +TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInVirtualHost) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* per_filter_config = + route_config.mutable_virtual_hosts(0)->mutable_typed_per_filter_config(); + (*per_filter_config)["unknown"].PackFrom( + envoy::extensions::filters::http::router::v3::Router()); + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (RouteConfigurationResponseState(0).state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = RouteConfigurationResponseState(0); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT( + response_state.error_message, + ::testing::HasSubstr("router filter does not support config override")); } // Test that we NACK unknown filter types in Route. TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* per_filter_config = route_config.mutable_virtual_hosts(0) ->mutable_routes(0) @@ -5703,13 +6076,11 @@ TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInRoute) { EXPECT_THAT(response_state.error_message, ::testing::HasSubstr("no filter registered for config type " "envoy.config.listener.v3.Listener")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we ignore optional unknown filter types in Route. TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* per_filter_config = route_config.mutable_virtual_hosts(0) ->mutable_routes(0) @@ -5720,7 +6091,77 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) { (*per_filter_config)["unknown"].PackFrom(filter_config); SetListenerAndRouteConfiguration(0, default_listener_, route_config); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + WaitForAllBackends(); + EXPECT_EQ(RouteConfigurationResponseState(0).state, + AdsServiceImpl::ResponseState::ACKED); +} + +// Test that we NACK filters without configs in Route. +TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInRoute) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* per_filter_config = route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_typed_per_filter_config(); + (*per_filter_config)["unknown"]; + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (RouteConfigurationResponseState(0).state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = RouteConfigurationResponseState(0); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr( + "no filter config specified for filter name unknown")); +} + +// Test that we NACK filters without configs in FilterConfig in Route. +TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInFilterConfigInRoute) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* per_filter_config = route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_typed_per_filter_config(); + (*per_filter_config)["unknown"].PackFrom( + ::envoy::config::route::v3::FilterConfig()); + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (RouteConfigurationResponseState(0).state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = RouteConfigurationResponseState(0); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr( + "no filter config specified for filter name unknown")); +} + +// Test that we ignore optional filters without configs in Route. +TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInRoute) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* per_filter_config = route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_typed_per_filter_config(); + ::envoy::config::route::v3::FilterConfig filter_config; + filter_config.set_is_optional(true); + (*per_filter_config)["unknown"].PackFrom(filter_config); + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -5729,13 +6170,11 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInRoute) { WaitForAllBackends(); EXPECT_EQ(RouteConfigurationResponseState(0).state, AdsServiceImpl::ResponseState::ACKED); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we NACK unparseable filter types in Route. TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* per_filter_config = route_config.mutable_virtual_hosts(0) ->mutable_routes(0) @@ -5755,13 +6194,11 @@ TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInRoute) { EXPECT_THAT( response_state.error_message, ::testing::HasSubstr("router filter does not support config override")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we NACK unknown filter types in ClusterWeight. TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* cluster_weight = route_config.mutable_virtual_hosts(0) ->mutable_routes(0) @@ -5785,13 +6222,11 @@ TEST_P(LdsRdsTest, RejectsUnknownHttpFilterTypeInClusterWeight) { EXPECT_THAT(response_state.error_message, ::testing::HasSubstr("no filter registered for config type " "envoy.config.listener.v3.Listener")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we ignore optional unknown filter types in ClusterWeight. TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* cluster_weight = route_config.mutable_virtual_hosts(0) ->mutable_routes(0) @@ -5807,7 +6242,93 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) { (*per_filter_config)["unknown"].PackFrom(filter_config); SetListenerAndRouteConfiguration(0, default_listener_, route_config); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + WaitForAllBackends(); + EXPECT_EQ(RouteConfigurationResponseState(0).state, + AdsServiceImpl::ResponseState::ACKED); +} + +// Test that we NACK filters without configs in ClusterWeight. +TEST_P(LdsRdsTest, RejectsHttpFilterWithoutConfigInClusterWeight) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* cluster_weight = route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_route() + ->mutable_weighted_clusters() + ->add_clusters(); + cluster_weight->set_name(kDefaultClusterName); + cluster_weight->mutable_weight()->set_value(100); + auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); + (*per_filter_config)["unknown"]; + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (RouteConfigurationResponseState(0).state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = RouteConfigurationResponseState(0); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr( + "no filter config specified for filter name unknown")); +} + +// Test that we NACK filters without configs in FilterConfig in ClusterWeight. +TEST_P(LdsRdsTest, + RejectsHttpFilterWithoutConfigInFilterConfigInClusterWeight) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* cluster_weight = route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_route() + ->mutable_weighted_clusters() + ->add_clusters(); + cluster_weight->set_name(kDefaultClusterName); + cluster_weight->mutable_weight()->set_value(100); + auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); + (*per_filter_config)["unknown"].PackFrom( + ::envoy::config::route::v3::FilterConfig()); + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Wait until xDS server sees NACK. + do { + CheckRpcSendFailure(); + } while (RouteConfigurationResponseState(0).state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = RouteConfigurationResponseState(0); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr( + "no filter config specified for filter name unknown")); +} + +// Test that we ignore optional filters without configs in ClusterWeight. +TEST_P(LdsRdsTest, IgnoresOptionalHttpFilterWithoutConfigInClusterWeight) { + if (GetParam().use_v2()) return; // Filters supported in v3 only. + RouteConfiguration route_config = default_route_config_; + auto* cluster_weight = route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_route() + ->mutable_weighted_clusters() + ->add_clusters(); + cluster_weight->set_name(kDefaultClusterName); + cluster_weight->mutable_weight()->set_value(100); + auto* per_filter_config = cluster_weight->mutable_typed_per_filter_config(); + ::envoy::config::route::v3::FilterConfig filter_config; + filter_config.set_is_optional(true); + (*per_filter_config)["unknown"].PackFrom(filter_config); + SetListenerAndRouteConfiguration(0, default_listener_, route_config); + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -5816,13 +6337,11 @@ TEST_P(LdsRdsTest, IgnoresOptionalUnknownHttpFilterTypeInClusterWeight) { WaitForAllBackends(); EXPECT_EQ(RouteConfigurationResponseState(0).state, AdsServiceImpl::ResponseState::ACKED); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } // Test that we NACK unparseable filter types in ClusterWeight. TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInClusterWeight) { if (GetParam().use_v2()) return; // Filters supported in v3 only. - gpr_setenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION", "true"); RouteConfiguration route_config = default_route_config_; auto* cluster_weight = route_config.mutable_virtual_hosts(0) ->mutable_routes(0) @@ -5847,13 +6366,8 @@ TEST_P(LdsRdsTest, RejectsUnparseableHttpFilterTypeInClusterWeight) { EXPECT_THAT( response_state.error_message, ::testing::HasSubstr("router filter does not support config override")); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_FAULT_INJECTION"); } -// TODO(lidiz): As part of adding the fault injection filter, add tests -// for overriding filter configs in the typed_per_filter_config fields in -// each of VirtualHost, Route, and ClusterWeight. - using CdsTest = BasicTest; // Tests that CDS client should send an ACK upon correct CDS response. @@ -5899,10 +6413,10 @@ TEST_P(CdsTest, AggregateClusterType) { SetNextResolutionForLbChannelAllBalancers(); // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args1, kNewEdsService1Name)); @@ -5932,7 +6446,7 @@ TEST_P(CdsTest, AggregateClusterType) { WaitForBackend(1); // Shutdown backend 1 and wait for all traffic to go to backend 2. ShutdownBackend(1); - WaitForBackend(2); + WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true)); EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state, AdsServiceImpl::ResponseState::ACKED); // Bring backend 1 back and ensure all traffic go back to it. @@ -5952,7 +6466,7 @@ TEST_P(CdsTest, AggregateClusterEdsToLogicalDns) { const char* kLogicalDNSClusterName = "logical_dns_cluster"; // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args1({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args1, kNewEdsService1Name)); @@ -5988,7 +6502,7 @@ TEST_P(CdsTest, AggregateClusterEdsToLogicalDns) { WaitForBackend(1); // Shutdown backend 1 and wait for all traffic to go to backend 2. ShutdownBackend(1); - WaitForBackend(2); + WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true)); EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state, AdsServiceImpl::ResponseState::ACKED); // Bring backend 1 back and ensure all traffic go back to it. @@ -6008,7 +6522,7 @@ TEST_P(CdsTest, AggregateClusterLogicalDnsToEds) { const char* kLogicalDNSClusterName = "logical_dns_cluster"; // Populate new EDS resources. AdsServiceImpl::EdsResourceArgs args2({ - {"locality0", GetBackendPorts(2, 3)}, + {"locality0", CreateEndpointsForBackends(2, 3)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args2, kNewEdsService2Name)); @@ -6044,7 +6558,7 @@ TEST_P(CdsTest, AggregateClusterLogicalDnsToEds) { WaitForBackend(1); // Shutdown backend 1 and wait for all traffic to go to backend 2. ShutdownBackend(1); - WaitForBackend(2); + WaitForBackend(2, WaitForBackendOptions().set_allow_failures(true)); EXPECT_EQ(balancers_[0]->ads_service()->cds_response_state().state, AdsServiceImpl::ResponseState::ACKED); // Bring backend 1 back and ensure all traffic go back to it. @@ -6224,7 +6738,7 @@ class XdsSecurityTest : public BasicTest { "waterzooi.test.google.be", "*.test.youtube.com", "192.168.1.3"}; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -6300,7 +6814,7 @@ class XdsSecurityTest : public BasicTest { continue; } } else { - WaitForBackend(0); + WaitForBackend(0, WaitForBackendOptions().set_allow_failures(true)); Status status = SendRpc(); if (!status.ok()) { gpr_log(GPR_ERROR, "RPC failed. code=%d message=%s Trying again.", @@ -6816,7 +7330,7 @@ class XdsEnabledServerTest : public XdsEnd2endTest { void SetUp() override { XdsEnd2endTest::SetUp(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -6834,14 +7348,10 @@ TEST_P(XdsEnabledServerTest, Basic) { ipv6_only_ ? "::1" : "127.0.0.1"); listener.mutable_address()->mutable_socket_address()->set_port_value( backends_[0]->port()); - listener.add_filter_chains(); - balancers_[0]->ads_service()->SetLdsResource(listener); - listener.set_name( - absl::StrCat("grpc/server?xds.resource.listening_address=[::1]:", - backends_[0]->port())); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); balancers_[0]->ads_service()->SetLdsResource(listener); WaitForBackend(0); - CheckRpcSendOk(); } TEST_P(XdsEnabledServerTest, BadLdsUpdateNoApiListenerNorAddress) { @@ -6849,9 +7359,13 @@ TEST_P(XdsEnabledServerTest, BadLdsUpdateNoApiListenerNorAddress) { listener.set_name( absl::StrCat("grpc/server?xds.resource.listening_address=", ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); - listener.add_filter_chains(); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); balancers_[0]->ads_service()->SetLdsResource(listener); - CheckRpcSendFailure(1, RpcOptions().set_wait_for_ready(true)); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); const auto response_state = balancers_[0]->ads_service()->lds_response_state(); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); @@ -6871,11 +7385,14 @@ TEST_P(XdsEnabledServerTest, BadLdsUpdateBothApiListenerAndAddress) { listener.mutable_address()->mutable_socket_address()->set_port_value( backends_[0]->port()); auto* filter_chain = listener.add_filter_chains(); - auto* transport_socket = filter_chain->mutable_transport_socket(); - transport_socket->set_name("envoy.transport_sockets.tls"); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); listener.mutable_api_listener(); balancers_[0]->ads_service()->SetLdsResource(listener); - CheckRpcSendFailure(1, RpcOptions().set_wait_for_ready(true)); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); const auto response_state = balancers_[0]->ads_service()->lds_response_state(); EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); @@ -6884,30 +7401,198 @@ TEST_P(XdsEnabledServerTest, BadLdsUpdateBothApiListenerAndAddress) { ::testing::HasSubstr("Listener has both address and ApiListener")); } -class XdsServerSecurityTest : public XdsEnd2endTest { - protected: - XdsServerSecurityTest() - : XdsEnd2endTest(1, 1, 100, true /* use_xds_enabled_server */) {} - - static void SetUpTestCase() { - gpr_setenv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT", "true"); - XdsEnd2endTest::SetUpTestCase(); - } - - static void TearDownTestCase() { - XdsEnd2endTest::TearDownTestCase(); - gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"); - } +TEST_P(XdsEnabledServerTest, UnsupportedL4Filter) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + balancers_[0]->ads_service()->SetLdsResource(listener); + listener.mutable_address()->mutable_socket_address()->set_address( + ipv6_only_ ? "::1" : "127.0.0.1"); + listener.mutable_address()->mutable_socket_address()->set_port_value( + backends_[0]->port()); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom(default_listener_ /* any proto object other than HttpConnectionManager */); + balancers_[0]->ads_service()->SetLdsResource(listener); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr("Unsupported filter type")); +} - void SetUp() override { - XdsEnd2endTest::SetUp(); - root_cert_ = ReadFile(kCaCertPath); - bad_root_cert_ = ReadFile(kBadClientCertPath); - identity_pair_ = ReadTlsIdentityPair(kServerKeyPath, kServerCertPath); - bad_identity_pair_ = - ReadTlsIdentityPair(kBadClientKeyPath, kBadClientCertPath); - identity_pair_2_ = ReadTlsIdentityPair(kClientKeyPath, kClientCertPath); - server_authenticated_identity_ = {"*.test.google.fr", +TEST_P(XdsEnabledServerTest, UnsupportedHttpFilter) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + listener.mutable_address()->mutable_socket_address()->set_address( + ipv6_only_ ? "::1" : "127.0.0.1"); + listener.mutable_address()->mutable_socket_address()->set_port_value( + backends_[0]->port()); + HttpConnectionManager http_connection_manager; + auto* http_filter = http_connection_manager.add_http_filters(); + http_filter->set_name("grpc.testing.unsupported_http_filter"); + http_filter->mutable_typed_config()->set_type_url( + "grpc.testing.unsupported_http_filter"); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom( + http_connection_manager); + balancers_[0]->ads_service()->SetLdsResource(listener); + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=[::1]:", + backends_[0]->port())); + balancers_[0]->ads_service()->SetLdsResource(listener); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT(response_state.error_message, + ::testing::HasSubstr("no filter registered for config type " + "grpc.testing.unsupported_http_filter")); +} + +TEST_P(XdsEnabledServerTest, HttpFilterNotSupportedOnServer) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + listener.mutable_address()->mutable_socket_address()->set_address( + ipv6_only_ ? "::1" : "127.0.0.1"); + listener.mutable_address()->mutable_socket_address()->set_port_value( + backends_[0]->port()); + HttpConnectionManager http_connection_manager; + auto* http_filter = http_connection_manager.add_http_filters(); + http_filter->set_name("grpc.testing.client_only_http_filter"); + http_filter->mutable_typed_config()->set_type_url( + "grpc.testing.client_only_http_filter"); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom( + http_connection_manager); + balancers_[0]->ads_service()->SetLdsResource(listener); + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=[::1]:", + backends_[0]->port())); + balancers_[0]->ads_service()->SetLdsResource(listener); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT( + response_state.error_message, + ::testing::HasSubstr("Filter grpc.testing.client_only_http_filter is not " + "supported on servers")); +} + +TEST_P(XdsEnabledServerTest, + HttpFilterNotSupportedOnServerIgnoredWhenOptional) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + listener.mutable_address()->mutable_socket_address()->set_address( + ipv6_only_ ? "::1" : "127.0.0.1"); + listener.mutable_address()->mutable_socket_address()->set_port_value( + backends_[0]->port()); + HttpConnectionManager http_connection_manager; + auto* http_filter = http_connection_manager.add_http_filters(); + http_filter->set_name("grpc.testing.client_only_http_filter"); + http_filter->mutable_typed_config()->set_type_url( + "grpc.testing.client_only_http_filter"); + http_filter->set_is_optional(true); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom( + http_connection_manager); + balancers_[0]->ads_service()->SetLdsResource(listener); + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=[::1]:", + backends_[0]->port())); + balancers_[0]->ads_service()->SetLdsResource(listener); + WaitForBackend(0); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::ACKED); +} + +// Verify that a mismatch of listening address results in "not serving" status. +TEST_P(XdsEnabledServerTest, ListenerAddressMismatch) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + listener.mutable_address()->mutable_socket_address()->set_address( + ipv6_only_ ? "::1" : "127.0.0.1"); + listener.mutable_address()->mutable_socket_address()->set_port_value( + backends_[0]->port()); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + balancers_[0]->ads_service()->SetLdsResource(listener); + WaitForBackend(0); + // Set a different listening address in the LDS update + listener.mutable_address()->mutable_socket_address()->set_address( + "192.168.1.1"); + balancers_[0]->ads_service()->SetLdsResource(listener); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::FAILED_PRECONDITION); +} + +TEST_P(XdsEnabledServerTest, UseOriginalDstNotSupported) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + balancers_[0]->ads_service()->SetLdsResource(listener); + listener.mutable_address()->mutable_socket_address()->set_address( + ipv6_only_ ? "::1" : "127.0.0.1"); + listener.mutable_address()->mutable_socket_address()->set_port_value( + backends_[0]->port()); + listener.add_filter_chains()->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + listener.mutable_use_original_dst()->set_value(true); + balancers_[0]->ads_service()->SetLdsResource(listener); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); + const auto response_state = + balancers_[0]->ads_service()->lds_response_state(); + EXPECT_EQ(response_state.state, AdsServiceImpl::ResponseState::NACKED); + EXPECT_THAT( + response_state.error_message, + ::testing::HasSubstr("Field \'use_original_dst\' is not supported.")); +} + +class XdsServerSecurityTest : public XdsEnd2endTest { + protected: + XdsServerSecurityTest() + : XdsEnd2endTest(1, 1, 100, true /* use_xds_enabled_server */) {} + + static void SetUpTestCase() { + gpr_setenv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT", "true"); + XdsEnd2endTest::SetUpTestCase(); + } + + static void TearDownTestCase() { + XdsEnd2endTest::TearDownTestCase(); + gpr_unsetenv("GRPC_XDS_EXPERIMENTAL_SECURITY_SUPPORT"); + } + + void SetUp() override { + XdsEnd2endTest::SetUp(); + root_cert_ = ReadFile(kCaCertPath); + bad_root_cert_ = ReadFile(kBadClientCertPath); + identity_pair_ = ReadTlsIdentityPair(kServerKeyPath, kServerCertPath); + bad_identity_pair_ = + ReadTlsIdentityPair(kBadClientKeyPath, kBadClientCertPath); + identity_pair_2_ = ReadTlsIdentityPair(kClientKeyPath, kClientCertPath); + server_authenticated_identity_ = {"*.test.google.fr", "waterzooi.test.google.be", "*.test.youtube.com", "192.168.1.3"}; server_authenticated_identity_2_ = {"testclient"}; @@ -6915,7 +7600,7 @@ class XdsServerSecurityTest : public XdsEnd2endTest { "waterzooi.test.google.be", "*.test.youtube.com", "192.168.1.3"}; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -6935,14 +7620,17 @@ class XdsServerSecurityTest : public XdsEnd2endTest { absl::string_view identity_certificate_name, bool require_client_certificates) { Listener listener; - listener.set_name( - absl::StrCat("grpc/server?xds.resource.listening_address=127.0.0.1:", - backends_[0]->port())); + listener.set_name(absl::StrCat( + ipv6_only_ ? "grpc/server?xds.resource.listening_address=[::1]:" + : "grpc/server?xds.resource.listening_address=127.0.0.1:", + backends_[0]->port())); listener.mutable_address()->mutable_socket_address()->set_address( - "127.0.0.1"); + ipv6_only_ ? "[::1]" : "127.0.0.1"); listener.mutable_address()->mutable_socket_address()->set_port_value( backends_[0]->port()); auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); if (!identity_instance_name.empty()) { auto* transport_socket = filter_chain->mutable_transport_socket(); transport_socket->set_name("envoy.transport_sockets.tls"); @@ -6969,11 +7657,6 @@ class XdsServerSecurityTest : public XdsEnd2endTest { downstream_tls_context); } balancers_[0]->ads_service()->SetLdsResource(listener); - listener.set_name( - absl::StrCat("grpc/server?xds.resource.listening_address=[::1]:", - backends_[0]->port())); - listener.mutable_address()->mutable_socket_address()->set_address("[::1]"); - balancers_[0]->ads_service()->SetLdsResource(listener); } std::shared_ptr CreateMtlsChannel() { @@ -7056,7 +7739,7 @@ class XdsServerSecurityTest : public XdsEnd2endTest { bool test_expects_failure = false) { gpr_log(GPR_INFO, "Sending RPC"); int num_tries = 0; - constexpr int kRetryCount = 10; + constexpr int kRetryCount = 100; for (; num_tries < kRetryCount; num_tries++) { auto channel = channel_creator(); auto stub = grpc::testing::EchoTestService::NewStub(channel); @@ -7130,6 +7813,8 @@ TEST_P(XdsServerSecurityTest, TlsConfigurationWithoutRootProviderInstance) { socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); socket_address->set_port_value(backends_[0]->port()); auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); auto* transport_socket = filter_chain->mutable_transport_socket(); transport_socket->set_name("envoy.transport_sockets.tls"); DownstreamTlsContext downstream_tls_context; @@ -7387,6 +8072,784 @@ TEST_P(XdsServerSecurityTest, TestFallbackToTls) { server_authenticated_identity_, {}); } +class XdsEnabledServerStatusNotificationTest : public XdsServerSecurityTest { + protected: + void SetValidLdsUpdate() { SetLdsUpdate("", "", "", "", false); } + + void SetInvalidLdsUpdate() { + Listener listener; + listener.set_name(absl::StrCat( + "grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + balancers_[0]->ads_service()->SetLdsResource(listener); + } + + void UnsetLdsUpdate() { + balancers_[0]->ads_service()->UnsetResource( + kLdsTypeUrl, absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", + backends_[0]->port())); + } +}; + +TEST_P(XdsEnabledServerStatusNotificationTest, ServingStatus) { + SetValidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::OK); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsEnabledServerStatusNotificationTest, NotServingStatus) { + SetInvalidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::UNAVAILABLE); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); +} + +TEST_P(XdsEnabledServerStatusNotificationTest, ErrorUpdateWhenAlreadyServing) { + SetValidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::OK); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); + // Invalid update does not lead to a change in the serving status. + SetInvalidLdsUpdate(); + do { + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); + } while (balancers_[0]->ads_service()->lds_response_state().state == + AdsServiceImpl::ResponseState::SENT); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::OK); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsEnabledServerStatusNotificationTest, + NotServingStatusToServingStatusTransition) { + SetInvalidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::UNAVAILABLE); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); + // Send a valid LDS update to change to serving status + SetValidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::OK); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +// This test verifies that the resource getting deleted when already serving +// results in future connections being dropped. +TEST_P(XdsEnabledServerStatusNotificationTest, + ServingStatusToNonServingStatusTransition) { + SetValidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::OK); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); + // Deleting the resource should result in a non-serving status. + UnsetLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::NOT_FOUND); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); +} + +TEST_P(XdsEnabledServerStatusNotificationTest, RepeatedServingStatusChanges) { + for (int i = 0; i < 5; i++) { + // Send a valid LDS update to get the server to start listening + SetValidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", + backends_[0]->port()), + grpc::StatusCode::OK); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); + // Deleting the resource will make the server start rejecting connections + UnsetLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", + backends_[0]->port()), + grpc::StatusCode::NOT_FOUND); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); + } +} + +TEST_P(XdsEnabledServerStatusNotificationTest, ExistingRpcsOnResourceDeletion) { + // Send a valid LDS update to get the server to start listening + SetValidLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::OK); + constexpr int kNumChannels = 10; + struct StreamingRpc { + std::shared_ptr channel; + std::unique_ptr stub; + ClientContext context; + std::unique_ptr> writer; + } streaming_rpcs[kNumChannels]; + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + for (int i = 0; i < kNumChannels; i++) { + streaming_rpcs[i].channel = CreateInsecureChannel(); + streaming_rpcs[i].stub = + grpc::testing::EchoTestService::NewStub(streaming_rpcs[i].channel); + streaming_rpcs[i].context.set_wait_for_ready(true); + streaming_rpcs[i].writer = streaming_rpcs[i].stub->RequestStream( + &streaming_rpcs[i].context, &response); + EXPECT_TRUE(streaming_rpcs[i].writer->Write(request)); + } + // Deleting the resource will make the server start rejecting connections + UnsetLdsUpdate(); + backends_[0]->notifier()->WaitOnServingStatusChange( + absl::StrCat(ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port()), + grpc::StatusCode::NOT_FOUND); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); + for (int i = 0; i < kNumChannels; i++) { + EXPECT_TRUE(streaming_rpcs[i].writer->Write(request)); + EXPECT_TRUE(streaming_rpcs[i].writer->WritesDone()); + EXPECT_TRUE(streaming_rpcs[i].writer->Finish().ok()); + // New RPCs on the existing channels should fail. + ClientContext new_context; + new_context.set_deadline(grpc_timeout_milliseconds_to_deadline(1000)); + EXPECT_FALSE( + streaming_rpcs[i].stub->Echo(&new_context, request, &response).ok()); + } +} + +using XdsServerFilterChainMatchTest = XdsServerSecurityTest; + +TEST_P(XdsServerFilterChainMatchTest, + DefaultFilterChainUsedWhenNoFilterChainMentioned) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + listener.mutable_default_filter_chain() + ->add_filters() + ->mutable_typed_config() + ->PackFrom(HttpConnectionManager()); + balancers_[0]->ads_service()->SetLdsResource(listener); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsServerFilterChainMatchTest, + DefaultFilterChainUsedWhenOtherFilterChainsDontMatch) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add a filter chain that will never get matched + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match() + ->mutable_destination_port() + ->set_value(8080); + // Add default filter chain that should get used + listener.mutable_default_filter_chain() + ->add_filters() + ->mutable_typed_config() + ->PackFrom(HttpConnectionManager()); + balancers_[0]->ads_service()->SetLdsResource(listener); + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsWithDestinationPortDontMatch) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with destination port that should never get matched + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match() + ->mutable_destination_port() + ->set_value(8080); + balancers_[0]->ads_service()->SetLdsResource(listener); + // RPC should fail since no matching filter chain was found and no default + // filter chain is configured. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); +} + +TEST_P(XdsServerFilterChainMatchTest, FilterChainsWithServerNamesDontMatch) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with server name that should never get matched + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_server_names("server_name"); + balancers_[0]->ads_service()->SetLdsResource(listener); + // RPC should fail since no matching filter chain was found and no default + // filter chain is configured. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsWithTransportProtocolsOtherThanRawBufferDontMatch) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with transport protocol "tls" that should never match + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_transport_protocol("tls"); + balancers_[0]->ads_service()->SetLdsResource(listener); + // RPC should fail since no matching filter chain was found and no default + // filter chain is configured. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsWithApplicationProtocolsDontMatch) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with application protocol that should never get matched + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_application_protocols("h2"); + balancers_[0]->ads_service()->SetLdsResource(listener); + // RPC should fail since no matching filter chain was found and no default + // filter chain is configured. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}, + true /* test_expects_failure */); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsWithTransportProtocolRawBufferIsPreferred) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with "raw_buffer" transport protocol + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_transport_protocol( + "raw_buffer"); + // Add another filter chain with no transport protocol set but application + // protocol set (fails match) + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_application_protocols("h2"); + balancers_[0]->ads_service()->SetLdsResource(listener); + // A successful RPC proves that filter chains that mention "raw_buffer" as the + // transport protocol are chosen as the best match in the round. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsWithMoreSpecificDestinationPrefixRangesArePreferred) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with prefix range (length 4 and 16) but with server name + // mentioned. (Prefix range is matched first.) + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + auto* prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(4); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(16); + filter_chain->mutable_filter_chain_match()->add_server_names("server_name"); + // Add filter chain with two prefix ranges (length 8 and 24). Since 24 is the + // highest match, it should be chosen. + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(8); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(24); + // Add another filter chain with a non-matching prefix range (with length 30) + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix("192.168.1.1"); + prefix_range->mutable_prefix_len()->set_value(30); + filter_chain->mutable_filter_chain_match()->add_server_names("server_name"); + // Add another filter chain with no prefix range mentioned + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_server_names("server_name"); + balancers_[0]->ads_service()->SetLdsResource(listener); + // A successful RPC proves that the filter chain with the longest matching + // prefix range was the best match. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsThatMentionSourceTypeArePreferred) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with the local source type (best match) + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_source_type( + FilterChainMatch::SAME_IP_OR_LOOPBACK); + // Add filter chain with the external source type but bad source port. + // Note that backends_[0]->port() will never be a match for the source port + // because it is already being used by a backend. + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_source_type( + FilterChainMatch::EXTERNAL); + filter_chain->mutable_filter_chain_match()->add_source_ports( + backends_[0]->port()); + // Add filter chain with the default source type (ANY) but bad source port. + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_source_ports( + backends_[0]->port()); + balancers_[0]->ads_service()->SetLdsResource(listener); + // A successful RPC proves that the filter chain with the longest matching + // prefix range was the best match. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsWithMoreSpecificSourcePrefixRangesArePreferred) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with source prefix range (length 16) but with a bad source + // port mentioned. (Prefix range is matched first.) + // Note that backends_[0]->port() will never be a match for the source port + // because it is already being used by a backend. + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + auto* source_prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + source_prefix_range->mutable_prefix_len()->set_value(4); + source_prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + source_prefix_range->mutable_prefix_len()->set_value(16); + filter_chain->mutable_filter_chain_match()->add_source_ports( + backends_[0]->port()); + // Add filter chain with two source prefix ranges (length 8 and 24). Since 24 + // is the highest match, it should be chosen. + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + source_prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + source_prefix_range->mutable_prefix_len()->set_value(8); + source_prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + source_prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + source_prefix_range->mutable_prefix_len()->set_value(24); + // Add another filter chain with a non-matching source prefix range (with + // length 30) and bad source port + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + source_prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + source_prefix_range->set_address_prefix("192.168.1.1"); + source_prefix_range->mutable_prefix_len()->set_value(30); + filter_chain->mutable_filter_chain_match()->add_source_ports( + backends_[0]->port()); + // Add another filter chain with no source prefix range mentioned and bad + // source port + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_source_ports( + backends_[0]->port()); + balancers_[0]->ads_service()->SetLdsResource(listener); + // A successful RPC proves that the filter chain with the longest matching + // source prefix range was the best match. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsServerFilterChainMatchTest, + FilterChainsWithMoreSpecificSourcePortArePreferred) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + // Since we don't know which port will be used by the channel, just add all + // ports except for 0. + for (int i = 1; i < 65536; i++) { + filter_chain->mutable_filter_chain_match()->add_source_ports(i); + } + // Add another filter chain with no source prefix range mentioned with a bad + // DownstreamTlsContext configuration. + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + auto* transport_socket = filter_chain->mutable_transport_socket(); + transport_socket->set_name("envoy.transport_sockets.tls"); + DownstreamTlsContext downstream_tls_context; + downstream_tls_context.mutable_common_tls_context() + ->mutable_tls_certificate_certificate_provider_instance() + ->set_instance_name("unknown"); + transport_socket->mutable_typed_config()->PackFrom(downstream_tls_context); + balancers_[0]->ads_service()->SetLdsResource(listener); + // A successful RPC proves that the filter chain with matching source port + // was chosen. + SendRpc([this]() { return CreateInsecureChannel(); }, {}, {}); +} + +TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchNacked) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + // Add a duplicate filter chain + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + balancers_[0]->ads_service()->SetLdsResource(listener); + auto initial_time = absl::Now(); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state != + AdsServiceImpl::ResponseState::NACKED && + initial_time + absl::Seconds(60) > absl::Now()); + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr( + "Duplicate matching rules detected when adding filter chain: {}")); +} + +TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnPrefixRangesNacked) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with prefix range + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + auto* prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(16); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(24); + // Add a filter chain with a duplicate prefix range entry + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(16); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(32); + balancers_[0]->ads_service()->SetLdsResource(listener); + auto initial_time = absl::Now(); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state != + AdsServiceImpl::ResponseState::NACKED && + initial_time + absl::Seconds(60) > absl::Now()); + if (ipv6_only_) { + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr( + "Duplicate matching rules detected when adding filter chain: " + "{prefix_ranges={{address_prefix=[::]:0, prefix_len=16}, " + "{address_prefix=[::]:0, prefix_len=32}}}")); + } else { + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr( + "Duplicate matching rules detected when adding filter chain: " + "{prefix_ranges={{address_prefix=127.0.0.0:0, prefix_len=16}, " + "{address_prefix=127.0.0.1:0, prefix_len=32}}}")); + } +} + +TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnTransportProtocolNacked) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with "raw_buffer" transport protocol + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_transport_protocol( + "raw_buffer"); + // Add a duplicate filter chain with the same "raw_buffer" transport protocol + // entry + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_transport_protocol( + "raw_buffer"); + balancers_[0]->ads_service()->SetLdsResource(listener); + auto initial_time = absl::Now(); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state != + AdsServiceImpl::ResponseState::NACKED && + initial_time + absl::Seconds(60) > absl::Now()); + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr("Duplicate matching rules detected when adding " + "filter chain: {transport_protocol=raw_buffer}")); +} + +TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnLocalSourceTypeNacked) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with the local source type + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_source_type( + FilterChainMatch::SAME_IP_OR_LOOPBACK); + // Add a duplicate filter chain with the same local source type entry + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_source_type( + FilterChainMatch::SAME_IP_OR_LOOPBACK); + balancers_[0]->ads_service()->SetLdsResource(listener); + auto initial_time = absl::Now(); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state != + AdsServiceImpl::ResponseState::NACKED && + initial_time + absl::Seconds(60) > absl::Now()); + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr("Duplicate matching rules detected when adding " + "filter chain: {source_type=SAME_IP_OR_LOOPBACK}")); +} + +TEST_P(XdsServerFilterChainMatchTest, + DuplicateMatchOnExternalSourceTypeNacked) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with the external source type + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_source_type( + FilterChainMatch::EXTERNAL); + // Add a duplicate filter chain with the same external source type entry + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->set_source_type( + FilterChainMatch::EXTERNAL); + balancers_[0]->ads_service()->SetLdsResource(listener); + auto initial_time = absl::Now(); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state != + AdsServiceImpl::ResponseState::NACKED && + initial_time + absl::Seconds(60) > absl::Now()); + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr("Duplicate matching rules detected when adding " + "filter chain: {source_type=EXTERNAL}")); +} + +TEST_P(XdsServerFilterChainMatchTest, + DuplicateMatchOnSourcePrefixRangesNacked) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with source prefix range + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + auto* prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(16); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(24); + // Add a filter chain with a duplicate source prefix range entry + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(16); + prefix_range = + filter_chain->mutable_filter_chain_match()->add_source_prefix_ranges(); + prefix_range->set_address_prefix(ipv6_only_ ? "::1" : "127.0.0.1"); + prefix_range->mutable_prefix_len()->set_value(32); + balancers_[0]->ads_service()->SetLdsResource(listener); + auto initial_time = absl::Now(); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state != + AdsServiceImpl::ResponseState::NACKED && + initial_time + absl::Seconds(60) > absl::Now()); + if (ipv6_only_) { + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr( + "Duplicate matching rules detected when adding filter chain: " + "{source_prefix_ranges={{address_prefix=[::]:0, prefix_len=16}, " + "{address_prefix=[::]:0, prefix_len=32}}}")); + } else { + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr( + "Duplicate matching rules detected when adding filter chain: " + "{source_prefix_ranges={{address_prefix=127.0.0.0:0, " + "prefix_len=16}, " + "{address_prefix=127.0.0.1:0, prefix_len=32}}}")); + } +} + +TEST_P(XdsServerFilterChainMatchTest, DuplicateMatchOnSourcePortNacked) { + Listener listener; + listener.set_name( + absl::StrCat("grpc/server?xds.resource.listening_address=", + ipv6_only_ ? "[::1]:" : "127.0.0.1:", backends_[0]->port())); + auto* socket_address = listener.mutable_address()->mutable_socket_address(); + socket_address->set_address(ipv6_only_ ? "::1" : "127.0.0.1"); + socket_address->set_port_value(backends_[0]->port()); + // Add filter chain with the external source type + auto* filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_source_ports(8080); + // Add a duplicate filter chain with the same source port entry + filter_chain = listener.add_filter_chains(); + filter_chain->add_filters()->mutable_typed_config()->PackFrom( + HttpConnectionManager()); + filter_chain->mutable_filter_chain_match()->add_source_ports(8080); + balancers_[0]->ads_service()->SetLdsResource(listener); + auto initial_time = absl::Now(); + do { + CheckRpcSendFailure(); + } while (balancers_[0]->ads_service()->lds_response_state().state != + AdsServiceImpl::ResponseState::NACKED && + initial_time + absl::Seconds(60) > absl::Now()); + EXPECT_THAT( + balancers_[0]->ads_service()->lds_response_state().error_message, + ::testing::HasSubstr("Duplicate matching rules detected when adding " + "filter chain: {source_ports={8080}}")); +} + using EdsTest = BasicTest; // Tests that EDS client should send a NACK if the EDS update contains @@ -7395,7 +8858,7 @@ TEST_P(EdsTest, NacksSparsePriorityList) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(), kDefaultLocalityWeight, 1}, + {"locality0", CreateEndpointsForBackends(), kDefaultLocalityWeight, 1}, }); balancers_[0]->ads_service()->SetEdsResource(BuildEdsResource(args)); CheckRpcSendFailure(); @@ -7413,7 +8876,7 @@ TEST_P(EdsTest, NacksSparsePriorityList) { // cluster name if not specified in the CDS resource. TEST_P(EdsTest, EdsServiceNameDefaultsToClusterName) { AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, kDefaultClusterName)); @@ -7470,7 +8933,6 @@ using LocalityMapTest = BasicTest; TEST_P(LocalityMapTest, WeightedRoundRobin) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - const size_t kNumRpcs = 5000; const int kLocalityWeight0 = 2; const int kLocalityWeight1 = 8; const int kTotalLocalityWeight = kLocalityWeight0 + kLocalityWeight1; @@ -7478,10 +8940,13 @@ TEST_P(LocalityMapTest, WeightedRoundRobin) { static_cast(kLocalityWeight0) / kTotalLocalityWeight; const double kLocalityWeightRate1 = static_cast(kLocalityWeight1) / kTotalLocalityWeight; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = + ComputeIdealNumRpcs(kLocalityWeightRate0, kErrorTolerance); // ADS response contains 2 localities, each of which contains 1 backend. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kLocalityWeight0}, - {"locality1", GetBackendPorts(1, 2), kLocalityWeight1}, + {"locality0", CreateEndpointsForBackends(0, 1), kLocalityWeight0}, + {"locality1", CreateEndpointsForBackends(1, 2), kLocalityWeight1}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -7496,15 +8961,10 @@ TEST_P(LocalityMapTest, WeightedRoundRobin) { const double locality_picked_rate_1 = static_cast(backends_[1]->backend_service()->request_count()) / kNumRpcs; - const double kErrorTolerance = 0.2; EXPECT_THAT(locality_picked_rate_0, - ::testing::AllOf( - ::testing::Ge(kLocalityWeightRate0 * (1 - kErrorTolerance)), - ::testing::Le(kLocalityWeightRate0 * (1 + kErrorTolerance)))); + ::testing::DoubleNear(kLocalityWeightRate0, kErrorTolerance)); EXPECT_THAT(locality_picked_rate_1, - ::testing::AllOf( - ::testing::Ge(kLocalityWeightRate1 * (1 - kErrorTolerance)), - ::testing::Le(kLocalityWeightRate1 * (1 + kErrorTolerance)))); + ::testing::DoubleNear(kLocalityWeightRate1, kErrorTolerance)); } // Tests that we correctly handle a locality containing no endpoints. @@ -7514,7 +8974,7 @@ TEST_P(LocalityMapTest, LocalityContainingNoEndpoints) { const size_t kNumRpcs = 5000; // EDS response contains 2 localities, one with no endpoints. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, {"locality1", {}}, }); balancers_[0]->ads_service()->SetEdsResource( @@ -7551,27 +9011,29 @@ TEST_P(LocalityMapTest, StressTest) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); const size_t kNumLocalities = 100; + const uint32_t kRpcTimeoutMs = 5000; // The first ADS response contains kNumLocalities localities, each of which // contains backend 0. AdsServiceImpl::EdsResourceArgs args; for (size_t i = 0; i < kNumLocalities; ++i) { std::string name = absl::StrCat("locality", i); - AdsServiceImpl::EdsResourceArgs::Locality locality(name, - {backends_[0]->port()}); + AdsServiceImpl::EdsResourceArgs::Locality locality( + name, CreateEndpointsForBackends(0, 1)); args.locality_list.emplace_back(std::move(locality)); } balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); // The second ADS response contains 1 locality, which contains backend 1. args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", GetBackendPorts(1, 2)}, + {"locality0", CreateEndpointsForBackends(1, 2)}, }); std::thread delayed_resource_setter( std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0, BuildEdsResource(args, DefaultEdsServiceName()), 60 * 1000)); // Wait until backend 0 is ready, before which kNumLocalities localities are // received and handled by the xds policy. - WaitForBackend(0, /*reset_counters=*/false); + WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false), + RpcOptions().set_timeout_ms(kRpcTimeoutMs)); EXPECT_EQ(0U, backends_[1]->backend_service()->request_count()); // Wait until backend 1 is ready, before which kNumLocalities localities are // removed by the xds policy. @@ -7605,9 +9067,9 @@ TEST_P(LocalityMapTest, UpdateMap) { locality_weight_rate_1.push_back(weight / kTotalLocalityWeight1); } AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), 2}, - {"locality1", GetBackendPorts(1, 2), 3}, - {"locality2", GetBackendPorts(2, 3), 4}, + {"locality0", CreateEndpointsForBackends(0, 1), 2}, + {"locality1", CreateEndpointsForBackends(1, 2), 3}, + {"locality2", CreateEndpointsForBackends(2, 3), 4}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -7636,9 +9098,9 @@ TEST_P(LocalityMapTest, UpdateMap) { ::testing::Le(locality_weight_rate_0[i] * (1 + kErrorTolerance)))); } args = AdsServiceImpl::EdsResourceArgs({ - {"locality1", GetBackendPorts(1, 2), 3}, - {"locality2", GetBackendPorts(2, 3), 2}, - {"locality3", GetBackendPorts(3, 4), 6}, + {"locality1", CreateEndpointsForBackends(1, 2), 3}, + {"locality2", CreateEndpointsForBackends(2, 3), 2}, + {"locality3", CreateEndpointsForBackends(3, 4), 6}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -7678,12 +9140,12 @@ TEST_P(LocalityMapTest, ReplaceAllLocalitiesInPriority) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1)}, + {"locality0", CreateEndpointsForBackends(0, 1)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); args = AdsServiceImpl::EdsResourceArgs({ - {"locality1", GetBackendPorts(1, 2)}, + {"locality1", CreateEndpointsForBackends(1, 2)}, }); std::thread delayed_resource_setter( std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0, @@ -7693,7 +9155,7 @@ TEST_P(LocalityMapTest, ReplaceAllLocalitiesInPriority) { // Keep sending RPCs until we switch over to backend 1, which tells us // that we received the update. No RPCs should fail during this // transition. - WaitForBackend(1, /*reset_counters=*/true, /*require_success=*/true); + WaitForBackend(1); delayed_resource_setter.join(); } @@ -7710,14 +9172,18 @@ TEST_P(FailoverTest, ChooseHighestPriority) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, - {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, - {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 1}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 2}, + {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight, + 3}, + {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight, + 0}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); - WaitForBackend(3, false); + WaitForBackend(3, WaitForBackendOptions().set_reset_counters(false)); for (size_t i = 0; i < 3; ++i) { EXPECT_EQ(0U, backends_[i]->backend_service()->request_count()); } @@ -7728,14 +9194,17 @@ TEST_P(FailoverTest, DoesNotUsePriorityWithNoEndpoints) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, - {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 1}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 2}, + {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight, + 3}, {"locality3", {}, kDefaultLocalityWeight, 0}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); - WaitForBackend(0, false); + WaitForBackend(0, WaitForBackendOptions().set_reset_counters(false)); for (size_t i = 1; i < 3; ++i) { EXPECT_EQ(0U, backends_[i]->backend_service()->request_count()); } @@ -7747,7 +9216,7 @@ TEST_P(FailoverTest, DoesNotUseLocalityWithNoEndpoints) { SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ {"locality0", {}, kDefaultLocalityWeight, 0}, - {"locality1", GetBackendPorts(), kDefaultLocalityWeight, 0}, + {"locality1", CreateEndpointsForBackends(), kDefaultLocalityWeight, 0}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -7763,16 +9232,20 @@ TEST_P(FailoverTest, Failover) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, - {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, - {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 1}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 2}, + {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight, + 3}, + {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight, + 0}, }); ShutdownBackend(3); ShutdownBackend(0); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); - WaitForBackend(1, false); + WaitForBackend(1, WaitForBackendOptions().set_reset_counters(false)); for (size_t i = 0; i < 4; ++i) { if (i == 1) continue; EXPECT_EQ(0U, backends_[i]->backend_service()->request_count()); @@ -7786,17 +9259,23 @@ TEST_P(FailoverTest, SwitchBackToHigherPriority) { SetNextResolutionForLbChannelAllBalancers(); const size_t kNumRpcs = 100; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, - {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, - {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 1}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 2}, + {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight, + 3}, + {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight, + 0}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); WaitForBackend(3); ShutdownBackend(3); ShutdownBackend(0); - WaitForBackend(1, false); + WaitForBackend( + 1, WaitForBackendOptions().set_reset_counters(false).set_allow_failures( + true)); for (size_t i = 0; i < 4; ++i) { if (i == 1) continue; EXPECT_EQ(0U, backends_[i]->backend_service()->request_count()); @@ -7813,16 +9292,22 @@ TEST_P(FailoverTest, UpdateInitialUnavailable) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 1}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 0}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 1}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 1}, - {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 2}, - {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 3}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 0}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 1}, + {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight, + 2}, + {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight, + 3}, }); ShutdownBackend(0); ShutdownBackend(1); @@ -7835,7 +9320,9 @@ TEST_P(FailoverTest, UpdateInitialUnavailable) { do { CheckRpcSendFailure(); } while (gpr_time_cmp(gpr_now(GPR_CLOCK_REALTIME), deadline) < 0); - WaitForBackend(2, false); + WaitForBackend( + 2, WaitForBackendOptions().set_reset_counters(false).set_allow_failures( + true)); for (size_t i = 0; i < 4; ++i) { if (i == 2) continue; EXPECT_EQ(0U, backends_[i]->backend_service()->request_count()); @@ -7850,23 +9337,31 @@ TEST_P(FailoverTest, UpdatePriority) { SetNextResolutionForLbChannelAllBalancers(); const size_t kNumRpcs = 100; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 1}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 2}, - {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 3}, - {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 0}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 1}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 2}, + {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight, + 3}, + {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight, + 0}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 2}, - {"locality1", GetBackendPorts(1, 2), kDefaultLocalityWeight, 0}, - {"locality2", GetBackendPorts(2, 3), kDefaultLocalityWeight, 1}, - {"locality3", GetBackendPorts(3, 4), kDefaultLocalityWeight, 3}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 2}, + {"locality1", CreateEndpointsForBackends(1, 2), kDefaultLocalityWeight, + 0}, + {"locality2", CreateEndpointsForBackends(2, 3), kDefaultLocalityWeight, + 1}, + {"locality3", CreateEndpointsForBackends(3, 4), kDefaultLocalityWeight, + 3}, }); std::thread delayed_resource_setter( std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0, BuildEdsResource(args, DefaultEdsServiceName()), 1000)); - WaitForBackend(3, false); + WaitForBackend(3, WaitForBackendOptions().set_reset_counters(false)); for (size_t i = 0; i < 3; ++i) { EXPECT_EQ(0U, backends_[i]->backend_service()->request_count()); } @@ -7885,8 +9380,10 @@ TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) { // - Priority 1 is locality 1, containing backends 1 and 2, which are up. ShutdownBackend(0); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0}, - {"locality1", GetBackendPorts(1, 3), kDefaultLocalityWeight, 1}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 0}, + {"locality1", CreateEndpointsForBackends(1, 3), kDefaultLocalityWeight, + 1}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -7896,8 +9393,10 @@ TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) { // - We add backend 3 to locality 1, just so we have a way to know // when the update has been seen by the client. args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", GetBackendPorts(0, 1), kDefaultLocalityWeight, 0}, - {"locality1", GetBackendPorts(1, 4), kDefaultLocalityWeight, 0}, + {"locality0", CreateEndpointsForBackends(0, 1), kDefaultLocalityWeight, + 0}, + {"locality1", CreateEndpointsForBackends(1, 4), kDefaultLocalityWeight, + 0}, }); std::thread delayed_resource_setter( std::bind(&BasicTest::SetEdsResourceWithDelay, this, 0, @@ -7905,7 +9404,7 @@ TEST_P(FailoverTest, MoveAllLocalitiesInCurrentPriorityToHigherPriority) { // When we get the first update, all backends in priority 0 are down, // so we will create priority 1. Backends 1 and 2 should have traffic, // but backend 3 should not. - WaitForAllBackends(1, 3, false); + WaitForAllBackends(1, 3, WaitForBackendOptions().set_reset_counters(false)); EXPECT_EQ(0UL, backends_[3]->backend_service()->request_count()); // When backend 3 gets traffic, we know the second update has been seen. WaitForBackend(3); @@ -7921,16 +9420,18 @@ using DropTest = BasicTest; TEST_P(DropTest, Vanilla) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - const size_t kNumRpcs = 5000; const uint32_t kDropPerMillionForLb = 100000; const uint32_t kDropPerMillionForThrottle = 200000; const double kDropRateForLb = kDropPerMillionForLb / 1000000.0; const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0; - const double KDropRateForLbAndThrottle = + const double kDropRateForLbAndThrottle = kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = + ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance); // The ADS response contains two drop categories. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); args.drop_categories = {{kLbDropType, kDropPerMillionForLb}, {kThrottleDropType, kDropPerMillionForThrottle}}; @@ -7953,24 +9454,21 @@ TEST_P(DropTest, Vanilla) { } // The drop rate should be roughly equal to the expectation. const double seen_drop_rate = static_cast(num_drops) / kNumRpcs; - const double kErrorTolerance = 0.2; - EXPECT_THAT( - seen_drop_rate, - ::testing::AllOf( - ::testing::Ge(KDropRateForLbAndThrottle * (1 - kErrorTolerance)), - ::testing::Le(KDropRateForLbAndThrottle * (1 + kErrorTolerance)))); + EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle, + kErrorTolerance)); } // Tests that drop config is converted correctly from per hundred. TEST_P(DropTest, DropPerHundred) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - const size_t kNumRpcs = 5000; const uint32_t kDropPerHundredForLb = 10; const double kDropRateForLb = kDropPerHundredForLb / 100.0; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance); // The ADS response contains one drop category. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); args.drop_categories = {{kLbDropType, kDropPerHundredForLb}}; args.drop_denominator = FractionalPercent::HUNDRED; @@ -7993,23 +9491,21 @@ TEST_P(DropTest, DropPerHundred) { } // The drop rate should be roughly equal to the expectation. const double seen_drop_rate = static_cast(num_drops) / kNumRpcs; - const double kErrorTolerance = 0.2; - EXPECT_THAT( - seen_drop_rate, - ::testing::AllOf(::testing::Ge(kDropRateForLb * (1 - kErrorTolerance)), - ::testing::Le(kDropRateForLb * (1 + kErrorTolerance)))); + EXPECT_THAT(seen_drop_rate, + ::testing::DoubleNear(kDropRateForLb, kErrorTolerance)); } // Tests that drop config is converted correctly from per ten thousand. TEST_P(DropTest, DropPerTenThousand) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - const size_t kNumRpcs = 5000; const uint32_t kDropPerTenThousandForLb = 1000; const double kDropRateForLb = kDropPerTenThousandForLb / 10000.0; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance); // The ADS response contains one drop category. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); args.drop_categories = {{kLbDropType, kDropPerTenThousandForLb}}; args.drop_denominator = FractionalPercent::TEN_THOUSAND; @@ -8032,36 +9528,37 @@ TEST_P(DropTest, DropPerTenThousand) { } // The drop rate should be roughly equal to the expectation. const double seen_drop_rate = static_cast(num_drops) / kNumRpcs; - const double kErrorTolerance = 0.2; - EXPECT_THAT( - seen_drop_rate, - ::testing::AllOf(::testing::Ge(kDropRateForLb * (1 - kErrorTolerance)), - ::testing::Le(kDropRateForLb * (1 + kErrorTolerance)))); + EXPECT_THAT(seen_drop_rate, + ::testing::DoubleNear(kDropRateForLb, kErrorTolerance)); } // Tests that drop is working correctly after update. TEST_P(DropTest, Update) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - const size_t kNumRpcs = 3000; const uint32_t kDropPerMillionForLb = 100000; const uint32_t kDropPerMillionForThrottle = 200000; + const double kErrorTolerance = 0.05; const double kDropRateForLb = kDropPerMillionForLb / 1000000.0; const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0; - const double KDropRateForLbAndThrottle = + const double kDropRateForLbAndThrottle = kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle; + const size_t kNumRpcsLbOnly = + ComputeIdealNumRpcs(kDropRateForLb, kErrorTolerance); + const size_t kNumRpcsBoth = + ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance); // The first ADS response contains one drop category. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); args.drop_categories = {{kLbDropType, kDropPerMillionForLb}}; balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); WaitForAllBackends(); - // Send kNumRpcs RPCs and count the drops. + // Send kNumRpcsLbOnly RPCs and count the drops. size_t num_drops = 0; gpr_log(GPR_INFO, "========= BEFORE FIRST BATCH =========="); - for (size_t i = 0; i < kNumRpcs; ++i) { + for (size_t i = 0; i < kNumRpcsLbOnly; ++i) { EchoResponse response; const Status status = SendRpc(RpcOptions(), &response); if (!status.ok() && @@ -8075,13 +9572,10 @@ TEST_P(DropTest, Update) { } gpr_log(GPR_INFO, "========= DONE WITH FIRST BATCH =========="); // The drop rate should be roughly equal to the expectation. - double seen_drop_rate = static_cast(num_drops) / kNumRpcs; + double seen_drop_rate = static_cast(num_drops) / kNumRpcsLbOnly; gpr_log(GPR_INFO, "First batch drop rate %f", seen_drop_rate); - const double kErrorTolerance = 0.3; - EXPECT_THAT( - seen_drop_rate, - ::testing::AllOf(::testing::Ge(kDropRateForLb * (1 - kErrorTolerance)), - ::testing::Le(kDropRateForLb * (1 + kErrorTolerance)))); + EXPECT_THAT(seen_drop_rate, + ::testing::DoubleNear(kDropRateForLb, kErrorTolerance)); // The second ADS response contains two drop categories, send an update EDS // response. args.drop_categories = {{kLbDropType, kDropPerMillionForLb}, @@ -8091,8 +9585,8 @@ TEST_P(DropTest, Update) { // Wait until the drop rate increases to the middle of the two configs, which // implies that the update has been in effect. const double kDropRateThreshold = - (kDropRateForLb + KDropRateForLbAndThrottle) / 2; - size_t num_rpcs = kNumRpcs; + (kDropRateForLb + kDropRateForLbAndThrottle) / 2; + size_t num_rpcs = kNumRpcsBoth; while (seen_drop_rate < kDropRateThreshold) { EchoResponse response; const Status status = SendRpc(RpcOptions(), &response); @@ -8107,10 +9601,10 @@ TEST_P(DropTest, Update) { } seen_drop_rate = static_cast(num_drops) / num_rpcs; } - // Send kNumRpcs RPCs and count the drops. + // Send kNumRpcsBoth RPCs and count the drops. num_drops = 0; gpr_log(GPR_INFO, "========= BEFORE SECOND BATCH =========="); - for (size_t i = 0; i < kNumRpcs; ++i) { + for (size_t i = 0; i < kNumRpcsBoth; ++i) { EchoResponse response; const Status status = SendRpc(RpcOptions(), &response); if (!status.ok() && @@ -8124,13 +9618,10 @@ TEST_P(DropTest, Update) { } gpr_log(GPR_INFO, "========= DONE WITH SECOND BATCH =========="); // The new drop rate should be roughly equal to the expectation. - seen_drop_rate = static_cast(num_drops) / kNumRpcs; + seen_drop_rate = static_cast(num_drops) / kNumRpcsBoth; gpr_log(GPR_INFO, "Second batch drop rate %f", seen_drop_rate); - EXPECT_THAT( - seen_drop_rate, - ::testing::AllOf( - ::testing::Ge(KDropRateForLbAndThrottle * (1 - kErrorTolerance)), - ::testing::Le(KDropRateForLbAndThrottle * (1 + kErrorTolerance)))); + EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle, + kErrorTolerance)); } // Tests that all the RPCs are dropped if any drop category drops 100%. @@ -8165,14 +9656,12 @@ class BalancerUpdateTest : public XdsEnd2endTest { TEST_P(BalancerUpdateTest, UpdateBalancersButKeepUsingOriginalBalancer) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {backends_[0]->port()}}, - }); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); - args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", {backends_[1]->port()}}, - }); + args = AdsServiceImpl::EdsResourceArgs( + {{"locality0", CreateEndpointsForBackends(1, 2)}}); balancers_[1]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); // Wait until the first backend is ready. @@ -8228,14 +9717,12 @@ TEST_P(BalancerUpdateTest, UpdateBalancersButKeepUsingOriginalBalancer) { TEST_P(BalancerUpdateTest, Repeated) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {backends_[0]->port()}}, - }); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); - args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", {backends_[1]->port()}}, - }); + args = AdsServiceImpl::EdsResourceArgs( + {{"locality0", CreateEndpointsForBackends(1, 2)}}); balancers_[1]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); // Wait until the first backend is ready. @@ -8298,14 +9785,12 @@ TEST_P(BalancerUpdateTest, Repeated) { TEST_P(BalancerUpdateTest, DeadUpdate) { SetNextResolution({}); SetNextResolutionForLbChannel({balancers_[0]->port()}); - AdsServiceImpl::EdsResourceArgs args({ - {"locality0", {backends_[0]->port()}}, - }); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); - args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", {backends_[1]->port()}}, - }); + args = AdsServiceImpl::EdsResourceArgs( + {{"locality0", CreateEndpointsForBackends(1, 2)}}); balancers_[1]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); // Start servers and send 10 RPCs per server. @@ -8394,7 +9879,7 @@ TEST_P(ClientLoadReportingTest, Vanilla) { // TODO(juanlishen): Partition the backends after multiple localities is // tested. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -8441,7 +9926,7 @@ TEST_P(ClientLoadReportingTest, SendAllClusters) { // TODO(juanlishen): Partition the backends after multiple localities is // tested. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -8486,7 +9971,7 @@ TEST_P(ClientLoadReportingTest, HonorsClustersRequestedByLrsServer) { SetNextResolutionForLbChannel({balancers_[0]->port()}); const size_t kNumRpcsPerAddress = 100; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -8523,7 +10008,7 @@ TEST_P(ClientLoadReportingTest, BalancerRestart) { const size_t kNumBackendsSecondPass = backends_.size() - kNumBackendsFirstPass; AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts(0, kNumBackendsFirstPass)}, + {"locality0", CreateEndpointsForBackends(0, kNumBackendsFirstPass)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -8561,7 +10046,7 @@ TEST_P(ClientLoadReportingTest, BalancerRestart) { // Now restart the balancer, this time pointing to the new backends. balancers_[0]->Start(); args = AdsServiceImpl::EdsResourceArgs({ - {"locality0", GetBackendPorts(kNumBackendsFirstPass)}, + {"locality0", CreateEndpointsForBackends(kNumBackendsFirstPass)}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); @@ -8595,16 +10080,18 @@ TEST_P(ClientLoadReportingWithDropTest, Vanilla) { } SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); - const size_t kNumRpcs = 3000; const uint32_t kDropPerMillionForLb = 100000; const uint32_t kDropPerMillionForThrottle = 200000; + const double kErrorTolerance = 0.05; const double kDropRateForLb = kDropPerMillionForLb / 1000000.0; const double kDropRateForThrottle = kDropPerMillionForThrottle / 1000000.0; - const double KDropRateForLbAndThrottle = + const double kDropRateForLbAndThrottle = kDropRateForLb + (1 - kDropRateForLb) * kDropRateForThrottle; + const size_t kNumRpcs = + ComputeIdealNumRpcs(kDropRateForLbAndThrottle, kErrorTolerance); // The ADS response contains two drop categories. AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); args.drop_categories = {{kLbDropType, kDropPerMillionForLb}, {kThrottleDropType, kDropPerMillionForThrottle}}; @@ -8630,12 +10117,8 @@ TEST_P(ClientLoadReportingWithDropTest, Vanilla) { } // The drop rate should be roughly equal to the expectation. const double seen_drop_rate = static_cast(num_drops) / kNumRpcs; - const double kErrorTolerance = 0.2; - EXPECT_THAT( - seen_drop_rate, - ::testing::AllOf( - ::testing::Ge(KDropRateForLbAndThrottle * (1 - kErrorTolerance)), - ::testing::Le(KDropRateForLbAndThrottle * (1 + kErrorTolerance)))); + EXPECT_THAT(seen_drop_rate, ::testing::DoubleNear(kDropRateForLbAndThrottle, + kErrorTolerance)); // Check client stats. const size_t total_rpc = num_warmup + kNumRpcs; ClientStats client_stats; @@ -8649,35 +10132,1205 @@ TEST_P(ClientLoadReportingWithDropTest, Vanilla) { client_stats.total_dropped_requests() < total_rpc); EXPECT_EQ(num_drops, client_stats.total_dropped_requests()); + EXPECT_THAT(static_cast(client_stats.dropped_requests(kLbDropType)) / + total_rpc, + ::testing::DoubleNear(kDropRateForLb, kErrorTolerance)); EXPECT_THAT( - client_stats.dropped_requests(kLbDropType), - ::testing::AllOf( - ::testing::Ge(total_rpc * kDropRateForLb * (1 - kErrorTolerance)), - ::testing::Le(total_rpc * kDropRateForLb * (1 + kErrorTolerance)))); - EXPECT_THAT(client_stats.dropped_requests(kThrottleDropType), - ::testing::AllOf( - ::testing::Ge(total_rpc * (1 - kDropRateForLb) * - kDropRateForThrottle * (1 - kErrorTolerance)), - ::testing::Le(total_rpc * (1 - kDropRateForLb) * - kDropRateForThrottle * (1 + kErrorTolerance)))); + static_cast(client_stats.dropped_requests(kThrottleDropType)) / + (total_rpc * (1 - kDropRateForLb)), + ::testing::DoubleNear(kDropRateForThrottle, kErrorTolerance)); +} + +class FaultInjectionTest : public XdsEnd2endTest { + public: + FaultInjectionTest() : XdsEnd2endTest(1, 1) {} + + // Builds a Listener with Fault Injection filter config. If the http_fault is + // nullptr, then assign an empty filter config. This filter config is required + // to enable the fault injection features. + static Listener BuildListenerWithFaultInjection( + const HTTPFault& http_fault = HTTPFault()) { + HttpConnectionManager http_connection_manager; + Listener listener; + listener.set_name(kServerName); + HttpFilter* fault_filter = http_connection_manager.add_http_filters(); + fault_filter->set_name("envoy.fault"); + fault_filter->mutable_typed_config()->PackFrom(http_fault); + HttpFilter* router_filter = http_connection_manager.add_http_filters(); + router_filter->set_name("router"); + router_filter->mutable_typed_config()->PackFrom( + envoy::extensions::filters::http::router::v3::Router()); + listener.mutable_api_listener()->mutable_api_listener()->PackFrom( + http_connection_manager); + return listener; + } + + RouteConfiguration BuildRouteConfigurationWithFaultInjection( + const HTTPFault& http_fault) { + // Package as Any + google::protobuf::Any filter_config; + filter_config.PackFrom(http_fault); + // Plug into the RouteConfiguration + RouteConfiguration new_route_config = default_route_config_; + auto* config_map = new_route_config.mutable_virtual_hosts(0) + ->mutable_routes(0) + ->mutable_typed_per_filter_config(); + (*config_map)["envoy.fault"] = std::move(filter_config); + return new_route_config; + } + + void SetFilterConfig(HTTPFault& http_fault) { + switch (GetParam().filter_config_setup()) { + case TestType::FilterConfigSetup::kRouteOverride: { + Listener listener = BuildListenerWithFaultInjection(); + RouteConfiguration route = + BuildRouteConfigurationWithFaultInjection(http_fault); + SetListenerAndRouteConfiguration(0, listener, route); + break; + } + case TestType::FilterConfigSetup::kHTTPConnectionManagerOriginal: { + Listener listener = BuildListenerWithFaultInjection(http_fault); + SetListenerAndRouteConfiguration(0, listener, default_route_config_); + } + }; + } +}; + +// Test to ensure the most basic fault injection config works. +TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysAbort) { + const uint32_t kAbortPercentagePerHundred = 100; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Construct the fault injection filter config + HTTPFault http_fault; + auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage(); + abort_percentage->set_numerator(kAbortPercentagePerHundred); + abort_percentage->set_denominator(FractionalPercent::HUNDRED); + http_fault.mutable_abort()->set_grpc_status( + static_cast(StatusCode::ABORTED)); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Fire several RPCs, and expect all of them to be aborted. + CheckRpcSendFailure(5, RpcOptions().set_wait_for_ready(true), + StatusCode::ABORTED); +} + +// Without the listener config, the fault injection won't be enabled. +TEST_P(FaultInjectionTest, XdsFaultInjectionWithoutListenerFilter) { + const uint32_t kAbortPercentagePerHundred = 100; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage(); + abort_percentage->set_numerator(kAbortPercentagePerHundred); + abort_percentage->set_denominator(FractionalPercent::HUNDRED); + http_fault.mutable_abort()->set_grpc_status( + static_cast(StatusCode::ABORTED)); + // Turn on fault injection + RouteConfiguration route = + BuildRouteConfigurationWithFaultInjection(http_fault); + SetListenerAndRouteConfiguration(0, default_listener_, route); + // Fire several RPCs, and expect all of them to be pass. + CheckRpcSendOk(5, RpcOptions().set_wait_for_ready(true)); +} + +TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbort) { + const uint32_t kAbortPercentagePerHundred = 50; + const double kAbortRate = kAbortPercentagePerHundred / 100.0; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage(); + abort_percentage->set_numerator(kAbortPercentagePerHundred); + abort_percentage->set_denominator(FractionalPercent::HUNDRED); + http_fault.mutable_abort()->set_grpc_status( + static_cast(StatusCode::ABORTED)); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Send kNumRpcs RPCs and count the aborts. + int num_total = 0, num_ok = 0, num_failure = 0, num_aborted = 0; + for (size_t i = 0; i < kNumRpcs; ++i) { + SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_aborted, + RpcOptions(), "Fault injected"); + } + EXPECT_EQ(kNumRpcs, num_total); + EXPECT_EQ(0, num_failure); + // The abort rate should be roughly equal to the expectation. + const double seen_abort_rate = static_cast(num_aborted) / kNumRpcs; + EXPECT_THAT(seen_abort_rate, + ::testing::DoubleNear(kAbortRate, kErrorTolerance)); +} + +TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageAbortViaHeaders) { + const uint32_t kAbortPercentageCap = 100; + const uint32_t kAbortPercentage = 50; + const double kAbortRate = kAbortPercentage / 100.0; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + http_fault.mutable_abort()->mutable_header_abort(); + http_fault.mutable_abort()->mutable_percentage()->set_numerator( + kAbortPercentageCap); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Send kNumRpcs RPCs and count the aborts. + std::vector> metadata = { + {"x-envoy-fault-abort-grpc-request", "10"}, + {"x-envoy-fault-abort-percentage", std::to_string(kAbortPercentage)}, + }; + int num_total = 0, num_ok = 0, num_failure = 0, num_aborted = 0; + RpcOptions options = RpcOptions().set_metadata(metadata); + for (size_t i = 0; i < kNumRpcs; ++i) { + SendRpcAndCount(&num_total, &num_ok, &num_failure, &num_aborted, options, + "Fault injected"); + } + EXPECT_EQ(kNumRpcs, num_total); + EXPECT_EQ(0, num_failure); + // The abort rate should be roughly equal to the expectation. + const double seen_abort_rate = static_cast(num_aborted) / kNumRpcs; + EXPECT_THAT(seen_abort_rate, + ::testing::DoubleNear(kAbortRate, kErrorTolerance)); } -class BootstrapContentsFromEnvVarTest : public XdsEnd2endTest { +TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelay) { + const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 3000; + const uint32_t kFixedDelaySeconds = 100; + const uint32_t kDelayPercentagePerHundred = 50; + const double kDelayRate = kDelayPercentagePerHundred / 100.0; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage(); + delay_percentage->set_numerator(kDelayPercentagePerHundred); + delay_percentage->set_denominator(FractionalPercent::HUNDRED); + auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay(); + fixed_delay->set_seconds(kFixedDelaySeconds); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Send kNumRpcs RPCs and count the delays. + RpcOptions rpc_options = RpcOptions() + .set_timeout_ms(kRpcTimeoutMilliseconds) + .set_skip_cancelled_check(true); + std::vector rpcs = + SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options); + size_t num_delayed = 0; + for (auto& rpc : rpcs) { + if (rpc.status.error_code() == StatusCode::OK) continue; + EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code()); + ++num_delayed; + } + // The delay rate should be roughly equal to the expectation. + const double seen_delay_rate = static_cast(num_delayed) / kNumRpcs; + EXPECT_THAT(seen_delay_rate, + ::testing::DoubleNear(kDelayRate, kErrorTolerance)); +} + +TEST_P(FaultInjectionTest, XdsFaultInjectionPercentageDelayViaHeaders) { + const uint32_t kFixedDelayMilliseconds = 100000; + const uint32_t kRpcTimeoutMilliseconds = grpc_test_slowdown_factor() * 3000; + const uint32_t kDelayPercentageCap = 100; + const uint32_t kDelayPercentage = 50; + const double kDelayRate = kDelayPercentage / 100.0; + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kDelayRate, kErrorTolerance); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + http_fault.mutable_delay()->mutable_header_delay(); + http_fault.mutable_delay()->mutable_percentage()->set_numerator( + kDelayPercentageCap); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Send kNumRpcs RPCs and count the delays. + std::vector> metadata = { + {"x-envoy-fault-delay-request", std::to_string(kFixedDelayMilliseconds)}, + {"x-envoy-fault-delay-request-percentage", + std::to_string(kDelayPercentage)}, + }; + RpcOptions rpc_options = RpcOptions() + .set_metadata(metadata) + .set_timeout_ms(kRpcTimeoutMilliseconds) + .set_skip_cancelled_check(true); + std::vector rpcs = + SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options); + size_t num_delayed = 0; + for (auto& rpc : rpcs) { + if (rpc.status.error_code() == StatusCode::OK) continue; + EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code()); + ++num_delayed; + } + // The delay rate should be roughly equal to the expectation. + const double seen_delay_rate = static_cast(num_delayed) / kNumRpcs; + EXPECT_THAT(seen_delay_rate, + ::testing::DoubleNear(kDelayRate, kErrorTolerance)); +} + +TEST_P(FaultInjectionTest, XdsFaultInjectionAlwaysDelayPercentageAbort) { + const uint32_t kAbortPercentagePerHundred = 50; + const double kAbortRate = kAbortPercentagePerHundred / 100.0; + const uint32_t kFixedDelaySeconds = 1; + const uint32_t kRpcTimeoutMilliseconds = 100 * 1000; // 100s should not reach + const uint32_t kConnectionTimeoutMilliseconds = + 10 * 1000; // 10s should not reach + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage(); + abort_percentage->set_numerator(kAbortPercentagePerHundred); + abort_percentage->set_denominator(FractionalPercent::HUNDRED); + http_fault.mutable_abort()->set_grpc_status( + static_cast(StatusCode::ABORTED)); + auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage(); + delay_percentage->set_numerator(1000000); // Always inject DELAY! + delay_percentage->set_denominator(FractionalPercent::MILLION); + auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay(); + fixed_delay->set_seconds(kFixedDelaySeconds); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Allow the channel to connect to one backends, so the herd of queued RPCs + // won't be executed on the same ExecCtx object and using the cached Now() + // value, which causes millisecond level delay error. + channel_->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)); + // Send kNumRpcs RPCs and count the aborts. + int num_aborted = 0; + RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds); + std::vector rpcs = + SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options); + for (auto& rpc : rpcs) { + EXPECT_GE(rpc.elapsed_time, kFixedDelaySeconds * 1000); + if (rpc.status.error_code() == StatusCode::OK) continue; + EXPECT_EQ("Fault injected", rpc.status.error_message()); + ++num_aborted; + } + // The abort rate should be roughly equal to the expectation. + const double seen_abort_rate = static_cast(num_aborted) / kNumRpcs; + EXPECT_THAT(seen_abort_rate, + ::testing::DoubleNear(kAbortRate, kErrorTolerance)); +} + +// This test and the above test apply different denominators to delay and abort. +// This ensures that we are using the right denominator for each injected fault +// in our code. +TEST_P(FaultInjectionTest, + XdsFaultInjectionAlwaysDelayPercentageAbortSwitchDenominator) { + const uint32_t kAbortPercentagePerMillion = 500000; + const double kAbortRate = kAbortPercentagePerMillion / 1000000.0; + const uint32_t kFixedDelaySeconds = 1; // 1s + const uint32_t kRpcTimeoutMilliseconds = 100 * 1000; // 100s should not reach + const uint32_t kConnectionTimeoutMilliseconds = + 10 * 1000; // 10s should not reach + const double kErrorTolerance = 0.05; + const size_t kNumRpcs = ComputeIdealNumRpcs(kAbortRate, kErrorTolerance); + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + auto* abort_percentage = http_fault.mutable_abort()->mutable_percentage(); + abort_percentage->set_numerator(kAbortPercentagePerMillion); + abort_percentage->set_denominator(FractionalPercent::MILLION); + http_fault.mutable_abort()->set_grpc_status( + static_cast(StatusCode::ABORTED)); + auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage(); + delay_percentage->set_numerator(100); // Always inject DELAY! + delay_percentage->set_denominator(FractionalPercent::HUNDRED); + auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay(); + fixed_delay->set_seconds(kFixedDelaySeconds); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Allow the channel to connect to one backends, so the herd of queued RPCs + // won't be executed on the same ExecCtx object and using the cached Now() + // value, which causes millisecond level delay error. + channel_->WaitForConnected( + grpc_timeout_milliseconds_to_deadline(kConnectionTimeoutMilliseconds)); + // Send kNumRpcs RPCs and count the aborts. + int num_aborted = 0; + RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMilliseconds); + std::vector rpcs = + SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options); + for (auto& rpc : rpcs) { + EXPECT_GE(rpc.elapsed_time, kFixedDelaySeconds * 1000); + if (rpc.status.error_code() == StatusCode::OK) continue; + EXPECT_EQ("Fault injected", rpc.status.error_message()); + ++num_aborted; + } + // The abort rate should be roughly equal to the expectation. + const double seen_abort_rate = static_cast(num_aborted) / kNumRpcs; + EXPECT_THAT(seen_abort_rate, + ::testing::DoubleNear(kAbortRate, kErrorTolerance)); +} + +TEST_P(FaultInjectionTest, XdsFaultInjectionMaxFault) { + const uint32_t kMaxFault = 10; + const uint32_t kNumRpcs = 30; // kNumRpcs should be bigger than kMaxFault + const uint32_t kRpcTimeoutMs = 4000; // 4 seconds + const uint32_t kLongDelaySeconds = 100; // 100 seconds + const uint32_t kAlwaysDelayPercentage = 100; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create an EDS resource + AdsServiceImpl::EdsResourceArgs args({ + {"locality0", CreateEndpointsForBackends()}, + }); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Construct the fault injection filter config + HTTPFault http_fault; + auto* delay_percentage = http_fault.mutable_delay()->mutable_percentage(); + delay_percentage->set_numerator( + kAlwaysDelayPercentage); // Always inject DELAY! + delay_percentage->set_denominator(FractionalPercent::HUNDRED); + auto* fixed_delay = http_fault.mutable_delay()->mutable_fixed_delay(); + fixed_delay->set_seconds(kLongDelaySeconds); + http_fault.mutable_max_active_faults()->set_value(kMaxFault); + // Config fault injection via different setup + SetFilterConfig(http_fault); + // Sends a batch of long running RPCs with long timeout to consume all + // active faults quota. + int num_delayed = 0; + RpcOptions rpc_options = RpcOptions().set_timeout_ms(kRpcTimeoutMs); + std::vector rpcs = + SendConcurrentRpcs(stub_.get(), kNumRpcs, rpc_options); + for (auto& rpc : rpcs) { + if (rpc.status.error_code() == StatusCode::OK) continue; + EXPECT_EQ(StatusCode::DEADLINE_EXCEEDED, rpc.status.error_code()); + ++num_delayed; + } + // Only kMaxFault number of RPC should be fault injected.. + EXPECT_EQ(kMaxFault, num_delayed); +} + +class BootstrapSourceTest : public XdsEnd2endTest { public: - BootstrapContentsFromEnvVarTest() : XdsEnd2endTest(4, 1, 100, false, true) {} + BootstrapSourceTest() : XdsEnd2endTest(4, 1) {} }; -TEST_P(BootstrapContentsFromEnvVarTest, Vanilla) { +TEST_P(BootstrapSourceTest, Vanilla) { SetNextResolution({}); SetNextResolutionForLbChannelAllBalancers(); AdsServiceImpl::EdsResourceArgs args({ - {"locality0", GetBackendPorts()}, + {"locality0", CreateEndpointsForBackends()}, }); balancers_[0]->ads_service()->SetEdsResource( BuildEdsResource(args, DefaultEdsServiceName())); WaitForAllBackends(); } +#ifndef DISABLED_XDS_PROTO_IN_CC +class ClientStatusDiscoveryServiceTest : public XdsEnd2endTest { + public: + ClientStatusDiscoveryServiceTest() : XdsEnd2endTest(1, 1) {} + + void SetUp() override { + XdsEnd2endTest::SetUp(); + admin_server_thread_ = absl::make_unique(this); + admin_server_thread_->Start(); + std::string admin_server_address = absl::StrCat( + ipv6_only_ ? "[::1]:" : "127.0.0.1:", admin_server_thread_->port()); + admin_channel_ = grpc::CreateChannel( + admin_server_address, + std::make_shared( + grpc_fake_transport_security_credentials_create())); + csds_stub_ = + envoy::service::status::v3::ClientStatusDiscoveryService::NewStub( + admin_channel_); + if (GetParam().use_csds_streaming()) { + stream_ = csds_stub_->StreamClientStatus(&stream_context_); + } + } + + void TearDown() override { + if (stream_ != nullptr) { + EXPECT_TRUE(stream_->WritesDone()); + Status status = stream_->Finish(); + EXPECT_TRUE(status.ok()) << "code=" << status.error_code() + << " message=" << status.error_message(); + } + admin_server_thread_->Shutdown(); + XdsEnd2endTest::TearDown(); + } + + envoy::service::status::v3::ClientStatusResponse FetchCsdsResponse() { + envoy::service::status::v3::ClientStatusResponse response; + if (!GetParam().use_csds_streaming()) { + // Fetch through unary pulls + ClientContext context; + Status status = csds_stub_->FetchClientStatus( + &context, envoy::service::status::v3::ClientStatusRequest(), + &response); + EXPECT_TRUE(status.ok()) << "code=" << status.error_code() + << " message=" << status.error_message(); + } else { + // Fetch through streaming pulls + EXPECT_TRUE( + stream_->Write(envoy::service::status::v3::ClientStatusRequest())); + EXPECT_TRUE(stream_->Read(&response)); + } + return response; + } + + private: + std::unique_ptr admin_server_thread_; + std::shared_ptr admin_channel_; + std::unique_ptr< + envoy::service::status::v3::ClientStatusDiscoveryService::Stub> + csds_stub_; + ClientContext stream_context_; + std::unique_ptr< + ClientReaderWriter> + stream_; +}; + +MATCHER_P4(EqNode, id, user_agent_name, user_agent_version, client_features, + "equals Node") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(id, arg.id(), result_listener); + ok &= ::testing::ExplainMatchResult(user_agent_name, arg.user_agent_name(), + result_listener); + ok &= ::testing::ExplainMatchResult( + user_agent_version, arg.user_agent_version(), result_listener); + ok &= ::testing::ExplainMatchResult(client_features, arg.client_features(), + result_listener); + return ok; +} + +MATCHER_P2(EqListenersConfigDump, version_info, dynamic_listeners, + "equals ListenerConfigDump") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(), + arg.static_listeners(), result_listener); + ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(), + result_listener); + ok &= ::testing::ExplainMatchResult(dynamic_listeners, + arg.dynamic_listeners(), result_listener); + return ok; +} + +MATCHER_P2(EqDynamicListenerState, version_info, listener, + "equals DynamicListenerState") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(), + result_listener); + ok &= + ::testing::ExplainMatchResult(listener, arg.listener(), result_listener); + return ok; +} + +MATCHER_P2(EqListener, name, api_listener, "equals Listener") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener); + ok &= ::testing::ExplainMatchResult( + api_listener, arg.api_listener().api_listener(), result_listener); + return ok; +} + +MATCHER_P(EqHttpConnectionManagerNotRds, route_config, + "equals HttpConnectionManager") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(route_config, arg.route_config(), + result_listener); + return ok; +} + +MATCHER_P(EqRouteConfigurationName, name, "equals RouteConfiguration") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener); + return ok; +} + +MATCHER_P2(EqRouteConfiguration, name, cluster_name, + "equals RouteConfiguration") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener); + ok &= ::testing::ExplainMatchResult( + ::testing::ElementsAre(::testing::Property( + &envoy::config::route::v3::VirtualHost::routes, + ::testing::ElementsAre(::testing::Property( + &envoy::config::route::v3::Route::route, + ::testing::Property( + &envoy::config::route::v3::RouteAction::cluster, + cluster_name))))), + arg.virtual_hosts(), result_listener); + return ok; +} + +MATCHER_P(EqRoutesConfigDump, dynamic_route_configs, + "equals RoutesConfigDump") { + bool ok = true; + ok &= ::testing::ExplainMatchResult( + ::testing::ElementsAre(), arg.static_route_configs(), result_listener); + ok &= ::testing::ExplainMatchResult( + dynamic_route_configs, arg.dynamic_route_configs(), result_listener); + return ok; +} + +MATCHER_P2(EqClustersConfigDump, version_info, dynamic_active_clusters, + "equals ClustersConfigDump") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(), + arg.static_clusters(), result_listener); + ok &= ::testing::ExplainMatchResult(::testing::ElementsAre(), + arg.dynamic_warming_clusters(), + result_listener); + ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(), + result_listener); + ok &= ::testing::ExplainMatchResult( + dynamic_active_clusters, arg.dynamic_active_clusters(), result_listener); + return ok; +} + +MATCHER_P(EqCluster, name, "equals Cluster") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener); + return ok; +} + +MATCHER_P(EqEndpointsConfigDump, dynamic_endpoint_configs, + "equals EndpointsConfigDump") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(dynamic_endpoint_configs, + arg.dynamic_endpoint_configs(), + result_listener); + return ok; +} + +MATCHER_P(EqEndpoint, port, "equals Endpoint") { + bool ok = true; + ok &= ::testing::ExplainMatchResult( + port, arg.address().socket_address().port_value(), result_listener); + return ok; +} + +MATCHER_P2(EqLocalityLbEndpoints, port, weight, "equals LocalityLbEndpoints") { + bool ok = true; + ok &= ::testing::ExplainMatchResult( + ::testing::ElementsAre(::testing::Property( + &envoy::config::endpoint::v3::LbEndpoint::endpoint, + EqEndpoint(port))), + arg.lb_endpoints(), result_listener); + ok &= ::testing::ExplainMatchResult( + weight, arg.load_balancing_weight().value(), result_listener); + return ok; +} + +MATCHER_P(EqClusterLoadAssignmentName, cluster_name, + "equals ClusterLoadAssignment") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(cluster_name, arg.cluster_name(), + result_listener); + return ok; +} + +MATCHER_P3(EqClusterLoadAssignment, cluster_name, port, weight, + "equals ClusterLoadAssignment") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(cluster_name, arg.cluster_name(), + result_listener); + ok &= ::testing::ExplainMatchResult( + ::testing::ElementsAre(EqLocalityLbEndpoints(port, weight)), + arg.endpoints(), result_listener); + return ok; +} + +MATCHER_P2(EqUpdateFailureState, details, version_info, + "equals UpdateFailureState") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(details, arg.details(), result_listener); + ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(), + result_listener); + return ok; +} + +MATCHER_P(UnpackListener, matcher, "is a Listener") { + Listener config; + if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config), + result_listener)) { + return false; + } + return ::testing::ExplainMatchResult(matcher, config, result_listener); +} + +MATCHER_P(UnpackRouteConfiguration, matcher, "is a RouteConfiguration") { + RouteConfiguration config; + if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config), + result_listener)) { + return false; + } + return ::testing::ExplainMatchResult(matcher, config, result_listener); +} + +MATCHER_P(UnpackHttpConnectionManager, matcher, "is a HttpConnectionManager") { + HttpConnectionManager config; + if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config), + result_listener)) { + return false; + } + return ::testing::ExplainMatchResult(matcher, config, result_listener); +} + +MATCHER_P(UnpackCluster, matcher, "is a Cluster") { + Cluster config; + if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config), + result_listener)) { + return false; + } + return ::testing::ExplainMatchResult(matcher, config, result_listener); +} + +MATCHER_P(UnpackClusterLoadAssignment, matcher, "is a ClusterLoadAssignment") { + ClusterLoadAssignment config; + if (!::testing::ExplainMatchResult(true, arg.UnpackTo(&config), + result_listener)) { + return false; + } + return ::testing::ExplainMatchResult(matcher, config, result_listener); +} + +MATCHER_P5(EqDynamicListener, name, version_info, client_status, + api_listener_matcher, error_state, "equals DynamicListener") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(false, arg.has_warming_state(), + result_listener); + ok &= ::testing::ExplainMatchResult(false, arg.has_draining_state(), + result_listener); + ok &= ::testing::ExplainMatchResult(name, arg.name(), result_listener); + ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(), + result_listener); + if (client_status == ClientResourceStatus::ACKED || + client_status == ClientResourceStatus::NACKED) { + ok &= ::testing::ExplainMatchResult( + EqDynamicListenerState(version_info, UnpackListener(EqListener( + name, api_listener_matcher))), + arg.active_state(), result_listener); + } + ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(), + result_listener); + return ok; +} + +MATCHER_P5(EqDynamicRouteConfig, name, version_info, client_status, + cluster_name, error_state, "equals DynamicRouteConfig") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(), + result_listener); + if (client_status == ClientResourceStatus::REQUESTED || + client_status == ClientResourceStatus::DOES_NOT_EXIST) { + ok &= ::testing::ExplainMatchResult( + UnpackRouteConfiguration(EqRouteConfigurationName(name)), + arg.route_config(), result_listener); + } else { + ok &= ::testing::ExplainMatchResult( + UnpackRouteConfiguration(EqRouteConfiguration(name, cluster_name)), + arg.route_config(), result_listener); + } + ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(), + result_listener); + ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(), + result_listener); + return ok; +} + +MATCHER_P4(EqDynamicCluster, name, version_info, client_status, error_state, + "equals DynamicCluster") { + bool ok = true; + ok &= ::testing::ExplainMatchResult(UnpackCluster(EqCluster(name)), + arg.cluster(), result_listener); + ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(), + result_listener); + ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(), + result_listener); + ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(), + result_listener); + return ok; +} + +MATCHER_P6(EqDynamicEndpointConfig, name, version_info, client_status, port, + weight, error_state, "equals DynamicEndpointConfig") { + bool ok = true; + if (client_status == ClientResourceStatus::REQUESTED || + client_status == ClientResourceStatus::DOES_NOT_EXIST) { + ok &= ::testing::ExplainMatchResult( + UnpackClusterLoadAssignment(EqClusterLoadAssignmentName(name)), + arg.endpoint_config(), result_listener); + } else { + ok &= ::testing::ExplainMatchResult( + UnpackClusterLoadAssignment( + EqClusterLoadAssignment(name, port, weight)), + arg.endpoint_config(), result_listener); + } + ok &= ::testing::ExplainMatchResult(version_info, arg.version_info(), + result_listener); + ok &= ::testing::ExplainMatchResult(client_status, arg.client_status(), + result_listener); + ok &= ::testing::ExplainMatchResult(error_state, arg.error_state(), + result_listener); + return ok; +} + +MATCHER(IsRdsEnabledHCM, "is a RDS enabled HttpConnectionManager") { + return ::testing::ExplainMatchResult( + UnpackHttpConnectionManager( + ::testing::Property(&HttpConnectionManager::has_rds, true)), + arg, result_listener); +} + +MATCHER_P2(EqNoRdsHCM, route_configuration_name, cluster_name, + "equals RDS disabled HttpConnectionManager") { + return ::testing::ExplainMatchResult( + UnpackHttpConnectionManager(EqHttpConnectionManagerNotRds( + EqRouteConfiguration(route_configuration_name, cluster_name))), + arg, result_listener); +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpVanilla) { + const size_t kNumRpcs = 5; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Send several RPCs to ensure the xDS setup works + CheckRpcSendOk(kNumRpcs); + // Fetches the client config + auto csds_response = FetchCsdsResponse(); + gpr_log(GPR_INFO, "xDS config dump: %s", csds_response.DebugString().c_str()); + EXPECT_EQ(1, csds_response.config_size()); + const auto& client_config = csds_response.config(0); + // Validate the Node information + EXPECT_THAT(client_config.node(), + EqNode("xds_end2end_test", ::testing::HasSubstr("C-core"), + ::testing::HasSubstr(grpc_version_string()), + ::testing::ElementsAre( + "envoy.lb.does_not_support_overprovisioning"))); + // Prepare matches for RDS on or off + ::testing::Matcher api_listener_matcher; + ::testing::Matcher + route_config_dump_matcher; + if (GetParam().enable_rds_testing()) { + api_listener_matcher = IsRdsEnabledHCM(); + route_config_dump_matcher = + EqRoutesConfigDump(::testing::ElementsAre(EqDynamicRouteConfig( + kDefaultRouteConfigurationName, "1", ClientResourceStatus::ACKED, + kDefaultClusterName, ::testing::_))); + } else { + api_listener_matcher = + EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName); + route_config_dump_matcher = EqRoutesConfigDump(::testing::ElementsAre()); + } + // Validate the dumped xDS configs + EXPECT_THAT( + client_config.xds_config(), + ::testing::UnorderedElementsAre( + ::testing::Property( + &envoy::service::status::v3::PerXdsConfig::listener_config, + EqListenersConfigDump( + "1", ::testing::ElementsAre(EqDynamicListener( + kServerName, "1", ClientResourceStatus::ACKED, + api_listener_matcher, ::testing::_)))), + ::testing::Property( + &envoy::service::status::v3::PerXdsConfig::route_config, + route_config_dump_matcher), + ::testing::Property( + &envoy::service::status::v3::PerXdsConfig::cluster_config, + EqClustersConfigDump( + "1", ::testing::ElementsAre(EqDynamicCluster( + kDefaultClusterName, "1", + ClientResourceStatus::ACKED, ::testing::_)))), + ::testing::Property( + &envoy::service::status::v3::PerXdsConfig::endpoint_config, + EqEndpointsConfigDump( + ::testing::ElementsAre(EqDynamicEndpointConfig( + kDefaultEdsServiceName, "1", ClientResourceStatus::ACKED, + backends_[0]->port(), kDefaultLocalityWeight, + ::testing::_)))))); +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEmpty) { + // The CSDS service should not fail if XdsClient is not initialized or there + // is no working xDS configs. + FetchCsdsResponse(); +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerError) { + int kFetchConfigRetries = 3; + int kFetchIntervalMilliseconds = 200; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Ensure the xDS resolver has working configs. + CheckRpcSendOk(); + // Bad Listener should be rejected. + Listener listener; + listener.set_name(kServerName); + balancers_[0]->ads_service()->SetLdsResource(listener); + // The old xDS configs should still be effective. + CheckRpcSendOk(); + ::testing::Matcher api_listener_matcher; + if (GetParam().enable_rds_testing()) { + api_listener_matcher = IsRdsEnabledHCM(); + } else { + api_listener_matcher = + EqNoRdsHCM(kDefaultRouteConfigurationName, kDefaultClusterName); + } + for (int o = 0; o < kFetchConfigRetries; o++) { + auto csds_response = FetchCsdsResponse(); + // Check if error state is propagated + bool ok = ::testing::Value( + csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::listener_config, + EqListenersConfigDump( + "1", + ::testing::ElementsAre(EqDynamicListener( + kServerName, "1", ClientResourceStatus::NACKED, + api_listener_matcher, + EqUpdateFailureState( + ::testing::HasSubstr( + "Listener has neither address nor ApiListener"), + "2"))))))); + if (ok) return; // TEST PASSED! + gpr_sleep_until( + grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds)); + } + FAIL() << "error_state not seen in CSDS responses"; +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpRouteError) { + int kFetchConfigRetries = 3; + int kFetchIntervalMilliseconds = 200; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Ensure the xDS resolver has working configs. + CheckRpcSendOk(); + // Bad route config will be rejected. + RouteConfiguration route_config; + route_config.set_name(kDefaultRouteConfigurationName); + route_config.add_virtual_hosts(); + SetRouteConfiguration(0, route_config); + // The old xDS configs should still be effective. + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + CheckRpcSendOk(); + for (int o = 0; o < kFetchConfigRetries; o++) { + auto csds_response = FetchCsdsResponse(); + bool ok = false; + if (GetParam().enable_rds_testing()) { + ok = ::testing::Value( + csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::route_config, + EqRoutesConfigDump(::testing::ElementsAre(EqDynamicRouteConfig( + kDefaultRouteConfigurationName, "1", + ClientResourceStatus::NACKED, kDefaultClusterName, + EqUpdateFailureState( + ::testing::HasSubstr("VirtualHost has no domains"), + "2"))))))); + } else { + ok = ::testing::Value( + csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::listener_config, + EqListenersConfigDump( + "1", + ::testing::ElementsAre(EqDynamicListener( + kServerName, "1", ClientResourceStatus::NACKED, + EqNoRdsHCM(kDefaultRouteConfigurationName, + kDefaultClusterName), + EqUpdateFailureState( + ::testing::HasSubstr("VirtualHost has no domains"), + "2"))))))); + } + if (ok) return; // TEST PASSED! + gpr_sleep_until( + grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds)); + } + FAIL() << "error_state not seen in CSDS responses"; +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterError) { + int kFetchConfigRetries = 3; + int kFetchIntervalMilliseconds = 200; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Ensure the xDS resolver has working configs. + CheckRpcSendOk(); + // Listener without any route, will be rejected. + Cluster cluster; + cluster.set_name(kDefaultClusterName); + balancers_[0]->ads_service()->SetCdsResource(cluster); + // The old xDS configs should still be effective. + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + CheckRpcSendOk(); + for (int o = 0; o < kFetchConfigRetries; o++) { + auto csds_response = FetchCsdsResponse(); + // Check if error state is propagated + bool ok = ::testing::Value( + csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::cluster_config, + EqClustersConfigDump( + "1", ::testing::ElementsAre(EqDynamicCluster( + kDefaultClusterName, "1", ClientResourceStatus::NACKED, + EqUpdateFailureState( + ::testing::HasSubstr("DiscoveryType not found"), + "2"))))))); + if (ok) return; // TEST PASSED! + gpr_sleep_until( + grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds)); + } + FAIL() << "error_state not seen in CSDS responses"; +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpEndpointError) { + int kFetchConfigRetries = 3; + int kFetchIntervalMilliseconds = 200; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + AdsServiceImpl::EdsResourceArgs args( + {{"locality0", CreateEndpointsForBackends(0, 1)}}); + balancers_[0]->ads_service()->SetEdsResource( + BuildEdsResource(args, DefaultEdsServiceName())); + // Ensure the xDS resolver has working configs. + CheckRpcSendOk(); + // Bad endpoint config will be rejected. + ClusterLoadAssignment cluster_load_assignment; + cluster_load_assignment.set_cluster_name(kDefaultEdsServiceName); + auto* endpoints = cluster_load_assignment.add_endpoints(); + endpoints->mutable_load_balancing_weight()->set_value(1); + auto* endpoint = endpoints->add_lb_endpoints()->mutable_endpoint(); + endpoint->mutable_address()->mutable_socket_address()->set_port_value(1 << 1); + balancers_[0]->ads_service()->SetEdsResource(cluster_load_assignment); + // The old xDS configs should still be effective. + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + CheckRpcSendOk(); + for (int o = 0; o < kFetchConfigRetries; o++) { + auto csds_response = FetchCsdsResponse(); + + // Check if error state is propagated + bool ok = ::testing::Value( + csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::endpoint_config, + EqEndpointsConfigDump( + ::testing::ElementsAre(EqDynamicEndpointConfig( + kDefaultEdsServiceName, "1", ClientResourceStatus::NACKED, + backends_[0]->port(), kDefaultLocalityWeight, + EqUpdateFailureState(::testing::HasSubstr("Empty locality"), + "2"))))))); + if (ok) return; // TEST PASSED! + gpr_sleep_until( + grpc_timeout_milliseconds_to_deadline(kFetchIntervalMilliseconds)); + } + FAIL() << "error_state not seen in CSDS responses"; +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpListenerRequested) { + int kTimeoutMillisecond = 1000; + balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName); + CheckRpcSendFailure(1, RpcOptions().set_timeout_ms(kTimeoutMillisecond), + StatusCode::DEADLINE_EXCEEDED); + auto csds_response = FetchCsdsResponse(); + EXPECT_THAT(csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::listener_config, + EqListenersConfigDump( + ::testing::_, ::testing::ElementsAre(EqDynamicListener( + kServerName, ::testing::_, + ClientResourceStatus::REQUESTED, + ::testing::_, ::testing::_)))))); +} + +TEST_P(ClientStatusDiscoveryServiceTest, XdsConfigDumpClusterRequested) { + int kTimeoutMillisecond = 1000; + std::string kClusterName1 = "cluster-1"; + std::string kClusterName2 = "cluster-2"; + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + // Create a route config requesting two non-existing clusters + RouteConfiguration route_config; + route_config.set_name(kDefaultRouteConfigurationName); + auto* vh = route_config.add_virtual_hosts(); + // The VirtualHost must match the domain name, otherwise will cause resolver + // transient failure. + vh->add_domains("*"); + auto* routes1 = vh->add_routes(); + routes1->mutable_match()->set_prefix(""); + routes1->mutable_route()->set_cluster(kClusterName1); + auto* routes2 = vh->add_routes(); + routes2->mutable_match()->set_prefix(""); + routes2->mutable_route()->set_cluster(kClusterName2); + SetRouteConfiguration(0, route_config); + // Try to get the configs plumb through + CheckRpcSendFailure(1, RpcOptions().set_timeout_ms(kTimeoutMillisecond), + StatusCode::DEADLINE_EXCEEDED); + auto csds_response = FetchCsdsResponse(); + EXPECT_THAT(csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::cluster_config, + EqClustersConfigDump( + ::testing::_, + ::testing::UnorderedElementsAre( + EqDynamicCluster(kClusterName1, ::testing::_, + ClientResourceStatus::REQUESTED, + ::testing::_), + EqDynamicCluster(kClusterName2, ::testing::_, + ClientResourceStatus::REQUESTED, + ::testing::_)))))); +} + +class CsdsShortAdsTimeoutTest : public ClientStatusDiscoveryServiceTest { + void SetUp() override { + // Shorten the ADS subscription timeout to speed up the test run. + xds_resource_does_not_exist_timeout_ms_ = 2000; + ClientStatusDiscoveryServiceTest::SetUp(); + } +}; + +TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpListenerDoesNotExist) { + int kTimeoutMillisecond = 1000000; // 1000s wait for the transient failure. + balancers_[0]->ads_service()->UnsetResource(kLdsTypeUrl, kServerName); + CheckRpcSendFailure(1, RpcOptions().set_timeout_ms(kTimeoutMillisecond), + grpc::UNAVAILABLE); + auto csds_response = FetchCsdsResponse(); + EXPECT_THAT(csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::listener_config, + EqListenersConfigDump( + ::testing::_, ::testing::ElementsAre(EqDynamicListener( + kServerName, ::testing::_, + ClientResourceStatus::DOES_NOT_EXIST, + ::testing::_, ::testing::_)))))); +} + +TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpRouteConfigDoesNotExist) { + if (!GetParam().enable_rds_testing()) return; + int kTimeoutMillisecond = 1000000; // 1000s wait for the transient failure. + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + balancers_[0]->ads_service()->UnsetResource(kRdsTypeUrl, + kDefaultRouteConfigurationName); + CheckRpcSendFailure(1, RpcOptions().set_timeout_ms(kTimeoutMillisecond), + grpc::UNAVAILABLE); + auto csds_response = FetchCsdsResponse(); + EXPECT_THAT( + csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::route_config, + EqRoutesConfigDump(::testing::ElementsAre( + EqDynamicRouteConfig(kDefaultRouteConfigurationName, ::testing::_, + ClientResourceStatus::DOES_NOT_EXIST, + ::testing::_, ::testing::_)))))); +} + +TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpClusterDoesNotExist) { + int kTimeoutMillisecond = 1000000; // 1000s wait for the transient failure. + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + balancers_[0]->ads_service()->UnsetResource(kCdsTypeUrl, kDefaultClusterName); + CheckRpcSendFailure(1, RpcOptions().set_timeout_ms(kTimeoutMillisecond), + grpc::UNAVAILABLE); + auto csds_response = FetchCsdsResponse(); + EXPECT_THAT(csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::cluster_config, + EqClustersConfigDump(::testing::_, + ::testing::ElementsAre(EqDynamicCluster( + kDefaultClusterName, ::testing::_, + ClientResourceStatus::DOES_NOT_EXIST, + ::testing::_)))))); +} + +TEST_P(CsdsShortAdsTimeoutTest, XdsConfigDumpEndpointDoesNotExist) { + int kTimeoutMillisecond = 1000000; // 1000s wait for the transient failure. + SetNextResolution({}); + SetNextResolutionForLbChannelAllBalancers(); + balancers_[0]->ads_service()->UnsetResource(kEdsTypeUrl, + kDefaultEdsServiceName); + CheckRpcSendFailure(1, RpcOptions().set_timeout_ms(kTimeoutMillisecond), + grpc::UNAVAILABLE); + auto csds_response = FetchCsdsResponse(); + EXPECT_THAT( + csds_response.config(0).xds_config(), + ::testing::Contains(::testing::Property( + &envoy::service::status::v3::PerXdsConfig::endpoint_config, + EqEndpointsConfigDump(::testing::ElementsAre(EqDynamicEndpointConfig( + kDefaultEdsServiceName, ::testing::_, + ClientResourceStatus::DOES_NOT_EXIST, ::testing::_, ::testing::_, + ::testing::_)))))); +} +#endif // DISABLED_XDS_PROTO_IN_CC + std::string TestTypeName(const ::testing::TestParamInfo& info) { return info.param.AsString(); } @@ -8702,6 +11355,9 @@ INSTANTIATE_TEST_SUITE_P(XdsTest, SecureNamingTest, // LDS depends on XdsResolver. INSTANTIATE_TEST_SUITE_P(XdsTest, LdsTest, ::testing::Values(TestType()), &TestTypeName); +INSTANTIATE_TEST_SUITE_P(XdsTest, LdsV2Test, + ::testing::Values(TestType().set_use_v2()), + &TestTypeName); // LDS/RDS commmon tests depend on XdsResolver. INSTANTIATE_TEST_SUITE_P( @@ -8726,8 +11382,13 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Values(TestType().set_use_xds_credentials()), &TestTypeName); // We are only testing the server here. +// Run with bootstrap from env var, so that we use a global XdsClient +// instance. Otherwise, we would need to use a separate fake resolver +// result generator on the client and server sides. INSTANTIATE_TEST_SUITE_P(XdsTest, XdsEnabledServerTest, - ::testing::Values(TestType()), &TestTypeName); + ::testing::Values(TestType().set_bootstrap_source( + TestType::kBootstrapFromEnvVar)), + &TestTypeName); // We are only testing the server here. INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerSecurityTest, @@ -8736,6 +11397,20 @@ INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerSecurityTest, .set_use_xds_credentials()), &TestTypeName); +// We are only testing the server here. +INSTANTIATE_TEST_SUITE_P(XdsTest, XdsEnabledServerStatusNotificationTest, + ::testing::Values(TestType() + .set_use_fake_resolver() + .set_use_xds_credentials()), + &TestTypeName); + +// We are only testing the server here. +INSTANTIATE_TEST_SUITE_P(XdsTest, XdsServerFilterChainMatchTest, + ::testing::Values(TestType() + .set_use_fake_resolver() + .set_use_xds_credentials()), + &TestTypeName); + // EDS could be tested with or without XdsResolver, but the tests would // be the same either way, so we test it only with XdsResolver. INSTANTIATE_TEST_SUITE_P( @@ -8757,6 +11432,16 @@ INSTANTIATE_TEST_SUITE_P( ::testing::Values(TestType(), TestType().set_enable_load_reporting()), &TestTypeName); +// Runs with bootstrap from env var, so that there's a global XdsClient. +INSTANTIATE_TEST_SUITE_P( + XdsTest, GlobalXdsClientTest, + ::testing::Values( + TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar), + TestType() + .set_bootstrap_source(TestType::kBootstrapFromEnvVar) + .set_enable_load_reporting()), + &TestTypeName); + // XdsResolverLoadReprtingOnlyTest depends on XdsResolver and load reporting. INSTANTIATE_TEST_SUITE_P( XdsTest, XdsResolverLoadReportingOnlyTest, @@ -8810,8 +11495,58 @@ INSTANTIATE_TEST_SUITE_P( TestType().set_enable_load_reporting().set_use_fake_resolver()), &TestTypeName); -INSTANTIATE_TEST_SUITE_P(XdsTest, BootstrapContentsFromEnvVarTest, - ::testing::Values(TestType()), &TestTypeName); +INSTANTIATE_TEST_SUITE_P( + XdsTest, FaultInjectionTest, + ::testing::Values( + TestType(), TestType().set_enable_rds_testing(), + TestType().set_filter_config_setup( + TestType::FilterConfigSetup::kRouteOverride), + TestType().set_enable_rds_testing().set_filter_config_setup( + TestType::FilterConfigSetup::kRouteOverride)), + &TestTypeName); + +INSTANTIATE_TEST_SUITE_P( + XdsTest, BootstrapSourceTest, + ::testing::Values( + TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar), + TestType().set_bootstrap_source(TestType::kBootstrapFromFile)), + &TestTypeName); + +#ifndef DISABLED_XDS_PROTO_IN_CC +// Run CSDS tests with RDS enabled and disabled. +// These need to run with the bootstrap from an env var instead of from +// a channel arg, since there needs to be a global XdsClient instance. +INSTANTIATE_TEST_SUITE_P( + XdsTest, ClientStatusDiscoveryServiceTest, + ::testing::Values( + TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar), + TestType() + .set_bootstrap_source(TestType::kBootstrapFromEnvVar) + .set_enable_rds_testing(), + TestType() + .set_bootstrap_source(TestType::kBootstrapFromEnvVar) + .set_use_csds_streaming(), + TestType() + .set_bootstrap_source(TestType::kBootstrapFromEnvVar) + .set_enable_rds_testing() + .set_use_csds_streaming()), + &TestTypeName); +INSTANTIATE_TEST_SUITE_P( + XdsTest, CsdsShortAdsTimeoutTest, + ::testing::Values( + TestType().set_bootstrap_source(TestType::kBootstrapFromEnvVar), + TestType() + .set_bootstrap_source(TestType::kBootstrapFromEnvVar) + .set_enable_rds_testing(), + TestType() + .set_bootstrap_source(TestType::kBootstrapFromEnvVar) + .set_use_csds_streaming(), + TestType() + .set_bootstrap_source(TestType::kBootstrapFromEnvVar) + .set_enable_rds_testing() + .set_use_csds_streaming()), + &TestTypeName); +#endif // DISABLED_XDS_PROTO_IN_CC } // namespace } // namespace testing @@ -8835,6 +11570,14 @@ int main(int argc, char** argv) { absl::make_unique( "fake2", &grpc::testing::g_fake2_cert_data_map)); grpc_init(); + grpc_core::XdsHttpFilterRegistry::RegisterFilter( + absl::make_unique( + "grpc.testing.client_only_http_filter", true, false), + {"grpc.testing.client_only_http_filter"}); + grpc_core::XdsHttpFilterRegistry::RegisterFilter( + absl::make_unique( + "grpc.testing.server_only_http_filter", false, true), + {"grpc.testing.server_only_http_filter"}); const auto result = RUN_ALL_TESTS(); grpc_shutdown(); return result; diff --git a/test/cpp/grpclb/grpclb_api_test.cc b/test/cpp/grpclb/grpclb_api_test.cc index 80bbe1a12e7..0623280425a 100644 --- a/test/cpp/grpclb/grpclb_api_test.cc +++ b/test/cpp/grpclb/grpclb_api_test.cc @@ -24,8 +24,8 @@ #include #include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/iomgr/sockaddr.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/proto/grpc/lb/v1/load_balancer.pb.h" // C++ version #include "test/core/util/test_config.h" diff --git a/test/cpp/interop/BUILD b/test/cpp/interop/BUILD index 1f53c6a3dd9..85a84a70d6d 100644 --- a/test/cpp/interop/BUILD +++ b/test/cpp/interop/BUILD @@ -229,6 +229,8 @@ grpc_cc_binary( ], deps = [ "//:grpc++", + "//:grpc++_reflection", + "//:grpcpp_admin", "//src/proto/grpc/testing:empty_proto", "//src/proto/grpc/testing:messages_proto", "//src/proto/grpc/testing:test_proto", @@ -239,6 +241,7 @@ grpc_cc_binary( grpc_cc_binary( name = "xds_interop_server", + testonly = True, srcs = [ "xds_interop_server.cc", ], @@ -247,10 +250,13 @@ grpc_cc_binary( ], deps = [ "//:grpc++", + "//:grpc++_reflection", + "//:grpcpp_admin", "//src/proto/grpc/testing:empty_proto", "//src/proto/grpc/testing:messages_proto", "//src/proto/grpc/testing:test_proto", "//test/core/util:grpc_test_util", + "//test/cpp/end2end:test_health_check_service_impl", "//test/cpp/util:test_config", ], ) diff --git a/test/cpp/interop/grpclb_fallback_test.cc b/test/cpp/interop/grpclb_fallback_test.cc index 28c358b2463..caa86fc3117 100644 --- a/test/cpp/interop/grpclb_fallback_test.cc +++ b/test/cpp/interop/grpclb_fallback_test.cc @@ -150,11 +150,8 @@ int TcpUserTimeoutCompare(grpc_socket_mutator* /*a*/, void TcpUserTimeoutDestroy(grpc_socket_mutator* mutator) { gpr_free(mutator); } const grpc_socket_mutator_vtable kTcpUserTimeoutMutatorVtable = - grpc_socket_mutator_vtable{ - .mutate_fd = TcpUserTimeoutMutateFd, - .compare = TcpUserTimeoutCompare, - .destroy = TcpUserTimeoutDestroy, - }; + grpc_socket_mutator_vtable{TcpUserTimeoutMutateFd, TcpUserTimeoutCompare, + TcpUserTimeoutDestroy}; std::unique_ptr CreateFallbackTestStub() { grpc::ChannelArguments channel_args; diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc index 749b6ae61b9..49a1252058b 100644 --- a/test/cpp/interop/interop_client.cc +++ b/test/cpp/interop/interop_client.cc @@ -23,6 +23,7 @@ #include #include +#include "absl/strings/match.h" #include "absl/strings/str_format.h" #include @@ -225,7 +226,7 @@ bool InteropClient::DoComputeEngineCreds( GPR_ASSERT(response.username().c_str() == default_service_account); GPR_ASSERT(!response.oauth_scope().empty()); const char* oauth_scope_str = response.oauth_scope().c_str(); - GPR_ASSERT(oauth_scope.find(oauth_scope_str) != std::string::npos); + GPR_ASSERT(absl::StrContains(oauth_scope, oauth_scope_str)); gpr_log(GPR_DEBUG, "Large unary with compute engine creds done."); return true; } @@ -251,7 +252,7 @@ bool InteropClient::DoOauth2AuthToken(const std::string& username, GPR_ASSERT(!response.oauth_scope().empty()); GPR_ASSERT(username == response.username()); const char* oauth_scope_str = response.oauth_scope().c_str(); - GPR_ASSERT(oauth_scope.find(oauth_scope_str) != std::string::npos); + GPR_ASSERT(absl::StrContains(oauth_scope, oauth_scope_str)); gpr_log(GPR_DEBUG, "Unary with oauth2 access token credentials done."); return true; } @@ -536,11 +537,7 @@ bool InteropClient::DoClientCompressedStreaming() { GPR_ASSERT(stream->WritesDone()); s = stream->Finish(); - if (!AssertStatusOk(s, context.debug_error_string())) { - return false; - } - - return true; + return AssertStatusOk(s, context.debug_error_string()); } bool InteropClient::DoServerCompressedStreaming() { @@ -597,10 +594,7 @@ bool InteropClient::DoServerCompressedStreaming() { } Status s = stream->Finish(); - if (!AssertStatusOk(s, context.debug_error_string())) { - return false; - } - return true; + return AssertStatusOk(s, context.debug_error_string()); } bool InteropClient::DoResponseStreamingWithSlowConsumer() { diff --git a/test/cpp/interop/xds_interop_client.cc b/test/cpp/interop/xds_interop_client.cc index e0dad44b782..f8ced82930d 100644 --- a/test/cpp/interop/xds_interop_client.cc +++ b/test/cpp/interop/xds_interop_client.cc @@ -16,6 +16,8 @@ * */ +#include +#include #include #include #include @@ -59,6 +61,9 @@ ABSL_FLAG(std::string, rpc, "UnaryCall", ABSL_FLAG(std::string, metadata, "", "metadata to send with the RPC."); ABSL_FLAG(std::string, expect_status, "OK", "RPC status for the test RPC to be considered successful"); +ABSL_FLAG( + bool, secure_mode, false, + "If true, XdsCredentials are used, InsecureChannelCredentials otherwise"); using grpc::Channel; using grpc::ClientAsyncResponseReader; @@ -460,9 +465,13 @@ class XdsUpdateClientConfigureServiceImpl void RunTestLoop(std::chrono::duration duration_per_query, StatsWatchers* stats_watchers, RpcConfigurationsQueue* rpc_configs_queue) { - TestClient client(grpc::CreateChannel(absl::GetFlag(FLAGS_server), - grpc::InsecureChannelCredentials()), - stats_watchers); + TestClient client( + grpc::CreateChannel(absl::GetFlag(FLAGS_server), + absl::GetFlag(FLAGS_secure_mode) + ? grpc::experimental::XdsCredentials( + grpc::InsecureChannelCredentials()) + : grpc::InsecureChannelCredentials()), + stats_watchers); std::chrono::time_point start = std::chrono::system_clock::now(); std::chrono::duration elapsed; @@ -506,9 +515,11 @@ void RunServer(const int port, StatsWatchers* stats_watchers, LoadBalancerStatsServiceImpl stats_service(stats_watchers); XdsUpdateClientConfigureServiceImpl client_config_service(rpc_configs_queue); + grpc::reflection::InitProtoReflectionServerBuilderPlugin(); ServerBuilder builder; builder.RegisterService(&stats_service); builder.RegisterService(&client_config_service); + grpc::AddAdminServices(&builder); builder.AddListeningPort(server_address.str(), grpc::InsecureServerCredentials()); std::unique_ptr server(builder.BuildAndStart()); diff --git a/test/cpp/interop/xds_interop_server.cc b/test/cpp/interop/xds_interop_server.cc index 1913c53964b..ea7c6f23aa0 100644 --- a/test/cpp/interop/xds_interop_server.cc +++ b/test/cpp/interop/xds_interop_server.cc @@ -19,13 +19,19 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include #include "absl/flags/flag.h" +#include "absl/strings/str_cat.h" +#include "absl/synchronization/mutex.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/gethostname.h" #include "src/core/lib/transport/byte_stream.h" @@ -33,24 +39,33 @@ #include "src/proto/grpc/testing/messages.pb.h" #include "src/proto/grpc/testing/test.grpc.pb.h" #include "test/core/util/test_config.h" +#include "test/cpp/end2end/test_health_check_service_impl.h" #include "test/cpp/util/test_config.h" -ABSL_FLAG(int32_t, port, 50051, "Server port."); +ABSL_FLAG(int32_t, port, 8080, "Server port for service."); +ABSL_FLAG(int32_t, maintenance_port, 8081, + "Server port for maintenance if --security is \"secure\"."); ABSL_FLAG(std::string, server_id, "cpp_server", "Server ID to include in responses."); +ABSL_FLAG(bool, secure_mode, false, + "If true, XdsServerCredentials are used, InsecureServerCredentials " + "otherwise"); using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; +using grpc::experimental::XdsServerBuilder; using grpc::testing::Empty; +using grpc::testing::HealthCheckServiceImpl; using grpc::testing::SimpleRequest; using grpc::testing::SimpleResponse; using grpc::testing::TestService; +using grpc::testing::XdsUpdateHealthService; class TestServiceImpl : public TestService::Service { public: - explicit TestServiceImpl(const std::string& i) : hostname_(i) {} + explicit TestServiceImpl(const std::string& hostname) : hostname_(hostname) {} Status UnaryCall(ServerContext* context, const SimpleRequest* /*request*/, SimpleResponse* response) override { @@ -70,17 +85,74 @@ class TestServiceImpl : public TestService::Service { std::string hostname_; }; -void RunServer(const int port, const std::string& hostname) { - std::ostringstream server_address; - server_address << "0.0.0.0:" << port; +class XdsUpdateHealthServiceImpl : public XdsUpdateHealthService::Service { + public: + explicit XdsUpdateHealthServiceImpl( + HealthCheckServiceImpl* health_check_service) + : health_check_service_(health_check_service) {} + + Status SetServing(ServerContext* /* context */, const Empty* /* request */, + Empty* /* response */) override { + health_check_service_->SetAll( + grpc::health::v1::HealthCheckResponse::SERVING); + return Status::OK; + } + + Status SetNotServing(ServerContext* /* context */, const Empty* /* request */, + Empty* /* response */) override { + health_check_service_->SetAll( + grpc::health::v1::HealthCheckResponse::NOT_SERVING); + return Status::OK; + } + + private: + HealthCheckServiceImpl* const health_check_service_; +}; +void RunServer(bool secure_mode, const int port, const int maintenance_port, + const std::string& hostname) { + std::unique_ptr xds_enabled_server; + std::unique_ptr server; TestServiceImpl service(hostname); + HealthCheckServiceImpl health_check_service; + health_check_service.SetStatus( + "", grpc::health::v1::HealthCheckResponse::SERVING); + health_check_service.SetStatus( + "grpc.testing.TestService", + grpc::health::v1::HealthCheckResponse::SERVING); + health_check_service.SetStatus( + "grpc.testing.XdsUpdateHealthService", + grpc::health::v1::HealthCheckResponse::SERVING); + XdsUpdateHealthServiceImpl update_health_service(&health_check_service); + + grpc::reflection::InitProtoReflectionServerBuilderPlugin(); ServerBuilder builder; - builder.RegisterService(&service); - builder.AddListeningPort(server_address.str(), - grpc::InsecureServerCredentials()); - std::unique_ptr server(builder.BuildAndStart()); - gpr_log(GPR_INFO, "Server listening on %s", server_address.str().c_str()); + if (secure_mode) { + XdsServerBuilder xds_builder; + xds_builder.RegisterService(&service); + xds_builder.AddListeningPort(absl::StrCat("0.0.0.0:", port), + grpc::experimental::XdsServerCredentials( + grpc::InsecureServerCredentials())); + xds_enabled_server = xds_builder.BuildAndStart(); + gpr_log(GPR_INFO, "Server starting on 0.0.0.0:%d", port); + builder.RegisterService(&health_check_service); + builder.RegisterService(&update_health_service); + grpc::AddAdminServices(&builder); + builder.AddListeningPort(absl::StrCat("0.0.0.0:", maintenance_port), + grpc::InsecureServerCredentials()); + server = builder.BuildAndStart(); + gpr_log(GPR_INFO, "Maintenance server listening on 0.0.0.0:%d", + maintenance_port); + } else { + builder.RegisterService(&service); + builder.RegisterService(&health_check_service); + builder.RegisterService(&update_health_service); + grpc::AddAdminServices(&builder); + builder.AddListeningPort(absl::StrCat("0.0.0.0:", port), + grpc::InsecureServerCredentials()); + server = builder.BuildAndStart(); + gpr_log(GPR_INFO, "Server listening on 0.0.0.0:%d", port); + } server->Wait(); } @@ -88,18 +160,23 @@ void RunServer(const int port, const std::string& hostname) { int main(int argc, char** argv) { grpc::testing::TestEnvironment env(argc, argv); grpc::testing::InitTest(&argc, &argv, true); - char* hostname = grpc_gethostname(); if (hostname == nullptr) { std::cout << "Failed to get hostname, terminating" << std::endl; return 1; } - if (absl::GetFlag(FLAGS_port) == 0) { + int port = absl::GetFlag(FLAGS_port); + if (port == 0) { std::cout << "Invalid port, terminating" << std::endl; return 1; } - - RunServer(absl::GetFlag(FLAGS_port), hostname); + int maintenance_port = absl::GetFlag(FLAGS_maintenance_port); + if (maintenance_port == 0) { + std::cout << "Invalid maintenance port, terminating" << std::endl; + return 1; + } + grpc::EnableDefaultHealthCheckService(false); + RunServer(absl::GetFlag(FLAGS_secure_mode), port, maintenance_port, hostname); return 0; } diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc index 3bd7ef01325..81351f74a9c 100644 --- a/test/cpp/microbenchmarks/bm_call_create.cc +++ b/test/cpp/microbenchmarks/bm_call_create.cc @@ -312,13 +312,15 @@ static void BM_LameChannelCallCreateCoreSeparateBatch(benchmark::State& state) { } BENCHMARK(BM_LameChannelCallCreateCoreSeparateBatch); -static void FilterDestroy(void* arg, grpc_error* /*error*/) { gpr_free(arg); } +static void FilterDestroy(void* arg, grpc_error_handle /*error*/) { + gpr_free(arg); +} -static void DoNothing(void* /*arg*/, grpc_error* /*error*/) {} +static void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {} class FakeClientChannelFactory : public grpc_core::ClientChannelFactory { public: - grpc_core::Subchannel* CreateSubchannel( + grpc_core::RefCountedPtr CreateSubchannel( const grpc_channel_args* /*args*/) override { return nullptr; } @@ -351,8 +353,8 @@ static void StartTransportStreamOp(grpc_call_element* /*elem*/, static void StartTransportOp(grpc_channel_element* /*elem*/, grpc_transport_op* /*op*/) {} -static grpc_error* InitCallElem(grpc_call_element* /*elem*/, - const grpc_call_element_args* /*args*/) { +static grpc_error_handle InitCallElem(grpc_call_element* /*elem*/, + const grpc_call_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -363,8 +365,8 @@ static void DestroyCallElem(grpc_call_element* /*elem*/, const grpc_call_final_info* /*final_info*/, grpc_closure* /*then_sched_closure*/) {} -grpc_error* InitChannelElem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +grpc_error_handle InitChannelElem(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } @@ -568,7 +570,8 @@ BENCHMARK_TEMPLATE(BM_IsolatedFilter, NoFilter, NoOp); typedef Fixture<&phony_filter::phony_filter, 0> PhonyFilter; BENCHMARK_TEMPLATE(BM_IsolatedFilter, PhonyFilter, NoOp); BENCHMARK_TEMPLATE(BM_IsolatedFilter, PhonyFilter, SendEmptyMetadata); -typedef Fixture<&grpc_client_channel_filter, 0> ClientChannelFilter; +typedef Fixture<&grpc_core::ClientChannel::kFilterVtable, 0> + ClientChannelFilter; BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientChannelFilter, NoOp); typedef Fixture<&grpc_message_compress_filter, CHECKS_NOT_LAST> CompressFilter; BENCHMARK_TEMPLATE(BM_IsolatedFilter, CompressFilter, NoOp); @@ -641,8 +644,8 @@ static void StartTransportOp(grpc_channel_element* /*elem*/, grpc_core::ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, GRPC_ERROR_NONE); } -static grpc_error* InitCallElem(grpc_call_element* elem, - const grpc_call_element_args* args) { +static grpc_error_handle InitCallElem(grpc_call_element* elem, + const grpc_call_element_args* args) { call_data* calld = static_cast(elem->call_data); calld->call_combiner = args->call_combiner; return GRPC_ERROR_NONE; @@ -657,8 +660,8 @@ static void DestroyCallElem(grpc_call_element* /*elem*/, grpc_core::ExecCtx::Run(DEBUG_LOCATION, then_sched_closure, GRPC_ERROR_NONE); } -grpc_error* InitChannelElem(grpc_channel_element* /*elem*/, - grpc_channel_element_args* /*args*/) { +grpc_error_handle InitChannelElem(grpc_channel_element* /*elem*/, + grpc_channel_element_args* /*args*/) { return GRPC_ERROR_NONE; } diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc index 063b7fca664..1a1de051da9 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc @@ -452,12 +452,12 @@ static void BM_HpackParserInitDestroy(benchmark::State& state) { } BENCHMARK(BM_HpackParserInitDestroy); -static grpc_error* UnrefHeader(void* /*user_data*/, grpc_mdelem md) { +static grpc_error_handle UnrefHeader(void* /*user_data*/, grpc_mdelem md) { GRPC_MDELEM_UNREF(md); return GRPC_ERROR_NONE; } -template +template static void BM_HpackParserParseHeader(benchmark::State& state) { TrackCounters track_counters; grpc_core::ExecCtx exec_ctx; @@ -784,7 +784,7 @@ class RepresentativeServerTrailingMetadata { static void free_timeout(void* p) { gpr_free(p); } // Benchmark the current on_initial_header implementation -static grpc_error* OnInitialHeader(void* user_data, grpc_mdelem md) { +static grpc_error_handle OnInitialHeader(void* user_data, grpc_mdelem md) { // Setup for benchmark. This will bloat the absolute values of this benchmark grpc_chttp2_incoming_metadata_buffer buffer( static_cast(user_data)); @@ -825,7 +825,8 @@ static grpc_error* OnInitialHeader(void* user_data, grpc_mdelem md) { if (!seen_error) { buffer.size = new_size; } - grpc_error* error = grpc_chttp2_incoming_metadata_buffer_add(&buffer, md); + grpc_error_handle error = + grpc_chttp2_incoming_metadata_buffer_add(&buffer, md); if (error != GRPC_ERROR_NONE) { GPR_ASSERT(0); } @@ -834,7 +835,7 @@ static grpc_error* OnInitialHeader(void* user_data, grpc_mdelem md) { } // Benchmark timeout handling -static grpc_error* OnHeaderTimeout(void* /*user_data*/, grpc_mdelem md) { +static grpc_error_handle OnHeaderTimeout(void* /*user_data*/, grpc_mdelem md) { if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) { grpc_millis* cached_timeout = static_cast(grpc_mdelem_get_user_data(md, free_timeout)); diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc index 45144017d5b..92c6ccd2ecf 100644 --- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc +++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc @@ -111,7 +111,7 @@ class PhonyEndpoint : public grpc_endpoint { static void delete_from_pollset_set(grpc_endpoint* /*ep*/, grpc_pollset_set* /*pollset*/) {} - static void shutdown(grpc_endpoint* ep, grpc_error* why) { + static void shutdown(grpc_endpoint* ep, grpc_error_handle why) { grpc_resource_user_shutdown(static_cast(ep)->ru_); grpc_core::ExecCtx::Run(DEBUG_LOCATION, static_cast(ep)->read_cb_, why); @@ -139,7 +139,7 @@ class Fixture { grpc_channel_args c_args = args.c_channel_args(); ep_ = new PhonyEndpoint; t_ = grpc_create_chttp2_transport(&c_args, ep_, client); - grpc_chttp2_transport_start_reading(t_, nullptr, nullptr); + grpc_chttp2_transport_start_reading(t_, nullptr, nullptr, nullptr); FlushExecCtx(); } @@ -171,7 +171,7 @@ std::unique_ptr MakeTestClosure(F f) { GRPC_CLOSURE_INIT(this, Execute, this, nullptr); } F f_; - static void Execute(void* arg, grpc_error* error) { + static void Execute(void* arg, grpc_error_handle error) { static_cast(arg)->f_(error); } }; @@ -183,7 +183,7 @@ grpc_closure* MakeOnceClosure(F f) { struct C : public grpc_closure { explicit C(const F& f) : f_(f) {} F f_; - static void Execute(void* arg, grpc_error* error) { + static void Execute(void* arg, grpc_error_handle error) { static_cast(arg)->f_(error); delete static_cast(arg); } @@ -239,7 +239,7 @@ class Stream { } private: - static void FinishDestroy(void* arg, grpc_error* /*error*/) { + static void FinishDestroy(void* arg, grpc_error_handle /*error*/) { auto stream = static_cast(arg); grpc_transport_destroy_stream(stream->f_->transport(), static_cast(stream->stream_), @@ -273,7 +273,7 @@ static void BM_StreamCreateDestroy(benchmark::State& state) { op.payload = &op_payload; op_payload.cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; std::unique_ptr next = - MakeTestClosure([&, s](grpc_error* /*error*/) { + MakeTestClosure([&, s](grpc_error_handle /*error*/) { if (!state.KeepRunning()) { delete s; return; @@ -339,7 +339,7 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State& state) { f.FlushExecCtx(); gpr_event bm_done; gpr_event_init(&bm_done); - start = MakeTestClosure([&, s](grpc_error* /*error*/) { + start = MakeTestClosure([&, s](grpc_error_handle /*error*/) { if (!state.KeepRunning()) { delete s; gpr_event_set(&bm_done, (void*)1); @@ -352,7 +352,7 @@ static void BM_StreamCreateSendInitialMetadataDestroy(benchmark::State& state) { op.payload->send_initial_metadata.send_initial_metadata = &b; s->Op(&op); }); - done = MakeTestClosure([&](grpc_error* /*error*/) { + done = MakeTestClosure([&](grpc_error_handle /*error*/) { reset_op(); op.cancel_stream = true; op.payload->cancel_stream.cancel_error = GRPC_ERROR_CANCELLED; @@ -380,12 +380,13 @@ static void BM_TransportEmptyOp(benchmark::State& state) { op = {}; op.payload = &op_payload; }; - std::unique_ptr c = MakeTestClosure([&](grpc_error* /*error*/) { - if (!state.KeepRunning()) return; - reset_op(); - op.on_complete = c.get(); - s->Op(&op); - }); + std::unique_ptr c = + MakeTestClosure([&](grpc_error_handle /*error*/) { + if (!state.KeepRunning()) return; + reset_op(); + op.on_complete = c.get(); + s->Op(&op); + }); grpc_core::ExecCtx::Run(DEBUG_LOCATION, c.get(), GRPC_ERROR_NONE); f.FlushExecCtx(); reset_op(); @@ -394,7 +395,7 @@ static void BM_TransportEmptyOp(benchmark::State& state) { gpr_event* stream_cancel_done = new gpr_event; gpr_event_init(stream_cancel_done); std::unique_ptr stream_cancel_closure = - MakeTestClosure([&](grpc_error* error) { + MakeTestClosure([&](grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); gpr_event_set(stream_cancel_done, reinterpret_cast(1)); }); @@ -403,7 +404,8 @@ static void BM_TransportEmptyOp(benchmark::State& state) { f.FlushExecCtx(); gpr_event_wait(stream_cancel_done, gpr_inf_future(GPR_CLOCK_REALTIME)); done_events.emplace_back(stream_cancel_done); - s->DestroyThen(MakeOnceClosure([s](grpc_error* /*error*/) { delete s; })); + s->DestroyThen( + MakeOnceClosure([s](grpc_error_handle /*error*/) { delete s; })); f.FlushExecCtx(); track_counters.Finish(state); } @@ -442,25 +444,26 @@ static void BM_TransportStreamSend(benchmark::State& state) { gpr_event* bm_done = new gpr_event; gpr_event_init(bm_done); - std::unique_ptr c = MakeTestClosure([&](grpc_error* /*error*/) { - if (!state.KeepRunning()) { - gpr_event_set(bm_done, reinterpret_cast(1)); - return; - } - grpc_slice_buffer send_buffer; - grpc_slice_buffer_init(&send_buffer); - grpc_slice_buffer_add(&send_buffer, grpc_slice_ref(send_slice)); - send_stream.Init(&send_buffer, 0); - grpc_slice_buffer_destroy(&send_buffer); - // force outgoing window to be yuge - s->chttp2_stream()->flow_control->TestOnlyForceHugeWindow(); - f.chttp2_transport()->flow_control->TestOnlyForceHugeWindow(); - reset_op(); - op.on_complete = c.get(); - op.send_message = true; - op.payload->send_message.send_message.reset(send_stream.get()); - s->Op(&op); - }); + std::unique_ptr c = + MakeTestClosure([&](grpc_error_handle /*error*/) { + if (!state.KeepRunning()) { + gpr_event_set(bm_done, reinterpret_cast(1)); + return; + } + grpc_slice_buffer send_buffer; + grpc_slice_buffer_init(&send_buffer); + grpc_slice_buffer_add(&send_buffer, grpc_slice_ref(send_slice)); + send_stream.Init(&send_buffer, 0); + grpc_slice_buffer_destroy(&send_buffer); + // force outgoing window to be yuge + s->chttp2_stream()->flow_control->TestOnlyForceHugeWindow(); + f.chttp2_transport()->flow_control->TestOnlyForceHugeWindow(); + reset_op(); + op.on_complete = c.get(); + op.send_message = true; + op.payload->send_message.send_message.reset(send_stream.get()); + s->Op(&op); + }); reset_op(); op.send_initial_metadata = true; @@ -478,7 +481,7 @@ static void BM_TransportStreamSend(benchmark::State& state) { gpr_event* stream_cancel_done = new gpr_event; gpr_event_init(stream_cancel_done); std::unique_ptr stream_cancel_closure = - MakeTestClosure([&](grpc_error* error) { + MakeTestClosure([&](grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); gpr_event_set(stream_cancel_done, reinterpret_cast(1)); }); @@ -487,7 +490,8 @@ static void BM_TransportStreamSend(benchmark::State& state) { f.FlushExecCtx(); gpr_event_wait(stream_cancel_done, gpr_inf_future(GPR_CLOCK_REALTIME)); done_events.emplace_back(stream_cancel_done); - s->DestroyThen(MakeOnceClosure([s](grpc_error* /*error*/) { delete s; })); + s->DestroyThen( + MakeOnceClosure([s](grpc_error_handle /*error*/) { delete s; })); f.FlushExecCtx(); track_counters.Finish(state); grpc_metadata_batch_destroy(&b); @@ -582,7 +586,7 @@ static void BM_TransportStreamRecv(benchmark::State& state) { } std::unique_ptr do_nothing = - MakeTestClosure([](grpc_error* /*error*/) {}); + MakeTestClosure([](grpc_error_handle /*error*/) {}); uint32_t received; @@ -591,22 +595,23 @@ static void BM_TransportStreamRecv(benchmark::State& state) { std::unique_ptr drain_continue; grpc_slice recv_slice; - std::unique_ptr c = MakeTestClosure([&](grpc_error* /*error*/) { - if (!state.KeepRunning()) return; - // force outgoing window to be yuge - s->chttp2_stream()->flow_control->TestOnlyForceHugeWindow(); - f.chttp2_transport()->flow_control->TestOnlyForceHugeWindow(); - received = 0; - reset_op(); - op.on_complete = do_nothing.get(); - op.recv_message = true; - op.payload->recv_message.recv_message = &recv_stream; - op.payload->recv_message.recv_message_ready = drain_start.get(); - s->Op(&op); - f.PushInput(grpc_slice_ref(incoming_data)); - }); + std::unique_ptr c = + MakeTestClosure([&](grpc_error_handle /*error*/) { + if (!state.KeepRunning()) return; + // force outgoing window to be yuge + s->chttp2_stream()->flow_control->TestOnlyForceHugeWindow(); + f.chttp2_transport()->flow_control->TestOnlyForceHugeWindow(); + received = 0; + reset_op(); + op.on_complete = do_nothing.get(); + op.recv_message = true; + op.payload->recv_message.recv_message = &recv_stream; + op.payload->recv_message.recv_message_ready = drain_start.get(); + s->Op(&op); + f.PushInput(grpc_slice_ref(incoming_data)); + }); - drain_start = MakeTestClosure([&](grpc_error* /*error*/) { + drain_start = MakeTestClosure([&](grpc_error_handle /*error*/) { if (recv_stream == nullptr) { GPR_ASSERT(!state.KeepRunning()); return; @@ -614,7 +619,7 @@ static void BM_TransportStreamRecv(benchmark::State& state) { grpc_core::Closure::Run(DEBUG_LOCATION, drain.get(), GRPC_ERROR_NONE); }); - drain = MakeTestClosure([&](grpc_error* /*error*/) { + drain = MakeTestClosure([&](grpc_error_handle /*error*/) { do { if (received == recv_stream->length()) { recv_stream.reset(); @@ -628,7 +633,7 @@ static void BM_TransportStreamRecv(benchmark::State& state) { grpc_slice_unref_internal(recv_slice), true)); }); - drain_continue = MakeTestClosure([&](grpc_error* /*error*/) { + drain_continue = MakeTestClosure([&](grpc_error_handle /*error*/) { recv_stream->Pull(&recv_slice); received += GRPC_SLICE_LENGTH(recv_slice); grpc_slice_unref_internal(recv_slice); @@ -664,7 +669,7 @@ static void BM_TransportStreamRecv(benchmark::State& state) { gpr_event* stream_cancel_done = new gpr_event; gpr_event_init(stream_cancel_done); std::unique_ptr stream_cancel_closure = - MakeTestClosure([&](grpc_error* error) { + MakeTestClosure([&](grpc_error_handle error) { GPR_ASSERT(error == GRPC_ERROR_NONE); gpr_event_set(stream_cancel_done, reinterpret_cast(1)); }); @@ -673,7 +678,8 @@ static void BM_TransportStreamRecv(benchmark::State& state) { f.FlushExecCtx(); gpr_event_wait(stream_cancel_done, gpr_inf_future(GPR_CLOCK_REALTIME)); done_events.emplace_back(stream_cancel_done); - s->DestroyThen(MakeOnceClosure([s](grpc_error* /*error*/) { delete s; })); + s->DestroyThen( + MakeOnceClosure([s](grpc_error_handle /*error*/) { delete s; })); grpc_metadata_batch_destroy(&b); grpc_metadata_batch_destroy(&b_recv); f.FlushExecCtx(); diff --git a/test/cpp/microbenchmarks/bm_closure.cc b/test/cpp/microbenchmarks/bm_closure.cc index 440eac02362..e38f95f742d 100644 --- a/test/cpp/microbenchmarks/bm_closure.cc +++ b/test/cpp/microbenchmarks/bm_closure.cc @@ -51,7 +51,7 @@ static void BM_WellFlushed(benchmark::State& state) { } BENCHMARK(BM_WellFlushed); -static void DoNothing(void* /*arg*/, grpc_error* /*error*/) {} +static void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {} static void BM_ClosureInitAgainstExecCtx(benchmark::State& state) { TrackCounters track_counters; @@ -369,7 +369,7 @@ class Rescheduler { benchmark::State& state_; grpc_closure closure_; - static void Step(void* arg, grpc_error* /*error*/) { + static void Step(void* arg, grpc_error_handle /*error*/) { Rescheduler* self = static_cast(arg); if (self->state_.KeepRunning()) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, &self->closure_, GRPC_ERROR_NONE); diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc index f0082491be3..d57a021cee7 100644 --- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc +++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc @@ -56,8 +56,8 @@ static void pollset_init(grpc_pollset* ps, gpr_mu** mu) { static void pollset_destroy(grpc_pollset* ps) { gpr_mu_destroy(&ps->mu); } -static grpc_error* pollset_kick(grpc_pollset* /*p*/, - grpc_pollset_worker* /*worker*/) { +static grpc_error_handle pollset_kick(grpc_pollset* /*p*/, + grpc_pollset_worker* /*worker*/) { return GRPC_ERROR_NONE; } @@ -68,9 +68,9 @@ static void cq_done_cb(void* /*done_arg*/, grpc_cq_completion* cq_completion) { /* Queues a completion tag if deadline is > 0. * Does nothing if deadline is 0 (i.e gpr_time_0(GPR_CLOCK_MONOTONIC)) */ -static grpc_error* pollset_work(grpc_pollset* ps, - grpc_pollset_worker** /*worker*/, - grpc_millis deadline) { +static grpc_error_handle pollset_work(grpc_pollset* ps, + grpc_pollset_worker** /*worker*/, + grpc_millis deadline) { if (deadline == 0) { gpr_log(GPR_DEBUG, "no-op"); return GRPC_ERROR_NONE; @@ -98,8 +98,10 @@ static const grpc_event_engine_vtable* init_engine_vtable(bool) { g_vtable.pollset_work = pollset_work; g_vtable.pollset_kick = pollset_kick; g_vtable.is_any_background_poller_thread = [] { return false; }; - g_vtable.add_closure_to_background_poller = - [](grpc_closure* /*closure*/, grpc_error* /*error*/) { return false; }; + g_vtable.add_closure_to_background_poller = [](grpc_closure* /*closure*/, + grpc_error_handle /*error*/) { + return false; + }; g_vtable.shutdown_background_closure = [] {}; g_vtable.shutdown_engine = [] {}; diff --git a/test/cpp/microbenchmarks/bm_error.cc b/test/cpp/microbenchmarks/bm_error.cc index ce42f334ff1..ecc39accfad 100644 --- a/test/cpp/microbenchmarks/bm_error.cc +++ b/test/cpp/microbenchmarks/bm_error.cc @@ -30,7 +30,7 @@ class ErrorDeleter { public: - void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); } + void operator()(grpc_error_handle error) { GRPC_ERROR_UNREF(error); } }; typedef std::unique_ptr ErrorPtr; @@ -78,7 +78,7 @@ BENCHMARK(BM_ErrorCreateAndSetIntAndStr); static void BM_ErrorCreateAndSetIntLoop(benchmark::State& state) { TrackCounters track_counters; - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); int n = 0; for (auto _ : state) { error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, n++); @@ -90,7 +90,7 @@ BENCHMARK(BM_ErrorCreateAndSetIntLoop); static void BM_ErrorCreateAndSetStrLoop(benchmark::State& state) { TrackCounters track_counters; - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); const char* str = "hello"; for (auto _ : state) { error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, @@ -103,7 +103,7 @@ BENCHMARK(BM_ErrorCreateAndSetStrLoop); static void BM_ErrorRefUnref(benchmark::State& state) { TrackCounters track_counters; - grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); + grpc_error_handle error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"); for (auto _ : state) { GRPC_ERROR_UNREF(GRPC_ERROR_REF(error)); } @@ -158,7 +158,7 @@ BENCHMARK(BM_ErrorGetPresentInt); class ErrorNone { public: grpc_millis deadline() const { return deadline_; } - grpc_error* error() const { return GRPC_ERROR_NONE; } + grpc_error_handle error() const { return GRPC_ERROR_NONE; } private: const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; @@ -167,7 +167,7 @@ class ErrorNone { class ErrorCancelled { public: grpc_millis deadline() const { return deadline_; } - grpc_error* error() const { return GRPC_ERROR_CANCELLED; } + grpc_error_handle error() const { return GRPC_ERROR_CANCELLED; } private: const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; @@ -176,7 +176,7 @@ class ErrorCancelled { class SimpleError { public: grpc_millis deadline() const { return deadline_; } - grpc_error* error() const { return error_.get(); } + grpc_error_handle error() const { return error_.get(); } private: const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; @@ -186,7 +186,7 @@ class SimpleError { class ErrorWithGrpcStatus { public: grpc_millis deadline() const { return deadline_; } - grpc_error* error() const { return error_.get(); } + grpc_error_handle error() const { return error_.get(); } private: const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; @@ -198,7 +198,7 @@ class ErrorWithGrpcStatus { class ErrorWithHttpError { public: grpc_millis deadline() const { return deadline_; } - grpc_error* error() const { return error_.get(); } + grpc_error_handle error() const { return error_.get(); } private: const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; @@ -210,14 +210,14 @@ class ErrorWithHttpError { class ErrorWithNestedGrpcStatus { public: grpc_millis deadline() const { return deadline_; } - grpc_error* error() const { return error_.get(); } + grpc_error_handle error() const { return error_.get(); } private: const grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; ErrorPtr nested_error_{grpc_error_set_int( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Error"), GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNIMPLEMENTED)}; - grpc_error* nested_errors_[1] = {nested_error_.get()}; + grpc_error_handle nested_errors_[1] = {nested_error_.get()}; ErrorPtr error_{GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Error", nested_errors_, 1)}; }; diff --git a/test/cpp/microbenchmarks/bm_pollset.cc b/test/cpp/microbenchmarks/bm_pollset.cc index 928b5877920..ee813aa3970 100644 --- a/test/cpp/microbenchmarks/bm_pollset.cc +++ b/test/cpp/microbenchmarks/bm_pollset.cc @@ -41,7 +41,7 @@ #include #endif -static void shutdown_ps(void* ps, grpc_error* /*error*/) { +static void shutdown_ps(void* ps, grpc_error_handle /*error*/) { grpc_pollset_destroy(static_cast(ps)); } @@ -167,7 +167,7 @@ template TestClosure* MakeTestClosure(F f) { struct C : public TestClosure { explicit C(F f) : f_(f) { GRPC_CLOSURE_INIT(this, C::cbfn, this, nullptr); } - static void cbfn(void* arg, grpc_error* /*error*/) { + static void cbfn(void* arg, grpc_error_handle /*error*/) { C* p = static_cast(arg); p->f_(); } diff --git a/test/cpp/microbenchmarks/bm_timer.cc b/test/cpp/microbenchmarks/bm_timer.cc index 3b0e0e250e4..60bf65da661 100644 --- a/test/cpp/microbenchmarks/bm_timer.cc +++ b/test/cpp/microbenchmarks/bm_timer.cc @@ -47,8 +47,9 @@ static void BM_InitCancelTimer(benchmark::State& state) { for (auto _ : state) { TimerClosure* timer_closure = &timer_closures[i++ % kTimerCount]; GRPC_CLOSURE_INIT( - &timer_closure->closure, [](void* /*args*/, grpc_error* /*err*/) {}, - nullptr, grpc_schedule_on_exec_ctx); + &timer_closure->closure, + [](void* /*args*/, grpc_error_handle /*err*/) {}, nullptr, + grpc_schedule_on_exec_ctx); grpc_timer_init(&timer_closure->timer, GRPC_MILLIS_INF_FUTURE, &timer_closure->closure); grpc_timer_cancel(&timer_closure->timer); @@ -76,8 +77,9 @@ static void BM_TimerBatch(benchmark::State& state) { for (grpc_millis deadline = start; deadline != end; deadline += increment) { TimerClosure* timer_closure = &timer_closures[deadline % kTimerCount]; GRPC_CLOSURE_INIT( - &timer_closure->closure, [](void* /*args*/, grpc_error* /*err*/) {}, - nullptr, grpc_schedule_on_exec_ctx); + &timer_closure->closure, + [](void* /*args*/, grpc_error_handle /*err*/) {}, nullptr, + grpc_schedule_on_exec_ctx); grpc_timer_init(&timer_closure->timer, deadline, &timer_closure->closure); } diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h index b5e8028173d..4526dee952a 100644 --- a/test/cpp/microbenchmarks/fullstack_fixtures.h +++ b/test/cpp/microbenchmarks/fullstack_fixtures.h @@ -187,7 +187,8 @@ class EndpointPairFixture : public BaseFixture { server_->c_server()->core_server->SetupTransport( server_transport_, nullptr, server_args, nullptr); - grpc_chttp2_transport_start_reading(server_transport_, nullptr, nullptr); + grpc_chttp2_transport_start_reading(server_transport_, nullptr, nullptr, + nullptr); } /* create channel */ @@ -202,7 +203,8 @@ class EndpointPairFixture : public BaseFixture { GPR_ASSERT(client_transport_); grpc_channel* channel = grpc_channel_create( "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, client_transport_); - grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr); + grpc_chttp2_transport_start_reading(client_transport_, nullptr, nullptr, + nullptr); channel_ = ::grpc::CreateChannelInternal( "", channel, diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc index edcee212b10..e2b56c98899 100644 --- a/test/cpp/naming/address_sorting_test.cc +++ b/test/cpp/naming/address_sorting_test.cc @@ -35,6 +35,7 @@ #include "src/core/ext/filters/client_channel/resolver/dns/dns_resolver_selection.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/host_port.h" @@ -42,7 +43,6 @@ #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" #include "test/cpp/util/subprocess.h" diff --git a/test/cpp/naming/cancel_ares_query_test.cc b/test/cpp/naming/cancel_ares_query_test.cc index 371e3e5eb4e..239d7d4429e 100644 --- a/test/cpp/naming/cancel_ares_query_test.cc +++ b/test/cpp/naming/cancel_ares_query_test.cc @@ -96,7 +96,7 @@ void ArgsInit(ArgsStruct* args) { args->channel_args = nullptr; } -void DoNothing(void* /*arg*/, grpc_error* /*error*/) {} +void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {} void ArgsFinish(ArgsStruct* args) { grpc_pollset_set_del_pollset(args->pollset_set, args->pollset); @@ -146,7 +146,7 @@ class AssertFailureResultHandler : public grpc_core::Resolver::ResultHandler { GPR_ASSERT(false); } - void ReturnError(grpc_error* /*error*/) override { GPR_ASSERT(false); } + void ReturnError(grpc_error_handle /*error*/) override { GPR_ASSERT(false); } private: ArgsStruct* args_; diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc index 1fdc38d7a28..a8c39fc3fd7 100644 --- a/test/cpp/naming/resolver_component_test.cc +++ b/test/cpp/naming/resolver_component_test.cc @@ -42,15 +42,15 @@ #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/host_port.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/parse_address.h" #include "src/core/lib/iomgr/resolve_address.h" -#include "src/core/lib/iomgr/sockaddr_utils.h" #include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/iomgr/work_serializer.h" #include "test/core/util/port.h" @@ -210,7 +210,7 @@ void ArgsInit(ArgsStruct* args) { args->channel_args = nullptr; } -void DoNothing(void* /*arg*/, grpc_error* /*error*/) {} +void DoNothing(void* /*arg*/, grpc_error_handle /*error*/) {} void ArgsFinish(ArgsStruct* args) { GPR_ASSERT(gpr_event_wait(&args->ev, TestDeadline())); @@ -260,7 +260,7 @@ void PollPollsetUntilRequestDone(ArgsStruct* args) { } void CheckServiceConfigResultLocked(const char* service_config_json, - grpc_error* service_config_error, + grpc_error_handle service_config_error, ArgsStruct* args) { if (!args->expected_service_config_string.empty()) { GPR_ASSERT(service_config_json != nullptr); @@ -269,7 +269,7 @@ void CheckServiceConfigResultLocked(const char* service_config_json, if (args->expected_service_config_error.empty()) { EXPECT_EQ(service_config_error, GRPC_ERROR_NONE); } else { - EXPECT_THAT(grpc_error_string(service_config_error), + EXPECT_THAT(grpc_error_std_string(service_config_error), testing::HasSubstr(args->expected_service_config_error)); } GRPC_ERROR_UNREF(service_config_error); @@ -435,8 +435,9 @@ class ResultHandler : public grpc_core::Resolver::ResultHandler { gpr_mu_unlock(args_->mu); } - void ReturnError(grpc_error* error) override { - gpr_log(GPR_ERROR, "resolver returned error: %s", grpc_error_string(error)); + void ReturnError(grpc_error_handle error) override { + gpr_log(GPR_ERROR, "resolver returned error: %s", + grpc_error_std_string(error).c_str()); GPR_ASSERT(false); } diff --git a/test/cpp/performance/writes_per_rpc_test.cc b/test/cpp/performance/writes_per_rpc_test.cc index d3273ee7949..045e29776e7 100644 --- a/test/cpp/performance/writes_per_rpc_test.cc +++ b/test/cpp/performance/writes_per_rpc_test.cc @@ -82,7 +82,7 @@ class EndpointPairFixture { server_->c_server()->core_server->SetupTransport(transport, nullptr, server_args, nullptr); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); } /* create channel */ @@ -97,7 +97,7 @@ class EndpointPairFixture { GPR_ASSERT(transport); grpc_channel* channel = grpc_channel_create( "target", &c_args, GRPC_CLIENT_DIRECT_CHANNEL, transport); - grpc_chttp2_transport_start_reading(transport, nullptr, nullptr); + grpc_chttp2_transport_start_reading(transport, nullptr, nullptr, nullptr); channel_ = ::grpc::CreateChannelInternal( "", channel, diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc index 2dec82ae11e..f757b0c9c39 100644 --- a/test/cpp/qps/client_async.cc +++ b/test/cpp/qps/client_async.cc @@ -142,7 +142,7 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext { if (!next_issue_) { // ready to issue RunNextState(true, nullptr); } else { // wait for the issue time - alarm_.reset(new Alarm); + alarm_ = absl::make_unique(); alarm_->Set(cq_, next_issue_(), ClientRpcContext::tag(this)); } } @@ -371,7 +371,7 @@ class ClientRpcContextStreamingPingPongImpl : public ClientRpcContext { break; // loop around, don't return case State::WAIT: next_state_ = State::READY_TO_WRITE; - alarm_.reset(new Alarm); + alarm_ = absl::make_unique(); alarm_->Set(cq_, next_issue_(), ClientRpcContext::tag(this)); return true; case State::READY_TO_WRITE: @@ -556,7 +556,7 @@ class ClientRpcContextStreamingFromClientImpl : public ClientRpcContext { } break; // loop around, don't return case State::WAIT: - alarm_.reset(new Alarm); + alarm_ = absl::make_unique(); alarm_->Set(cq_, next_issue_(), ClientRpcContext::tag(this)); next_state_ = State::READY_TO_WRITE; return true; diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc index c53abd5b9c0..0ae85290d26 100644 --- a/test/cpp/qps/driver.cc +++ b/test/cpp/qps/driver.cc @@ -634,9 +634,7 @@ std::unique_ptr RunScenario( ReceiveFinalStatusFromServer(servers, *result); ShutdownServers(servers, *result); - if (g_inproc_servers != nullptr) { - delete g_inproc_servers; - } + delete g_inproc_servers; merged_latencies.FillProto(result->mutable_latencies()); for (std::unordered_map::iterator it = merged_statuses.begin(); diff --git a/test/cpp/qps/json_run_localhost.cc b/test/cpp/qps/json_run_localhost.cc index eaa6e4a1b5f..b515efebf8d 100644 --- a/test/cpp/qps/json_run_localhost.cc +++ b/test/cpp/qps/json_run_localhost.cc @@ -125,9 +125,8 @@ int main(int argc, char** argv) { } } - if (g_driver != nullptr) { - delete g_driver; - } + delete g_driver; + g_driver = nullptr; for (int i = 0; i < kNumWorkers; ++i) { if (g_workers[i] != nullptr) { diff --git a/test/cpp/qps/parse_json.cc b/test/cpp/qps/parse_json.cc index 8777f171420..f3ac1052d4d 100644 --- a/test/cpp/qps/parse_json.cc +++ b/test/cpp/qps/parse_json.cc @@ -34,7 +34,7 @@ void ParseJson(const std::string& json, const std::string& type, auto status = JsonToBinaryString( type_resolver.get(), "type.googleapis.com/" + type, json, &binary); if (!status.ok()) { - std::string errmsg(status.error_message()); + std::string errmsg(status.message()); gpr_log(GPR_ERROR, "Failed to convert json to binary: errcode=%d msg=%s", status.code(), errmsg.c_str()); gpr_log(GPR_ERROR, "JSON: %s", json.c_str()); diff --git a/test/cpp/test/BUILD b/test/cpp/test/BUILD index 01ebb761dd3..13d816c49fa 100644 --- a/test/cpp/test/BUILD +++ b/test/cpp/test/BUILD @@ -21,6 +21,23 @@ grpc_package( visibility = "public", ) +grpc_cc_test( + name = "mock_stream_test", + srcs = ["mock_stream_test.cc"], + external_deps = [ + "gtest", + ], + deps = [ + "//:gpr", + "//:grpc", + "//:grpc++", + "//:grpc++_test", + "//src/proto/grpc/testing:echo_proto", + "//test/core/util:grpc_test_util", + "//test/cpp/util:test_util", + ], +) + grpc_cc_test( name = "client_context_test_peer_test", srcs = ["client_context_test_peer_test.cc"], diff --git a/test/cpp/test/mock_stream_test.cc b/test/cpp/test/mock_stream_test.cc new file mode 100644 index 00000000000..6545762c75e --- /dev/null +++ b/test/cpp/test/mock_stream_test.cc @@ -0,0 +1,60 @@ +/* + * + * Copyright 2020 the gRPC authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include "absl/memory/memory.h" + +#include "src/proto/grpc/testing/echo.grpc.pb.h" + +using grpc::testing::EchoRequest; +using grpc::testing::EchoResponse; + +TEST(MockStreamTest, Basic) { + auto cr = absl::make_unique>(); + ASSERT_NE(cr, nullptr); + + auto cw = absl::make_unique>(); + ASSERT_NE(cw, nullptr); + + auto crw = absl::make_unique< + grpc::testing::MockClientReaderWriter>(); + ASSERT_NE(crw, nullptr); + + auto carr = absl::make_unique< + grpc::testing::MockClientAsyncResponseReader>(); + ASSERT_NE(carr, nullptr); + + auto car = + absl::make_unique>(); + ASSERT_NE(car, nullptr); + + auto caw = + absl::make_unique>(); + ASSERT_NE(caw, nullptr); + + auto carw = absl::make_unique< + grpc::testing::MockClientAsyncReaderWriter>(); + ASSERT_NE(carw, nullptr); +} + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/cpp/util/channel_trace_proto_helper.cc b/test/cpp/util/channel_trace_proto_helper.cc index 88fb7e423dc..2e1c7bee04c 100644 --- a/test/cpp/util/channel_trace_proto_helper.cc +++ b/test/cpp/util/channel_trace_proto_helper.cc @@ -58,10 +58,10 @@ void VaidateProtoJsonTranslation(const std::string& json_str) { EXPECT_TRUE(s.ok()); // Parse JSON and re-dump to string, to make sure formatting is the // same as what would be generated by our JSON library. - grpc_error* error = GRPC_ERROR_NONE; + grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::Json parsed_json = grpc_core::Json::Parse(proto_json_str.c_str(), &error); - ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_string(error); + ASSERT_EQ(error, GRPC_ERROR_NONE) << grpc_error_std_string(error); ASSERT_EQ(parsed_json.type(), grpc_core::Json::Type::OBJECT); proto_json_str = parsed_json.Dump(); // uncomment these to compare the json strings. diff --git a/test/cpp/util/cli_credentials.cc b/test/cpp/util/cli_credentials.cc index 183d3edcf90..0c09872ff87 100644 --- a/test/cpp/util/cli_credentials.cc +++ b/test/cpp/util/cli_credentials.cc @@ -169,7 +169,7 @@ std::shared_ptr CliCredentials::GetCredentials() : grpc::CompositeChannelCredentials(channel_creds, call_creds); } -const std::string CliCredentials::GetCredentialUsage() const { +std::string CliCredentials::GetCredentialUsage() const { return " --ssl_target ; Set server host for ssl validation\n" " --ssl_client_cert ; Client cert for ssl\n" " --ssl_client_key ; Client private key for ssl\n" @@ -180,7 +180,7 @@ const std::string CliCredentials::GetCredentialUsage() const { " access_token=\n"; } -const std::string CliCredentials::GetSslTargetNameOverride() const { +std::string CliCredentials::GetSslTargetNameOverride() const { bool use_ssl = absl::GetFlag(FLAGS_channel_creds_type) == "ssl" || absl::GetFlag(FLAGS_channel_creds_type) == "gdc"; return use_ssl ? absl::GetFlag(FLAGS_ssl_target) : ""; diff --git a/test/cpp/util/cli_credentials.h b/test/cpp/util/cli_credentials.h index 8595eb425d1..4c534fa5f54 100644 --- a/test/cpp/util/cli_credentials.h +++ b/test/cpp/util/cli_credentials.h @@ -29,8 +29,8 @@ class CliCredentials { public: virtual ~CliCredentials() {} std::shared_ptr GetCredentials() const; - virtual const std::string GetCredentialUsage() const; - virtual const std::string GetSslTargetNameOverride() const; + virtual std::string GetCredentialUsage() const; + virtual std::string GetSslTargetNameOverride() const; protected: // Returns the appropriate channel_creds_type value for the set of legacy diff --git a/test/cpp/util/grpc_tool.cc b/test/cpp/util/grpc_tool.cc index 0c73135648a..0175b0cf4e9 100644 --- a/test/cpp/util/grpc_tool.cc +++ b/test/cpp/util/grpc_tool.cc @@ -52,7 +52,9 @@ ABSL_FLAG(bool, remotedb, true, "Use server types to parse and format messages"); ABSL_FLAG(std::string, metadata, "", "Metadata to send to server, in the form of key1:val1:key2:val2"); -ABSL_FLAG(std::string, proto_path, ".", "Path to look for the proto file."); +ABSL_FLAG(std::string, proto_path, ".", + "Path to look for the proto file. " + "Multiple paths can be separated by " GRPC_CLI_PATH_SEPARATOR); ABSL_FLAG(std::string, protofiles, "", "Name of the proto file."); ABSL_FLAG(bool, binary_input, false, "Input in binary format"); ABSL_FLAG(bool, binary_output, false, "Output in binary format"); @@ -489,8 +491,9 @@ bool GrpcTool::CallMethod(int argc, const char** argv, " ; Text protobuffer (overrides infile)\n" " --protofiles ; Comma separated proto files used as a" " fallback when parsing request/response\n" - " --proto_path ; The search path of proto files, valid" - " only when --protofiles is given\n" + " --proto_path ; The search paths of proto files" + " (" GRPC_CLI_PATH_SEPARATOR + " separated), valid only when --protofiles is given\n" " --noremotedb ; Don't attempt to use reflection service" " at all\n" " --metadata ; The metadata to be sent to the server\n" @@ -856,8 +859,9 @@ bool GrpcTool::ParseMessage(int argc, const char** argv, " ; Text protobuffer (overrides --infile)\n" " --protofiles ; Comma separated proto files used as a" " fallback when parsing request/response\n" - " --proto_path ; The search path of proto files, valid" - " only when --protofiles is given\n" + " --proto_path ; The search paths of proto files" + " (" GRPC_CLI_PATH_SEPARATOR + " separated), valid only when --protofiles is given\n" " --noremotedb ; Don't attempt to use reflection service" " at all\n" " --infile ; Input filename (defaults to stdin)\n" @@ -946,7 +950,9 @@ bool GrpcTool::ToText(int argc, const char** argv, const CliCredentials& cred, " grpc_cli totext \n" " ; Comma separated list of proto files\n" " ; Protocol buffer type name\n" - " --proto_path ; The search path of proto files\n" + " --proto_path ; The search paths of proto files" + " (" GRPC_CLI_PATH_SEPARATOR + " separated)\n" " --infile ; Input filename (defaults to stdin)\n" " --outfile ; Output filename (defaults to stdout)\n"); @@ -964,7 +970,9 @@ bool GrpcTool::ToJson(int argc, const char** argv, const CliCredentials& cred, " grpc_cli tojson \n" " ; Comma separated list of proto files\n" " ; Protocol buffer type name\n" - " --proto_path ; The search path of proto files\n" + " --proto_path ; The search paths of proto files" + " (" GRPC_CLI_PATH_SEPARATOR + " separated)\n" " --infile ; Input filename (defaults to stdin)\n" " --outfile ; Output filename (defaults to stdout)\n"); @@ -983,7 +991,9 @@ bool GrpcTool::ToBinary(int argc, const char** argv, const CliCredentials& cred, " grpc_cli tobinary []\n" " ; Comma separated list of proto files\n" " ; Protocol buffer type name\n" - " --proto_path ; The search path of proto files\n" + " --proto_path ; The search paths of proto files" + " (" GRPC_CLI_PATH_SEPARATOR + " separated)\n" " --infile ; Input filename (defaults to stdin)\n" " --outfile ; Output filename (defaults to stdout)\n"); diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc index 5a19b4f9514..870d4768d4f 100644 --- a/test/cpp/util/grpc_tool_test.cc +++ b/test/cpp/util/grpc_tool_test.cc @@ -150,7 +150,7 @@ class TestCliCredentials final : public grpc::testing::CliCredentials { grpc_slice_unref(ca_slice); return credential_ptr; } - const std::string GetCredentialUsage() const override { return ""; } + std::string GetCredentialUsage() const override { return ""; } private: const bool secure_; @@ -284,7 +284,7 @@ class GrpcToolTest : public ::testing::Test { // SetUpServer cannot be used with EXPECT_EXIT. grpc_pick_unused_port_or_die() // uses atexit() to free chosen ports, and it will spawn a new thread in // resolve_address_posix.c:192 at exit time. - const std::string SetUpServer(bool secure = false) { + std::string SetUpServer(bool secure = false) { std::ostringstream server_address; int port = grpc_pick_unused_port_or_die(); server_address << "localhost:" << port; diff --git a/test/cpp/util/proto_file_parser.cc b/test/cpp/util/proto_file_parser.cc index a4f9b054e40..7a977f3148f 100644 --- a/test/cpp/util/proto_file_parser.cc +++ b/test/cpp/util/proto_file_parser.cc @@ -24,6 +24,7 @@ #include #include "absl/memory/memory.h" +#include "absl/strings/str_split.h" #include @@ -79,7 +80,10 @@ ProtoFileParser::ProtoFileParser(const std::shared_ptr& channel, std::unordered_set known_services; if (!protofiles.empty()) { - source_tree_.MapPath("", proto_path); + for (const absl::string_view single_path : absl::StrSplit( + proto_path, GRPC_CLI_PATH_SEPARATOR, absl::AllowEmpty())) { + source_tree_.MapPath("", std::string(single_path)); + } error_printer_ = absl::make_unique(this); importer_ = absl::make_unique( &source_tree_, error_printer_.get()); diff --git a/test/cpp/util/proto_file_parser.h b/test/cpp/util/proto_file_parser.h index 38abbc12cb9..29ea6331316 100644 --- a/test/cpp/util/proto_file_parser.h +++ b/test/cpp/util/proto_file_parser.h @@ -26,6 +26,12 @@ #include "test/cpp/util/config_grpc_cli.h" #include "test/cpp/util/proto_reflection_descriptor_database.h" +#if defined(_WIN32) && !defined(__CYGWIN__) +#define GRPC_CLI_PATH_SEPARATOR ";" +#else +#define GRPC_CLI_PATH_SEPARATOR ":" +#endif + namespace grpc { namespace testing { class ErrorPrinter; diff --git a/test/cpp/util/proto_reflection_descriptor_database.cc b/test/cpp/util/proto_reflection_descriptor_database.cc index f2c18f5c23f..f2356021dff 100644 --- a/test/cpp/util/proto_reflection_descriptor_database.cc +++ b/test/cpp/util/proto_reflection_descriptor_database.cc @@ -290,7 +290,7 @@ bool ProtoReflectionDescriptorDatabase::GetServices( return false; } -const protobuf::FileDescriptorProto +protobuf::FileDescriptorProto ProtoReflectionDescriptorDatabase::ParseFileDescriptorProtoResponse( const std::string& byte_fd_proto) { protobuf::FileDescriptorProto file_desc_proto; @@ -310,7 +310,7 @@ void ProtoReflectionDescriptorDatabase::AddFileFromResponse( } } -const std::shared_ptr +std::shared_ptr ProtoReflectionDescriptorDatabase::GetStream() { if (!stream_) { stream_ = stub_->ServerReflectionInfo(&ctx_); diff --git a/test/cpp/util/proto_reflection_descriptor_database.h b/test/cpp/util/proto_reflection_descriptor_database.h index c6dc62f571a..f1f752126e3 100644 --- a/test/cpp/util/proto_reflection_descriptor_database.h +++ b/test/cpp/util/proto_reflection_descriptor_database.h @@ -82,13 +82,13 @@ class ProtoReflectionDescriptorDatabase : public protobuf::DescriptorDatabase { grpc::reflection::v1alpha::ServerReflectionResponse> ClientStream; - const protobuf::FileDescriptorProto ParseFileDescriptorProtoResponse( + protobuf::FileDescriptorProto ParseFileDescriptorProtoResponse( const std::string& byte_fd_proto); void AddFileFromResponse( const grpc::reflection::v1alpha::FileDescriptorResponse& response); - const std::shared_ptr GetStream(); + std::shared_ptr GetStream(); bool DoOneRequest( const grpc::reflection::v1alpha::ServerReflectionRequest& request, diff --git a/test/distrib/php/run_distrib_test.sh b/test/distrib/php/run_distrib_test.sh index a6102f60758..0ca30f407bb 100755 --- a/test/distrib/php/run_distrib_test.sh +++ b/test/distrib/php/run_distrib_test.sh @@ -20,6 +20,6 @@ cd "$(dirname "$0")" cp -r "$EXTERNAL_GIT_ROOT"/input_artifacts/grpc-*.tgz . find . -regex ".*/grpc-[0-9].*.tgz" | cut -b3- | \ - xargs pecl install + MAKEFLAGS=-j xargs pecl install php -d extension=grpc.so -d max_execution_time=300 distribtest.php diff --git a/test/distrib/php/run_distrib_test_macos.sh b/test/distrib/php/run_distrib_test_macos.sh index 8def0498604..1ec38c659a6 100755 --- a/test/distrib/php/run_distrib_test_macos.sh +++ b/test/distrib/php/run_distrib_test_macos.sh @@ -20,6 +20,6 @@ cd "$(dirname "$0")" cp -r "$EXTERNAL_GIT_ROOT"/input_artifacts/grpc-*.tgz . find . -regex ".*/grpc-[0-9].*.tgz" | cut -b3- | \ - xargs sudo pecl install + xargs sudo MAKEFLAGS=-j pecl install php -d extension=grpc.so -d max_execution_time=300 distribtest.php diff --git a/test/distrib/python/distribtest.py b/test/distrib/python/distribtest.py index 1144786c48d..0fc2854c778 100644 --- a/test/distrib/python/distribtest.py +++ b/test/distrib/python/distribtest.py @@ -18,4 +18,4 @@ import grpc # which is what we are testing here. channel = grpc.insecure_channel('localhost:1000') del channel -print 'Success!' +print('Success!') diff --git a/third_party/README.md b/third_party/README.md index 473b5426449..b93570f1a9f 100644 --- a/third_party/README.md +++ b/third_party/README.md @@ -81,9 +81,9 @@ git commit -m "update submodule boringssl-with-bazel with origin/master-with-baz - Run `tools/buildgen/generate_projects.sh` to regenerate the generated files - Because `sha256` in `bazel/grpc_deps.bzl` was left empty, you will get a DEBUG msg like this one: -``` -Rule 'boringssl' indicated that a canonical reproducible form can be obtained by modifying arguments sha256 = "SHA value" -``` + ``` + Rule 'boringssl' indicated that a canonical reproducible form can be obtained by modifying arguments sha256 = "SHA value" + ``` - Commit the regenrated files `git commit -m "regenerate files"` - Update `bazel/grpc_deps.bzl` with the SHA value shown in the above debug msg. Commit again `git commit -m "Updated sha256"` @@ -105,3 +105,10 @@ Rule 'boringssl' indicated that a canonical reproducible form can be obtained by ### Updating third_party/protobuf See http://go/grpc-third-party-protobuf-update-instructions (internal only) + +### Updating third_party/envoy-api + +Apart from the above steps, please perform the following two steps to generate the Python `xds-protos` package: + +1. Bump the version in the `tools/distrib/python/xds_protos/setup.py`; +2. Run `tools/distrib/python/xds_protos/build_validate_upload.sh` to upload the built wheel. diff --git a/third_party/abseil-cpp b/third_party/abseil-cpp index 6f9d96a1f41..997aaf3a283 160000 --- a/third_party/abseil-cpp +++ b/third_party/abseil-cpp @@ -1 +1 @@ -Subproject commit 6f9d96a1f41439ac172ee2ef7ccd8edf0e5d068c +Subproject commit 997aaf3a28308eba1b9156aa35ab7bca9688e9f6 diff --git a/third_party/benchmark b/third_party/benchmark index 090faecb454..73d4d5e8d6d 160000 --- a/third_party/benchmark +++ b/third_party/benchmark @@ -1 +1 @@ -Subproject commit 090faecb454fbd6e6e17a75ef8146acb037118d4 +Subproject commit 73d4d5e8d6d449fc8663765a42aa8aeeee844489 diff --git a/third_party/boringssl-with-bazel b/third_party/boringssl-with-bazel index 1a735945522..688fc5cf542 160000 --- a/third_party/boringssl-with-bazel +++ b/third_party/boringssl-with-bazel @@ -1 +1 @@ -Subproject commit 1a7359455220f7010def8c63f7c7e041ce6707c6 +Subproject commit 688fc5cf5428868679d2ae1072cad81055752068 diff --git a/third_party/protobuf b/third_party/protobuf index d7e943b8d2b..436bd7880e4 160000 --- a/third_party/protobuf +++ b/third_party/protobuf @@ -1 +1 @@ -Subproject commit d7e943b8d2bc444a8c770644e73d090b486f8b37 +Subproject commit 436bd7880e458532901c58f4d9d1ea23fa7edd52 diff --git a/third_party/protobuf.patch b/third_party/protobuf.patch index 79220868e4a..f7ff1dd667a 100644 --- a/third_party/protobuf.patch +++ b/third_party/protobuf.patch @@ -5,7 +5,7 @@ index 97ac28028..8b7585d9d 100644 @@ -31,3 +31,9 @@ # Copyright 2007 Google Inc. All Rights Reserved. - __version__ = '3.15.2' + __version__ = '3.15.8' + +if __name__ != '__main__': + try: diff --git a/third_party/py/BUILD b/third_party/py/BUILD index e69de29bb2d..6ab5124ce3c 100644 --- a/third_party/py/BUILD +++ b/third_party/py/BUILD @@ -0,0 +1,5 @@ +exports_files([ + "BUILD.tpl", + "python_configure.bzl", + "variety.tpl" +]) diff --git a/third_party/py/python_configure.bzl b/third_party/py/python_configure.bzl index 88fcb1006fb..fa47d89ebc9 100644 --- a/third_party/py/python_configure.bzl +++ b/third_party/py/python_configure.bzl @@ -348,7 +348,7 @@ def _python_autoconf_impl(repository_ctx): repository_ctx, "_python2", _PYTHON2_BIN_PATH, - "python", + "python2", _PYTHON2_LIB_PATH, True ) diff --git a/third_party/xxhash/.gitattributes b/third_party/xxhash/.gitattributes new file mode 100644 index 00000000000..fbcf75b5553 --- /dev/null +++ b/third_party/xxhash/.gitattributes @@ -0,0 +1,10 @@ +# Set the default behavior +* text eol=lf + +# Explicitly declare source files +*.c text eol=lf +*.h text eol=lf + +# Denote files that should not be modified. +*.odt binary + diff --git a/third_party/xxhash/.gitignore b/third_party/xxhash/.gitignore new file mode 100644 index 00000000000..d0ce9aac3b8 --- /dev/null +++ b/third_party/xxhash/.gitignore @@ -0,0 +1,47 @@ +# objects +*.o +*.obj +*.s + +# libraries +libxxhash.* +!libxxhash.pc.in + +# Executables +*.exe +xxh32sum +xxh64sum +xxh128sum +xxhsum +xxhsum32 +xxhsum_privateXXH +xxhsum_inlinedXXH +dispatch +tests/generate_unicode_test + +# compilation chain +.clang_complete + +# Mac OS-X artefacts +*.dSYM +.DS_Store + +# Wasm / emcc / emscripten artefacts +*.html +*.wasm +*.js + +# CMake build directories +build*/ + +# project managers artifacts +.projectile + +# analyzer artifacts +infer-out + +# test artifacts +.test* +tmp* +tests/*.unicode +tests/unicode_test* diff --git a/third_party/xxhash/.travis.yml b/third_party/xxhash/.travis.yml new file mode 100644 index 00000000000..834768699c9 --- /dev/null +++ b/third_party/xxhash/.travis.yml @@ -0,0 +1,138 @@ +language: c + +# Dump CPU info before start +before_install: + - cat /proc/cpuinfo || echo /proc/cpuinfo is not present + +matrix: + fast_finish: true + include: + + - name: General linux x64 tests + arch: amd64 + addons: + apt: + packages: + - g++-multilib + - gcc-multilib + - cppcheck + script: + - make -B test-all + - make clean + - CFLAGS="-Werror" MOREFLAGS="-Wno-sign-conversion" make dispatch # removing sign conversion warnings due to a bug in gcc-5's definition of some AVX512 intrinsics + - make clean + - CC=g++ CFLAGS="-O1 -mavx512f -Werror" make + - make clean + - CC=g++ CFLAGS="-Wall -Wextra -Werror" make DISPATCH=1 + + + - name: Check results consistency on x64 + arch: amd64 + script: + - CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR make check # Scalar code path + - make clean + - CPPFLAGS=-DXXH_VECTOR=XXH_SSE2 make check # SSE2 code path + - make clean + - CPPFLAGS="-mavx2 -DXXH_VECTOR=XXH_AVX2" make check # AVX2 code path + - make clean + - CPPFLAGS="-mavx512f -DXXH_VECTOR=XXH_AVX512" make check # AVX512 code path + - make clean + - CPPFLAGS=-DXXH_REROLL=1 make check # reroll code path (#240) + - make -C tests/bench + + - name: macOS General Test + os: osx + compiler: clang + script: + - CFLAGS="-Werror" make # test library build + - make clean + - make test MOREFLAGS='-Werror' | tee # test scenario where `stdout` is not the console + + - name: ARM compilation and consistency checks (Qemu) + dist: xenial + arch: amd64 + addons: + apt: + packages: + - qemu-system-arm + - qemu-user-static + - gcc-arm-linux-gnueabi + - libc6-dev-armel-cross + script: + # arm (32-bit) + - CC=arm-linux-gnueabi-gcc CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR LDFLAGS=-static RUN_ENV=qemu-arm-static make check # Scalar code path + - make clean + # NEON (32-bit) + - CC=arm-linux-gnueabi-gcc CPPFLAGS=-DXXH_VECTOR=XXH_NEON CFLAGS="-O3 -march=armv7-a -fPIC -mfloat-abi=softfp -mfpu=neon-vfpv4" LDFLAGS=-static RUN_ENV=qemu-arm-static make check # NEON code path + + - name: aarch64 compilation and consistency checks + dist: xenial + arch: arm64 + script: + # aarch64 + - CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR make check # Scalar code path + # NEON (64-bit) + - make clean + - CPPFLAGS=-DXXH_VECTOR=XXH_NEON make check # NEON code path + # clang + - make clean + - CC=clang CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR make check # Scalar code path + # clang + NEON + - make clean + - CC=clang CPPFLAGS=-DXXH_VECTOR=XXH_NEON make check # NEON code path + + # We need Bionic here because the QEMU versions shipped in the older repos + # do not support POWER8 emulation, and compiling QEMU from source is a pain. + - name: PowerPC + PPC64 compilation and consistency checks (Qemu on Bionic) + dist: bionic + arch: amd64 + addons: + apt: + packages: + - qemu-system-ppc + - qemu-user-static + - gcc-powerpc-linux-gnu + - gcc-powerpc64-linux-gnu + - libc6-dev-powerpc-cross + - libc6-dev-ppc64-cross + script: + - CC=powerpc-linux-gnu-gcc RUN_ENV=qemu-ppc-static LDFLAGS=-static make check # Scalar code path + - make clean + - CC=powerpc64-linux-gnu-gcc RUN_ENV=qemu-ppc64-static CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR CFLAGS="-O3" LDFLAGS="-static -m64" make check # Scalar code path + # VSX code + - make clean + - CC=powerpc64-linux-gnu-gcc RUN_ENV="qemu-ppc64-static -cpu power8" CPPFLAGS=-DXXH_VECTOR=XXH_VSX CFLAGS="-O3 -maltivec -mvsx -mcpu=power8 -mpower8-vector" LDFLAGS="-static -m64" make check # VSX code path + # altivec.h redefinition issue #426 + - make clean + - CC=powerpc64-linux-gnu-gcc CPPFLAGS=-DXXH_VECTOR=XXH_VSX CFLAGS="-maltivec -mvsx -mcpu=power8 -mpower8-vector" make -C tests test_ppc_redefine + + - name: PPC64LE compilation and consistency checks + dist: xenial + arch: ppc64le + script: + # Scalar (universal) code path + - CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR LDFLAGS=-static make check + # VSX code path (64-bit) + - make clean + - CPPFLAGS=-DXXH_VECTOR=XXH_VSX CFLAGS="-O3 -maltivec -mvsx -mpower8-vector -mcpu=power8" LDFLAGS="-static" make check + # altivec.h redefinition issue #426 + - make clean + - CPPFLAGS=-DXXH_VECTOR=XXH_VSX CFLAGS="-maltivec -mvsx -mcpu=power8 -mpower8-vector" make -C tests test_ppc_redefine + + - name: IBM s390x compilation and consistency checks + dist: bionic + arch: s390x + script: + # Scalar (universal) code path + - CPPFLAGS=-DXXH_VECTOR=XXH_SCALAR LDFLAGS=-static make check + # s390x code path (64-bit) + - make clean + - CPPFLAGS=-DXXH_VECTOR=XXH_VSX CFLAGS="-O3 -march=arch11 -mzvector" LDFLAGS="-static" make check + + - name: cmake build test + script: + - cd cmake_unofficial + - mkdir build + - cd build + - cmake .. + - CFLAGS=-Werror make diff --git a/third_party/xxhash/BUILD b/third_party/xxhash/BUILD new file mode 100644 index 00000000000..91d7bd05669 --- /dev/null +++ b/third_party/xxhash/BUILD @@ -0,0 +1,12 @@ +# TODO(donnadionne): describe this package. +cc_library( + name = "xxhash", + hdrs = [ + "xxhash.h", + ], + # Must specify the includes so that the header file can be found. + includes = [ + "", + ], + visibility = ["//visibility:public"], +) diff --git a/third_party/xxhash/CHANGELOG b/third_party/xxhash/CHANGELOG new file mode 100644 index 00000000000..23870756bb4 --- /dev/null +++ b/third_party/xxhash/CHANGELOG @@ -0,0 +1,52 @@ +v0.8.0 +- api : stabilize XXH3 +- cli : xxhsum can parse BSD-style --check lines, by @WayneD +- cli : `xxhsum -` accepts console input, requested by @jaki +- cli : xxhsum accepts -- separator, by @jaki +- cli : fix : print correct default algo for symlinked helpers, by @martinetd +- install: improved pkgconfig script, allowing custom install locations, requested by @ellert + +v0.7.4 +- perf: automatic vector detection and selection at runtime (`xxh_x86dispatch.h`), initiated by @easyaspi314 +- perf: added AVX512 support, by @gzm55 +- api : new: secret generator `XXH_generateSecret()`, suggested by @koraa +- api : fix: XXH3_state_t is movable, identified by @koraa +- api : fix: state is correctly aligned in AVX mode (unlike `malloc()`), by @easyaspi314 +- api : fix: streaming generated wrong values in some combination of random ingestion lengths, reported by @WayneD +- cli : fix unicode print on Windows, by @easyaspi314 +- cli : can `-c` check file generated by sfv +- build: `make DISPATCH=1` generates `xxhsum` and `libxxhash` with runtime vector detection (x86/x64 only) +- install: cygwin installation support +- doc : Cryptol specification of XXH32 and XXH64, by @weaversa + +v0.7.3 +- perf: improved speed for large inputs (~+20%) +- perf: improved latency for small inputs (~10%) +- perf: s390x Vectorial code, by @easyaspi314 +- cli: improved support for Unicode filenames on Windows, thanks to @easyaspi314 and @t-mat +- api: `xxhash.h` can now be included in any order, with and without `XXH_STATIC_LINKING_ONLY` and `XXH_INLINE_ALL` +- build: xxHash's implementation transferred into `xxhash.h`. No more need to have `xxhash.c` in the `/include` directory for `XXH_INLINE_ALL` to work +- install: created pkg-config file, by @bket +- install: VCpkg installation instructions, by @LilyWangL +- doc: Highly improved code documentation, by @easyaspi314 +- misc: New test tool in `/tests/collisions`: brute force collision tester for 64-bit hashes + +v0.7.2 +- Fixed collision ratio of `XXH128` for some specific input lengths, reported by @svpv +- Improved `VSX` and `NEON` variants, by @easyaspi314 +- Improved performance of scalar code path (`XXH_VECTOR=0`), by @easyaspi314 +- `xxhsum`: can generate 128-bit hashes with the `-H2` option (note: for experimental purposes only! `XXH128` is not yet frozen) +- `xxhsum`: option `-q` removes status notifications + +v0.7.1 +- Secret first: the algorithm computation can be altered by providing a "secret", which is any blob of bytes, of size >= `XXH3_SECRET_SIZE_MIN`. +- `seed` is still available, and acts as a secret generator +- updated `ARM NEON` variant by @easyaspi314 +- Streaming implementation is available +- Improve compatibility and performance with Visual Studio, with help from @aras-p +- Better integration when using `XXH_INLINE_ALL`: do not pollute host namespace, use its own macros, such as `XXH_ASSERT()`, `XXH_ALIGN`, etc. +- 128-bit variant provides helper functions for comparison of hashes. +- Better `clang` generation of `rotl` instruction, thanks to @easyaspi314 +- `XXH_REROLL` build macro to reduce binary size, by @easyaspi314 +- Improved `cmake` script, by @Mezozoysky +- Full benchmark program provided in `/tests/bench` diff --git a/third_party/xxhash/Doxyfile b/third_party/xxhash/Doxyfile new file mode 100644 index 00000000000..634e1e1a38d --- /dev/null +++ b/third_party/xxhash/Doxyfile @@ -0,0 +1,58 @@ +# Doxygen config for xxHash +DOXYFILE_ENCODING = UTF-8 + +PROJECT_NAME = "xxHash" +PROJECT_NUMBER = "0.8.0" +PROJECT_BRIEF = "Extremely fast non-cryptographic hash function" +OUTPUT_DIRECTORY = doxygen +OUTPUT_LANGUAGE = English + +# We already separate the internal docs. +INTERNAL_DOCS = YES +# Consistency +SORT_MEMBER_DOCS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES + +# Warnings +QUIET = YES +# Until we document everything +WARN_IF_UNDOCUMENTED = NO + +# TODO: Add the other files. It is just xxhash.h for now. +FILE_PATTERNS = xxhash.h xxh_x86dispatch.c +# Note: xxHash's source files are technically ASCII only. +INPUT_ENCODING = UTF-8 +TAB_SIZE = 4 +MARKDOWN_SUPPORT = YES + +# xxHash is a C library +OPTIMIZE_OUTPUT_FOR_C = YES +# So we can document the internals +EXTRACT_STATIC = YES +# Document the macros +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +# Predefine some macros to clean up the output. +PREDEFINED = "XXH_DOXYGEN=" \ + "XXH_PUBLIC_API=" \ + "XXH_FORCE_INLINE=static inline" \ + "XXH_NO_INLINE=static" \ + "XXH_RESTRICT=restrict" \ + "XSUM_API=" \ + "XXH_STATIC_LINKING_ONLY" \ + "XXH_IMPLEMENTATION" \ + "XXH_ALIGN(N)=alignas(N)" \ + "XXH_ALIGN_MEMBER(align,type)=alignas(align) type" + +# We want HTML docs +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +# Tweak the colors a bit +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_GAMMA = 100 +HTML_COLORSTYLE_SAT = 100 + +# We don't want LaTeX. +GENERATE_LATEX = NO diff --git a/third_party/xxhash/LICENSE b/third_party/xxhash/LICENSE new file mode 100644 index 00000000000..fa20595dc62 --- /dev/null +++ b/third_party/xxhash/LICENSE @@ -0,0 +1,48 @@ +xxHash Library +Copyright (c) 2012-2020 Yann Collet +All rights reserved. + +BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +---------------------------------------------------- + +xxhsum command line interface +Copyright (c) 2013-2020 Yann Collet +All rights reserved. + +GPL v2 License + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. diff --git a/third_party/xxhash/Makefile b/third_party/xxhash/Makefile new file mode 100644 index 00000000000..23cf4a8c7fc --- /dev/null +++ b/third_party/xxhash/Makefile @@ -0,0 +1,506 @@ +# ################################################################ +# xxHash Makefile +# Copyright (C) 2012-2020 Yann Collet +# +# GPL v2 License +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# You can contact the author at: +# - xxHash homepage: https://www.xxhash.com +# - xxHash source repository: https://github.com/Cyan4973/xxHash +# ################################################################ +# xxhsum: provides 32/64 bits hash of one or multiple files, or stdin +# ################################################################ +Q = $(if $(filter 1,$(V) $(VERBOSE)),,@) + +# Version numbers +SED ?= sed +SED_ERE_OPT ?= -E +LIBVER_MAJOR_SCRIPT:=`$(SED) -n '/define XXH_VERSION_MAJOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h` +LIBVER_MINOR_SCRIPT:=`$(SED) -n '/define XXH_VERSION_MINOR/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h` +LIBVER_PATCH_SCRIPT:=`$(SED) -n '/define XXH_VERSION_RELEASE/s/.*[[:blank:]]\([0-9][0-9]*\).*/\1/p' < xxhash.h` +LIBVER_MAJOR := $(shell echo $(LIBVER_MAJOR_SCRIPT)) +LIBVER_MINOR := $(shell echo $(LIBVER_MINOR_SCRIPT)) +LIBVER_PATCH := $(shell echo $(LIBVER_PATCH_SCRIPT)) +LIBVER := $(LIBVER_MAJOR).$(LIBVER_MINOR).$(LIBVER_PATCH) + +CFLAGS ?= -O3 +DEBUGFLAGS+=-Wall -Wextra -Wconversion -Wcast-qual -Wcast-align -Wshadow \ + -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement \ + -Wstrict-prototypes -Wundef -Wpointer-arith -Wformat-security \ + -Wvla -Wformat=2 -Winit-self -Wfloat-equal -Wwrite-strings \ + -Wredundant-decls -Wstrict-overflow=2 +CFLAGS += $(DEBUGFLAGS) $(MOREFLAGS) +FLAGS = $(CFLAGS) $(CPPFLAGS) +XXHSUM_VERSION = $(LIBVER) +UNAME := $(shell uname) + +# Define *.exe as extension for Windows systems +ifneq (,$(filter Windows%,$(OS))) +EXT =.exe +else +EXT = +endif + +# OS X linker doesn't support -soname, and use different extension +# see: https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html +ifeq ($(UNAME), Darwin) + SHARED_EXT = dylib + SHARED_EXT_MAJOR = $(LIBVER_MAJOR).$(SHARED_EXT) + SHARED_EXT_VER = $(LIBVER).$(SHARED_EXT) + SONAME_FLAGS = -install_name $(LIBDIR)/libxxhash.$(SHARED_EXT_MAJOR) -compatibility_version $(LIBVER_MAJOR) -current_version $(LIBVER) +else + SONAME_FLAGS = -Wl,-soname=libxxhash.$(SHARED_EXT).$(LIBVER_MAJOR) + SHARED_EXT = so + SHARED_EXT_MAJOR = $(SHARED_EXT).$(LIBVER_MAJOR) + SHARED_EXT_VER = $(SHARED_EXT).$(LIBVER) +endif + +LIBXXH = libxxhash.$(SHARED_EXT_VER) + +XXHSUM_SRC_DIR = cli +XXHSUM_SPLIT_SRCS = $(XXHSUM_SRC_DIR)/xsum_os_specific.c \ + $(XXHSUM_SRC_DIR)/xsum_output.c \ + $(XXHSUM_SRC_DIR)/xsum_sanity_check.c +XXHSUM_SPLIT_OBJS = $(XXHSUM_SPLIT_SRCS:.c=.o) +XXHSUM_HEADERS = $(XXHSUM_SRC_DIR)/xsum_config.h \ + $(XXHSUM_SRC_DIR)/xsum_arch.h \ + $(XXHSUM_SRC_DIR)/xsum_os_specific.h \ + $(XXHSUM_SRC_DIR)/xsum_output.h \ + $(XXHSUM_SRC_DIR)/xsum_sanity_check.h + +## generate CLI and libraries in release mode (default for `make`) +.PHONY: default +default: DEBUGFLAGS= +default: lib xxhsum_and_links + +.PHONY: all +all: lib xxhsum xxhsum_inlinedXXH + +## xxhsum is the command line interface (CLI) +ifeq ($(DISPATCH),1) +xxhsum: CPPFLAGS += -DXXHSUM_DISPATCH=1 +xxhsum: xxh_x86dispatch.o +endif +xxhsum: xxhash.o xxhsum.o $(XXHSUM_SPLIT_OBJS) + $(CC) $(FLAGS) $^ $(LDFLAGS) -o $@$(EXT) + +xxhsum32: CFLAGS += -m32 ## generate CLI in 32-bits mode +xxhsum32: xxhash.c xxhsum.c $(XXHSUM_SPLIT_SRCS) ## do not generate object (avoid mixing different ABI) + $(CC) $(FLAGS) $^ $(LDFLAGS) -o $@$(EXT) + +## dispatch only works for x86/x64 systems +dispatch: CPPFLAGS += -DXXHSUM_DISPATCH=1 +dispatch: xxhash.o xxh_x86dispatch.o xxhsum.c $(XXHSUM_SPLIT_SRCS) + $(CC) $(FLAGS) $^ $(LDFLAGS) -o $@$(EXT) + +xxhash.o: xxhash.c xxhash.h +xxhsum.o: xxhsum.c $(XXHSUM_HEADERS) \ + xxhash.h xxh_x86dispatch.h +xxh_x86dispatch.o: xxh_x86dispatch.c xxh_x86dispatch.h xxhash.h + +.PHONY: xxhsum_and_links +xxhsum_and_links: xxhsum xxh32sum xxh64sum xxh128sum + +xxh32sum xxh64sum xxh128sum: xxhsum + ln -sf $<$(EXT) $@$(EXT) + +xxhsum_inlinedXXH: CPPFLAGS += -DXXH_INLINE_ALL +xxhsum_inlinedXXH: xxhsum.c $(XXHSUM_SPLIT_SRCS) + $(CC) $(FLAGS) $< -o $@$(EXT) + + +# library + +libxxhash.a: ARFLAGS = rcs +libxxhash.a: xxhash.o + $(AR) $(ARFLAGS) $@ $^ + +$(LIBXXH): LDFLAGS += -shared +ifeq (,$(filter Windows%,$(OS))) +$(LIBXXH): CFLAGS += -fPIC +endif +ifeq ($(DISPATCH),1) +$(LIBXXH): xxh_x86dispatch.c +endif +$(LIBXXH): xxhash.c + $(CC) $(FLAGS) $^ $(LDFLAGS) $(SONAME_FLAGS) -o $@ + ln -sf $@ libxxhash.$(SHARED_EXT_MAJOR) + ln -sf $@ libxxhash.$(SHARED_EXT) + +.PHONY: libxxhash +libxxhash: ## generate dynamic xxhash library +libxxhash: $(LIBXXH) + +.PHONY: lib +lib: ## generate static and dynamic xxhash libraries +lib: libxxhash.a libxxhash + +# helper targets + +AWK = awk +GREP = grep +SORT = sort + +.PHONY: list +list: ## list all Makefile targets + $(Q)$(MAKE) -pRrq -f $(lastword $(MAKEFILE_LIST)) : 2>/dev/null | $(AWK) -v RS= -F: '/^# File/,/^# Finished Make data base/ {if ($$1 !~ "^[#.]") {print $$1}}' | $(SORT) | egrep -v -e '^[^[:alnum:]]' -e '^$@$$' | xargs + +.PHONY: help +help: ## list documented targets + $(Q)$(GREP) -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ + $(SORT) | \ + $(AWK) 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: clean +clean: ## remove all build artifacts + $(Q)$(RM) -r *.dSYM # Mac OS-X specific + $(Q)$(RM) core *.o *.obj *.$(SHARED_EXT) *.$(SHARED_EXT).* *.a libxxhash.pc + $(Q)$(RM) xxhsum$(EXT) xxhsum32$(EXT) xxhsum_inlinedXXH$(EXT) dispatch$(EXT) + $(Q)$(RM) xxh32sum$(EXT) xxh64sum$(EXT) xxh128sum$(EXT) + $(Q)$(RM) $(XXHSUM_SRC_DIR)/*.o $(XXHSUM_SRC_DIR)/*.obj + @echo cleaning completed + + +# ================================================= +# tests +# ================================================= + +# make check can be run with cross-compiled binaries on emulated environments (qemu user mode) +# by setting $(RUN_ENV) to the target emulation environment +.PHONY: check +check: xxhsum ## basic tests for xxhsum CLI, set RUN_ENV for emulated environments + # stdin + $(RUN_ENV) ./xxhsum$(EXT) < xxhash.c + # multiple files + $(RUN_ENV) ./xxhsum$(EXT) xxhash.* xxhsum.* + # internal bench + $(RUN_ENV) ./xxhsum$(EXT) -bi0 + # long bench command + $(RUN_ENV) ./xxhsum$(EXT) --benchmark-all -i0 + # bench multiple variants + $(RUN_ENV) ./xxhsum$(EXT) -b1,2,3 -i0 + # file bench + $(RUN_ENV) ./xxhsum$(EXT) -bi0 xxhash.c + # 32-bit + $(RUN_ENV) ./xxhsum$(EXT) -H0 xxhash.c + # 128-bit + $(RUN_ENV) ./xxhsum$(EXT) -H2 xxhash.c + # request incorrect variant + $(RUN_ENV) ./xxhsum$(EXT) -H9 xxhash.c ; test $$? -eq 1 + @printf "\n ....... checks completed successfully ....... \n" + +.PHONY: test-unicode +test-unicode: + $(MAKE) -C tests test_unicode + +.PHONY: test-mem +VALGRIND = valgrind --leak-check=yes --error-exitcode=1 +test-mem: RUN_ENV = $(VALGRIND) +test-mem: xxhsum check + +.PHONY: test32 +test32: clean xxhsum32 + @echo ---- test 32-bit ---- + ./xxhsum32 -bi1 xxhash.c + +.PHONY: test-xxhsum-c +test-xxhsum-c: xxhsum + # xxhsum to/from pipe + ./xxhsum xxh* | ./xxhsum -c - + ./xxhsum -H0 xxh* | ./xxhsum -c - + # xxhsum -q does not display "Loading" message into stderr (#251) + ! ./xxhsum -q xxh* 2>&1 | grep Loading + # xxhsum does not display "Loading" message into stderr either + ! ./xxhsum xxh* 2>&1 | grep Loading + # Check that xxhsum do display filename that it failed to open. + LC_ALL=C ./xxhsum nonexistent 2>&1 | grep "Error: Could not open 'nonexistent'" + # xxhsum to/from file, shell redirection + ./xxhsum xxh* > .test.xxh64 + ./xxhsum --tag xxh* > .test.xxh64_tag + ./xxhsum --little-endian xxh* > .test.le_xxh64 + ./xxhsum --tag --little-endian xxh* > .test.le_xxh64_tag + ./xxhsum -H0 xxh* > .test.xxh32 + ./xxhsum -H0 --tag xxh* > .test.xxh32_tag + ./xxhsum -H0 --little-endian xxh* > .test.le_xxh32 + ./xxhsum -H0 --tag --little-endian xxh* > .test.le_xxh32_tag + ./xxhsum -H2 xxh* > .test.xxh128 + ./xxhsum -H2 --tag xxh* > .test.xxh128_tag + ./xxhsum -H2 --little-endian xxh* > .test.le_xxh128 + ./xxhsum -H2 --tag --little-endian xxh* > .test.le_xxh128_tag + ./xxhsum -c .test.xxh* + ./xxhsum -c --little-endian .test.le_xxh* + ./xxhsum -c .test.*_tag + # read list of files from stdin + ./xxhsum -c < .test.xxh64 + ./xxhsum -c < .test.xxh32 + cat .test.xxh* | ./xxhsum -c - + # check variant with '*' marker as second separator + $(SED) 's/ / \*/' .test.xxh32 | ./xxhsum -c + # bsd-style output + ./xxhsum --tag xxhsum* | $(GREP) XXH64 + ./xxhsum --tag -H0 xxhsum* | $(GREP) XXH32 + ./xxhsum --tag -H1 xxhsum* | $(GREP) XXH64 + ./xxhsum --tag -H2 xxhsum* | $(GREP) XXH128 + ./xxhsum --tag -H32 xxhsum* | $(GREP) XXH32 + ./xxhsum --tag -H64 xxhsum* | $(GREP) XXH64 + ./xxhsum --tag -H128 xxhsum* | $(GREP) XXH128 + ./xxhsum --tag -H0 --little-endian xxhsum* | $(GREP) XXH32_LE + ./xxhsum --tag -H1 --little-endian xxhsum* | $(GREP) XXH64_LE + ./xxhsum --tag -H2 --little-endian xxhsum* | $(GREP) XXH128_LE + ./xxhsum --tag -H32 --little-endian xxhsum* | $(GREP) XXH32_LE + ./xxhsum --tag -H64 --little-endian xxhsum* | $(GREP) XXH64_LE + ./xxhsum --tag -H128 --little-endian xxhsum* | $(GREP) XXH128_LE + # check bsd-style + ./xxhsum --tag xxhsum* | ./xxhsum -c + ./xxhsum --tag -H32 --little-endian xxhsum* | ./xxhsum -c + # xxhsum -c warns improperly format lines. + echo '12345678 ' >>.test.xxh32 + ./xxhsum -c .test.xxh32 | $(GREP) improperly + echo '123456789 file' >>.test.xxh64 + ./xxhsum -c .test.xxh64 | $(GREP) improperly + # Expects "FAILED" + echo "0000000000000000 LICENSE" | ./xxhsum -c -; test $$? -eq 1 + echo "00000000 LICENSE" | ./xxhsum -c -; test $$? -eq 1 + # Expects "FAILED open or read" + echo "0000000000000000 test-expects-file-not-found" | ./xxhsum -c -; test $$? -eq 1 + echo "00000000 test-expects-file-not-found" | ./xxhsum -c -; test $$? -eq 1 + @$(RM) .test.* + +.PHONY: armtest +armtest: clean + @echo ---- test ARM compilation ---- + CC=arm-linux-gnueabi-gcc MOREFLAGS="-Werror -static" $(MAKE) xxhsum + +.PHONY: clangtest +clangtest: clean + @echo ---- test clang compilation ---- + CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion" $(MAKE) all + +.PHONY: cxxtest +cxxtest: clean + @echo ---- test C++ compilation ---- + CC="$(CXX) -Wno-deprecated" $(MAKE) all CFLAGS="-O3 -Wall -Wextra -Wundef -Wshadow -Wcast-align -Werror -fPIC" + +.PHONY: c90test +ifeq ($(NO_C90_TEST),true) +c90test: + @echo no c90 compatibility test +else +c90test: CPPFLAGS += -DXXH_NO_LONG_LONG +c90test: CFLAGS += -std=c90 -Werror -pedantic +c90test: xxhash.c + @echo ---- test strict C90 compilation [xxh32 only] ---- + $(RM) xxhash.o + $(CC) $(FLAGS) $^ $(LDFLAGS) -c + $(RM) xxhash.o +endif + +.PHONY: usan +usan: CC=clang +usan: CXX=clang++ +usan: ## check CLI runtime for undefined behavior, using clang's sanitizer + @echo ---- check undefined behavior - sanitize ---- + $(MAKE) clean + $(MAKE) test CC=$(CC) CXX=$(CXX) MOREFLAGS="-g -fsanitize=undefined -fno-sanitize-recover=all" + +.PHONY: staticAnalyze +SCANBUILD ?= scan-build +staticAnalyze: clean ## check C source files using $(SCANBUILD) static analyzer + @echo ---- static analyzer - $(SCANBUILD) ---- + CFLAGS="-g -Werror" $(SCANBUILD) --status-bugs -v $(MAKE) all + +CPPCHECK ?= cppcheck +.PHONY: cppcheck +cppcheck: ## check C source files using $(CPPCHECK) static analyzer + @echo ---- static analyzer - $(CPPCHECK) ---- + $(CPPCHECK) . --force --enable=warning,portability,performance,style --error-exitcode=1 > /dev/null + +.PHONY: namespaceTest +namespaceTest: ## ensure XXH_NAMESPACE redefines all public symbols + $(CC) -c xxhash.c + $(CC) -DXXH_NAMESPACE=TEST_ -c xxhash.c -o xxhash2.o + $(CC) xxhash.o xxhash2.o xxhsum.c $(XXHSUM_SPLIT_SRCS) -o xxhsum2 # will fail if one namespace missing (symbol collision) + $(RM) *.o xxhsum2 # clean + +MD2ROFF ?= ronn +MD2ROFF_FLAGS ?= --roff --warnings --manual="User Commands" --organization="xxhsum $(XXHSUM_VERSION)" +xxhsum.1: xxhsum.1.md xxhash.h + cat $< | $(MD2ROFF) $(MD2ROFF_FLAGS) | $(SED) -n '/^\.\\\".*/!p' > $@ + +.PHONY: man +man: xxhsum.1 ## generate man page from markdown source + +.PHONY: clean-man +clean-man: + $(RM) xxhsum.1 + +.PHONY: preview-man +preview-man: man + man ./xxhsum.1 + +.PHONY: test +test: DEBUGFLAGS += -DXXH_DEBUGLEVEL=1 +test: all namespaceTest check test-xxhsum-c c90test test-tools + +.PHONY: test-inline +test-inline: + $(MAKE) -C tests test_multiInclude + +.PHONY: test-all +test-all: CFLAGS += -Werror +test-all: test test32 clangtest cxxtest usan test-inline listL120 trailingWhitespace test-unicode + +.PHONY: test-tools +test-tools: + CFLAGS=-Werror $(MAKE) -C tests/bench + CFLAGS=-Werror $(MAKE) -C tests/collisions + +.PHONY: listL120 +listL120: # extract lines >= 120 characters in *.{c,h}, by Takayuki Matsuoka (note: $$, for Makefile compatibility) + find . -type f -name '*.c' -o -name '*.h' | while read -r filename; do awk 'length > 120 {print FILENAME "(" FNR "): " $$0}' $$filename; done + +.PHONY: trailingWhitespace +trailingWhitespace: + ! $(GREP) -E "`printf '[ \\t]$$'`" xxhsum.1 *.c *.h LICENSE Makefile cmake_unofficial/CMakeLists.txt + + +# ========================================================= +# make install is validated only for the following targets +# ========================================================= +ifneq (,$(filter Linux Darwin GNU/kFreeBSD GNU Haiku OpenBSD FreeBSD NetBSD DragonFly SunOS CYGWIN% , $(UNAME))) + +DESTDIR ?= +# directory variables: GNU conventions prefer lowercase +# see https://www.gnu.org/prep/standards/html_node/Makefile-Conventions.html +# support both lower and uppercase (BSD), use uppercase in script +prefix ?= /usr/local +PREFIX ?= $(prefix) +exec_prefix ?= $(PREFIX) +EXEC_PREFIX ?= $(exec_prefix) +libdir ?= $(EXEC_PREFIX)/lib +LIBDIR ?= $(libdir) +includedir ?= $(PREFIX)/include +INCLUDEDIR ?= $(includedir) +bindir ?= $(EXEC_PREFIX)/bin +BINDIR ?= $(bindir) +datarootdir ?= $(PREFIX)/share +mandir ?= $(datarootdir)/man +man1dir ?= $(mandir)/man1 + +ifneq (,$(filter $(UNAME),FreeBSD NetBSD DragonFly)) +PKGCONFIGDIR ?= $(PREFIX)/libdata/pkgconfig +else +PKGCONFIGDIR ?= $(LIBDIR)/pkgconfig +endif + +ifneq (,$(filter $(UNAME),OpenBSD FreeBSD NetBSD DragonFly SunOS)) +MANDIR ?= $(PREFIX)/man/man1 +else +MANDIR ?= $(man1dir) +endif + +ifneq (,$(filter $(UNAME),SunOS)) +INSTALL ?= ginstall +else +INSTALL ?= install +endif + +INSTALL_PROGRAM ?= $(INSTALL) +INSTALL_DATA ?= $(INSTALL) -m 644 + + +PCLIBDIR ?= $(shell echo "$(LIBDIR)" | $(SED) -n $(SED_ERE_OPT) -e "s@^$(EXEC_PREFIX)(/|$$)@@p") +PCINCDIR ?= $(shell echo "$(INCLUDEDIR)" | $(SED) -n $(SED_ERE_OPT) -e "s@^$(PREFIX)(/|$$)@@p") +PCEXECDIR?= $(if $(filter $(PREFIX),$(EXEC_PREFIX)),$$\{prefix\},$(EXEC_PREFIX)) + +ifeq (,$(PCLIBDIR)) +# Additional prefix check is required, since the empty string is technically a +# valid PCLIBDIR +ifeq (,$(shell echo "$(LIBDIR)" | $(SED) -n $(SED_ERE_OPT) -e "\\@^$(EXEC_PREFIX)(/|$$)@ p")) +$(error configured libdir ($(LIBDIR)) is outside of exec_prefix ($(EXEC_PREFIX)), can't generate pkg-config file) +endif +endif + +ifeq (,$(PCINCDIR)) +# Additional prefix check is required, since the empty string is technically a +# valid PCINCDIR +ifeq (,$(shell echo "$(INCLUDEDIR)" | $(SED) -n $(SED_ERE_OPT) -e "\\@^$(PREFIX)(/|$$)@ p")) +$(error configured includedir ($(INCLUDEDIR)) is outside of prefix ($(PREFIX)), can't generate pkg-config file) +endif +endif + +libxxhash.pc: libxxhash.pc.in + @echo creating pkgconfig + $(Q)$(SED) $(SED_ERE_OPT) -e 's|@PREFIX@|$(PREFIX)|' \ + -e 's|@EXECPREFIX@|$(PCEXECDIR)|' \ + -e 's|@LIBDIR@|$(PCLIBDIR)|' \ + -e 's|@INCLUDEDIR@|$(PCINCDIR)|' \ + -e 's|@VERSION@|$(LIBVER)|' \ + $< > $@ + + +.PHONY: install +install: lib libxxhash.pc xxhsum ## install libraries, CLI, links and man page + @echo Installing libxxhash + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(LIBDIR) + $(Q)$(INSTALL_DATA) libxxhash.a $(DESTDIR)$(LIBDIR) + $(Q)$(INSTALL_PROGRAM) $(LIBXXH) $(DESTDIR)$(LIBDIR) + $(Q)ln -sf $(LIBXXH) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT_MAJOR) + $(Q)ln -sf $(LIBXXH) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT) + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(INCLUDEDIR) # includes + $(Q)$(INSTALL_DATA) xxhash.h $(DESTDIR)$(INCLUDEDIR) + $(Q)$(INSTALL_DATA) xxh3.h $(DESTDIR)$(INCLUDEDIR) # for compatibility, will be removed in v0.9.0 +ifeq ($(DISPATCH),1) + $(Q)$(INSTALL_DATA) xxh_x86dispatch.h $(DESTDIR)$(INCLUDEDIR) +endif + @echo Installing pkgconfig + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(PKGCONFIGDIR)/ + $(Q)$(INSTALL_DATA) libxxhash.pc $(DESTDIR)$(PKGCONFIGDIR)/ + @echo Installing xxhsum + $(Q)$(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR)/ $(DESTDIR)$(MANDIR)/ + $(Q)$(INSTALL_PROGRAM) xxhsum $(DESTDIR)$(BINDIR)/xxhsum + $(Q)ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh32sum + $(Q)ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh64sum + $(Q)ln -sf xxhsum $(DESTDIR)$(BINDIR)/xxh128sum + @echo Installing man pages + $(Q)$(INSTALL_DATA) xxhsum.1 $(DESTDIR)$(MANDIR)/xxhsum.1 + $(Q)ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh32sum.1 + $(Q)ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh64sum.1 + $(Q)ln -sf xxhsum.1 $(DESTDIR)$(MANDIR)/xxh128sum.1 + @echo xxhash installation completed + +.PHONY: uninstall +uninstall: ## uninstall libraries, CLI, links and man page + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.a + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT) + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/libxxhash.$(SHARED_EXT_MAJOR) + $(Q)$(RM) $(DESTDIR)$(LIBDIR)/$(LIBXXH) + $(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/xxhash.h + $(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/xxh3.h + $(Q)$(RM) $(DESTDIR)$(INCLUDEDIR)/xxh_x86dispatch.h + $(Q)$(RM) $(DESTDIR)$(PKGCONFIGDIR)/libxxhash.pc + $(Q)$(RM) $(DESTDIR)$(BINDIR)/xxh32sum + $(Q)$(RM) $(DESTDIR)$(BINDIR)/xxh64sum + $(Q)$(RM) $(DESTDIR)$(BINDIR)/xxh128sum + $(Q)$(RM) $(DESTDIR)$(BINDIR)/xxhsum + $(Q)$(RM) $(DESTDIR)$(MANDIR)/xxh32sum.1 + $(Q)$(RM) $(DESTDIR)$(MANDIR)/xxh64sum.1 + $(Q)$(RM) $(DESTDIR)$(MANDIR)/xxh128sum.1 + $(Q)$(RM) $(DESTDIR)$(MANDIR)/xxhsum.1 + @echo xxhsum successfully uninstalled + +endif diff --git a/third_party/xxhash/README.md b/third_party/xxhash/README.md new file mode 100644 index 00000000000..7d9ae9dd46a --- /dev/null +++ b/third_party/xxhash/README.md @@ -0,0 +1,235 @@ + +xxHash - Extremely fast hash algorithm +====================================== + +xxHash is an Extremely fast Hash algorithm, running at RAM speed limits. +It successfully completes the [SMHasher](https://code.google.com/p/smhasher/wiki/SMHasher) test suite +which evaluates collision, dispersion and randomness qualities of hash functions. +Code is highly portable, and hashes are identical across all platforms (little / big endian). + +|Branch |Status | +|------------|---------| +|dev | [![Build Status](https://travis-ci.org/Cyan4973/xxHash.svg?branch=dev)](https://travis-ci.org/Cyan4973/xxHash?branch=dev) | + + +Benchmarks +------------------------- + +The reference system uses an Intel i7-9700K cpu, and runs Ubuntu x64 20.04. +The [open source benchmark program] is compiled with `clang` v10.0 using `-O3` flag. + +| Hash Name | Width | Bandwidth (GB/s) | Small Data Velocity | Quality | Comment | +| --------- | ----- | ---------------- | ----- | --- | --- | +| __XXH3__ (SSE2) | 64 | 31.5 GB/s | 133.1 | 10 +| __XXH128__ (SSE2) | 128 | 29.6 GB/s | 118.1 | 10 +| _RAM sequential read_ | N/A | 28.0 GB/s | N/A | N/A | _for reference_ +| City64 | 64 | 22.0 GB/s | 76.6 | 10 +| T1ha2 | 64 | 22.0 GB/s | 99.0 | 9 | Slightly worse [collisions] +| City128 | 128 | 21.7 GB/s | 57.7 | 10 +| __XXH64__ | 64 | 19.4 GB/s | 71.0 | 10 +| SpookyHash | 64 | 19.3 GB/s | 53.2 | 10 +| Mum | 64 | 18.0 GB/s | 67.0 | 9 | Slightly worse [collisions] +| __XXH32__ | 32 | 9.7 GB/s | 71.9 | 10 +| City32 | 32 | 9.1 GB/s | 66.0 | 10 +| Murmur3 | 32 | 3.9 GB/s | 56.1 | 10 +| SipHash | 64 | 3.0 GB/s | 43.2 | 10 +| FNV64 | 64 | 1.2 GB/s | 62.7 | 5 | Poor avalanche properties +| Blake2 | 256 | 1.1 GB/s | 5.1 | 10 | Cryptographic +| SHA1 | 160 | 0.8 GB/s | 5.6 | 10 | Cryptographic but broken +| MD5 | 128 | 0.6 GB/s | 7.8 | 10 | Cryptographic but broken + +[open source benchmark program]: https://github.com/Cyan4973/xxHash/tree/release/tests/bench +[collisions]: https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison#collision-study + +note 1: Small data velocity is a _rough_ evaluation of algorithm's efficiency on small data. For more detailed analysis, please refer to next paragraph. + +note 2: some algorithms feature _faster than RAM_ speed. In which case, they can only reach their full speed when input data is already in CPU cache (L3 or better). Otherwise, they max out on RAM speed limit. + +### Small data + +Performance on large data is only one part of the picture. +Hashing is also very useful in constructions like hash tables and bloom filters. +In these use cases, it's frequent to hash a lot of small data (starting at a few bytes). +Algorithm's performance can be very different for such scenarios, since parts of the algorithm, +such as initialization or finalization, become fixed cost. +The impact of branch mis-prediction also becomes much more present. + +XXH3 has been designed for excellent performance on both long and small inputs, +which can be observed in the following graph: + +![XXH3, latency, random size](https://user-images.githubusercontent.com/750081/61976089-aedeab00-af9f-11e9-9239-e5375d6c080f.png) + +For a more detailed analysis, visit the wiki : +https://github.com/Cyan4973/xxHash/wiki/Performance-comparison#benchmarks-concentrating-on-small-data- + +Quality +------------------------- + +Speed is not the only property that matters. +Produced hash values must respect excellent dispersion and randomness properties, +so that any sub-section of it can be used to maximally spread out a table or index, +as well as reduce the amount of collisions to the minimal theoretical level, following the [birthday paradox]. + +`xxHash` has been tested with Austin Appleby's excellent SMHasher test suite, +and passes all tests, ensuring reasonable quality levels. +It also passes extended tests from [newer forks of SMHasher], featuring additional scenarios and conditions. + +Finally, xxHash provides its own [massive collision tester](https://github.com/Cyan4973/xxHash/tree/dev/tests/collisions), +able to generate and compare billions of hash to test the limits of 64-bit hash algorithms. +On this front too, xxHash features good results, in line with the [birthday paradox]. +A more detailed analysis is documented [in the wiki](https://github.com/Cyan4973/xxHash/wiki/Collision-ratio-comparison). + +[birthday paradox]: https://en.wikipedia.org/wiki/Birthday_problem +[newer forks of SMHasher]: https://github.com/rurban/smhasher + + +### Build modifiers + +The following macros can be set at compilation time to modify libxxhash's behavior. They are generally disabled by default. + +- `XXH_INLINE_ALL`: Make all functions `inline`, with implementations being directly included within `xxhash.h`. + Inlining functions is beneficial for speed on small keys. + It's _extremely effective_ when key length is expressed as _a compile time constant_, + with performance improvements observed in the +200% range . + See [this article](https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html) for details. +- `XXH_PRIVATE_API`: same outcome as `XXH_INLINE_ALL`. Still available for legacy support. + The name underlines that `XXH_*` symbols will not be exported. +- `XXH_NAMESPACE`: Prefixes all symbols with the value of `XXH_NAMESPACE`. + This macro can only use compilable character set. + Useful to evade symbol naming collisions, + in case of multiple inclusions of xxHash's source code. + Client applications still use the regular function names, + as symbols are automatically translated through `xxhash.h`. +- `XXH_FORCE_MEMORY_ACCESS`: The default method `0` uses a portable `memcpy()` notation. + Method `1` uses a gcc-specific `packed` attribute, which can provide better performance for some targets. + Method `2` forces unaligned reads, which is not standards compliant, but might sometimes be the only way to extract better read performance. + Method `3` uses a byteshift operation, which is best for old compilers which don't inline `memcpy()` or big-endian systems without a byteswap instruction +- `XXH_FORCE_ALIGN_CHECK`: Use a faster direct read path when input is aligned. + This option can result in dramatic performance improvement when input to hash is aligned on 32 or 64-bit boundaries, + when running on architectures unable to load memory from unaligned addresses, or suffering a performance penalty from it. + It is (slightly) detrimental on platform with good unaligned memory access performance (same instruction for both aligned and unaligned accesses). + This option is automatically disabled on `x86`, `x64` and `aarch64`, and enabled on all other platforms. +- `XXH_VECTOR` : manually select a vector instruction set (default: auto-selected at compilation time). Available instruction sets are `XXH_SCALAR`, `XXH_SSE2`, `XXH_AVX2`, `XXH_AVX512`, `XXH_NEON` and `XXH_VSX`. Compiler may require additional flags to ensure proper support (for example, `gcc` on linux will require `-mavx2` for AVX2, and `-mavx512f` for AVX512). +- `XXH_NO_PREFETCH` : disable prefetching. XXH3 only. +- `XXH_PREFETCH_DIST` : select prefecting distance. XXH3 only. +- `XXH_NO_INLINE_HINTS`: By default, xxHash uses `__attribute__((always_inline))` and `__forceinline` to improve performance at the cost of code size. + Defining this macro to 1 will mark all internal functions as `static`, allowing the compiler to decide whether to inline a function or not. + This is very useful when optimizing for smallest binary size, + and is automatically defined when compiling with `-O0`, `-Os`, `-Oz`, or `-fno-inline` on GCC and Clang. + This may also increase performance depending on compiler and architecture. +- `XXH_REROLL`: Reduces the size of the generated code by not unrolling some loops. + Impact on performance may vary, depending on platform and algorithm. +- `XXH_ACCEPT_NULL_INPUT_POINTER`: if set to `1`, when input is a `NULL` pointer, + xxHash'd result is the same as a zero-length input + (instead of a dereference segfault). + Adds one branch at the beginning of each hash. +- `XXH_STATIC_LINKING_ONLY`: gives access to the state declaration for static allocation. + Incompatible with dynamic linking, due to risks of ABI changes. +- `XXH_NO_LONG_LONG`: removes compilation of algorithms relying on 64-bit types (XXH3 and XXH64). Only XXH32 will be compiled. + Useful for targets (architectures and compilers) without 64-bit support. +- `XXH_IMPORT`: MSVC specific: should only be defined for dynamic linking, as it prevents linkage errors. +- `XXH_CPU_LITTLE_ENDIAN`: By default, endianess is determined by a runtime test resolved at compile time. + If, for some reason, the compiler cannot simplify the runtime test, it can cost performance. + It's possible to skip auto-detection and simply state that the architecture is little-endian by setting this macro to 1. + Setting it to 0 states big-endian. + +For the Command Line Interface `xxhsum`, the following environment variables can also be set : +- `DISPATCH=1` : use `xxh_x86dispatch.c`, to automatically select between `scalar`, `sse2`, `avx2` or `avx512` instruction set at runtime, depending on local host. This option is only valid for `x86`/`x64` systems. + + +### Building xxHash - Using vcpkg + +You can download and install xxHash using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + ./vcpkg install xxhash + +The xxHash port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + + +### Example + +The simplest example calls xxhash 64-bit variant as a one-shot function +generating a hash value from a single buffer, and invoked from a C/C++ program: + +```C +#include "xxhash.h" + + (...) + XXH64_hash_t hash = XXH64(buffer, size, seed); +} +``` + +Streaming variant is more involved, but makes it possible to provide data incrementally: + +```C +#include "stdlib.h" /* abort() */ +#include "xxhash.h" + + +XXH64_hash_t calcul_hash_streaming(FileHandler fh) +{ + /* create a hash state */ + XXH64_state_t* const state = XXH64_createState(); + if (state==NULL) abort(); + + size_t const bufferSize = SOME_SIZE; + void* const buffer = malloc(bufferSize); + if (buffer==NULL) abort(); + + /* Initialize state with selected seed */ + XXH64_hash_t const seed = 0; /* or any other value */ + if (XXH64_reset(state, seed) == XXH_ERROR) abort(); + + /* Feed the state with input data, any size, any number of times */ + (...) + while ( /* some data left */ ) { + size_t const length = get_more_data(buffer, bufferSize, fh); + if (XXH64_update(state, buffer, length) == XXH_ERROR) abort(); + (...) + } + (...) + + /* Produce the final hash value */ + XXH64_hash_t const hash = XXH64_digest(state); + + /* State could be re-used; but in this example, it is simply freed */ + free(buffer); + XXH64_freeState(state); + + return hash; +} +``` + + +### License + +The library files `xxhash.c` and `xxhash.h` are BSD licensed. +The utility `xxhsum` is GPL licensed. + + +### Other programming languages + +Beyond the C reference version, +xxHash is also available from many different programming languages, +thanks to great contributors. +They are [listed here](http://www.xxhash.com/#other-languages). + + +### Packaging status + +Many distributions bundle a package manager +which allows easy xxhash installation as both a `libxxhash` library +and `xxhsum` command line interface. + +[![Packaging status](https://repology.org/badge/vertical-allrepos/xxhash.svg)](https://repology.org/project/xxhash/versions) + + +### Special Thanks + +- Takayuki Matsuoka, aka @t-mat, for creating `xxhsum -c` and great support during early xxh releases +- Mathias Westerdahl, aka @JCash, for introducing the first version of `XXH64` +- Devin Hussey, aka @easyaspi314, for incredible low-level optimizations on `XXH3` and `XXH128` diff --git a/third_party/xxhash/appveyor.yml b/third_party/xxhash/appveyor.yml new file mode 100644 index 00000000000..850f48b14de --- /dev/null +++ b/third_party/xxhash/appveyor.yml @@ -0,0 +1,111 @@ +#---------------------------------# +# general configuration # +#---------------------------------# +version: 1.0.{build} +max_jobs: 2 + +#---------------------------------# +# environment configuration # +#---------------------------------# +clone_depth: 2 +environment: + matrix: + - COMPILER: "visual" + ARCH: "x64" + TEST_XXHSUM: "true" + - COMPILER: "visual" + ARCH: "x64" + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + TEST_XXHSUM: "true" + - COMPILER: "visual" + ARCH: "Win32" + TEST_XXHSUM: "true" + - COMPILER: "visual" + ARCH: "Win32" + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2013 + TEST_XXHSUM: "true" + - COMPILER: "visual" + ARCH: "ARM" + - COMPILER: "visual" + ARCH: "ARM64" + APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 + # note: ARM64 is not available with Visual Studio 14 2015, which is default for Appveyor + - COMPILER: "gcc" + PLATFORM: "mingw64" + - COMPILER: "gcc" + PLATFORM: "mingw32" + - COMPILER: "gcc" + PLATFORM: "clang" + +install: + - ECHO Installing %COMPILER% %PLATFORM% %ARCH% + - MKDIR bin + - if [%COMPILER%]==[gcc] SET PATH_ORIGINAL=%PATH% + - if [%COMPILER%]==[gcc] ( + SET "PATH_MINGW32=c:\MinGW\bin;c:\MinGW\usr\bin" && + SET "PATH_MINGW64=c:\msys64\mingw64\bin;c:\msys64\usr\bin" && + COPY C:\MinGW\bin\mingw32-make.exe C:\MinGW\bin\make.exe && + COPY C:\MinGW\bin\gcc.exe C:\MinGW\bin\cc.exe + ) + +#---------------------------------# +# build configuration # +#---------------------------------# +build_script: + - if [%PLATFORM%]==[mingw32] SET PATH=%PATH_MINGW32%;%PATH_ORIGINAL% + - if [%PLATFORM%]==[mingw64] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL% + - if [%PLATFORM%]==[clang] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL% + - ECHO *** + - ECHO Building %COMPILER% %PLATFORM% %ARCH% + - ECHO *** + + - if [%COMPILER%]==[gcc] ( + if [%PLATFORM%]==[clang] ( + clang -v + ) ELSE ( + gcc -v + ) + ) + - if [%COMPILER%]==[gcc] ( + echo ----- && + make -v && + echo ----- && + if not [%PLATFORM%]==[clang] ( + if [%PLATFORM%]==[mingw32] ( SET CPPFLAGS=-DPOOL_MT=0 ) && + make -B clean test MOREFLAGS=-Werror + ) ELSE ( + SET CXXFLAGS=--std=c++14 && + make -B clean test CC=clang CXX=clang++ MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wno-pass-failed" NO_C90_TEST=true + ) && + make -C tests/bench + ) + # note 1: strict c90 tests with clang fail, due to (erroneous) presence on `inline` keyword in some included system file + # note 2: multi-threading code doesn't work with mingw32, disabled through POOL_MT=0 + # note 3: clang requires C++14 to compile sort because its own code contains c++14-only code + + - if [%COMPILER%]==[visual] ( + cd cmake_unofficial && + cmake . -DCMAKE_BUILD_TYPE=Release -A %ARCH% -DXXHASH_C_FLAGS="/WX" && + cmake --build . --config Release + ) + +#---------------------------------# +# tests configuration # +#---------------------------------# +test_script: + # note: can only run x86 and x64 binaries on Appveyor + # note: if %COMPILER%==gcc, xxhsum was already tested within `make test` + - if [%TEST_XXHSUM%]==[true] ( + ECHO *** && + ECHO Testing %COMPILER% %PLATFORM% %ARCH% && + ECHO *** && + cd Release && + xxhsum.exe -bi1 && + ECHO ------- xxhsum tested ------- + ) + + +#---------------------------------# +# artifacts configuration # +#---------------------------------# +# none yet diff --git a/third_party/xxhash/cli/xsum_arch.h b/third_party/xxhash/cli/xsum_arch.h new file mode 100644 index 00000000000..cc39297972b --- /dev/null +++ b/third_party/xxhash/cli/xsum_arch.h @@ -0,0 +1,153 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * Checks for predefined macros by the compiler to try and get both the arch + * and the compiler version. + */ +#ifndef XSUM_ARCH_H +#define XSUM_ARCH_H + +#include "xsum_config.h" + +#define XSUM_LIB_VERSION XXH_VERSION_MAJOR.XXH_VERSION_MINOR.XXH_VERSION_RELEASE +#define XSUM_QUOTE(str) #str +#define XSUM_EXPAND_AND_QUOTE(str) XSUM_QUOTE(str) +#define XSUM_PROGRAM_VERSION XSUM_EXPAND_AND_QUOTE(XSUM_LIB_VERSION) + + +/* Show compiler versions in WELCOME_MESSAGE. XSUM_CC_VERSION_FMT will return the printf specifiers, + * and VERSION will contain the comma separated list of arguments to the XSUM_CC_VERSION_FMT string. */ +#if defined(__clang_version__) +/* Clang does its own thing. */ +# ifdef __apple_build_version__ +# define XSUM_CC_VERSION_FMT "Apple Clang %s" +# else +# define XSUM_CC_VERSION_FMT "Clang %s" +# endif +# define XSUM_CC_VERSION __clang_version__ +#elif defined(__VERSION__) +/* GCC and ICC */ +# define XSUM_CC_VERSION_FMT "%s" +# ifdef __INTEL_COMPILER /* icc adds its prefix */ +# define XSUM_CC_VERSION __VERSION__ +# else /* assume GCC */ +# define XSUM_CC_VERSION "GCC " __VERSION__ +# endif +#elif defined(_MSC_FULL_VER) && defined(_MSC_BUILD) +/* + * MSVC + * "For example, if the version number of the Visual C++ compiler is + * 15.00.20706.01, the _MSC_FULL_VER macro evaluates to 150020706." + * + * https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017 + */ +# define XSUM_CC_VERSION_FMT "MSVC %02i.%02i.%05i.%02i" +# define XSUM_CC_VERSION _MSC_FULL_VER / 10000000 % 100, _MSC_FULL_VER / 100000 % 100, _MSC_FULL_VER % 100000, _MSC_BUILD +#elif defined(_MSC_VER) /* old MSVC */ +# define XSUM_CC_VERSION_FMT "MSVC %02i.%02i" +# define XSUM_CC_VERSION _MSC_VER / 100, _MSC_VER % 100 +#elif defined(__TINYC__) +/* tcc stores its version in the __TINYC__ macro. */ +# define XSUM_CC_VERSION_FMT "tcc %i.%i.%i" +# define XSUM_CC_VERSION __TINYC__ / 10000 % 100, __TINYC__ / 100 % 100, __TINYC__ % 100 +#else +# define XSUM_CC_VERSION_FMT "%s" +# define XSUM_CC_VERSION "unknown compiler" +#endif + +/* makes the next part easier */ +#if defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) +# define XSUM_ARCH_X64 1 +# define XSUM_ARCH_X86 "x86_64" +#elif defined(__i386__) || defined(_M_IX86) || defined(_M_IX86_FP) +# define XSUM_ARCH_X86 "i386" +#endif + +/* Try to detect the architecture. */ +#if defined(XSUM_ARCH_X86) +# if defined(XXHSUM_DISPATCH) +# define XSUM_ARCH XSUM_ARCH_X86 " autoVec" +# elif defined(__AVX512F__) +# define XSUM_ARCH XSUM_ARCH_X86 " + AVX512" +# elif defined(__AVX2__) +# define XSUM_ARCH XSUM_ARCH_X86 " + AVX2" +# elif defined(__AVX__) +# define XSUM_ARCH XSUM_ARCH_X86 " + AVX" +# elif defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) \ + || defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP == 2) +# define XSUM_ARCH XSUM_ARCH_X86 " + SSE2" +# else +# define XSUM_ARCH XSUM_ARCH_X86 +# endif +#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) +# define XSUM_ARCH "aarch64 + NEON" +#elif defined(__arm__) || defined(__thumb__) || defined(__thumb2__) || defined(_M_ARM) +/* ARM has a lot of different features that can change xxHash significantly. */ +# if defined(__thumb2__) || (defined(__thumb__) && (__thumb__ == 2 || __ARM_ARCH >= 7)) +# define XSUM_ARCH_THUMB " Thumb-2" +# elif defined(__thumb__) +# define XSUM_ARCH_THUMB " Thumb-1" +# else +# define XSUM_ARCH_THUMB "" +# endif +/* ARMv7 has unaligned by default */ +# if defined(__ARM_FEATURE_UNALIGNED) || __ARM_ARCH >= 7 || defined(_M_ARMV7VE) +# define XSUM_ARCH_UNALIGNED " + unaligned" +# else +# define XSUM_ARCH_UNALIGNED "" +# endif +# if defined(__ARM_NEON) || defined(__ARM_NEON__) +# define XSUM_ARCH_NEON " + NEON" +# else +# define XSUM_ARCH_NEON "" +# endif +# define XSUM_ARCH "ARMv" XSUM_EXPAND_AND_QUOTE(__ARM_ARCH) XSUM_ARCH_THUMB XSUM_ARCH_NEON XSUM_ARCH_UNALIGNED +#elif defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) +# if defined(__GNUC__) && defined(__POWER9_VECTOR__) +# define XSUM_ARCH "ppc64 + POWER9 vector" +# elif defined(__GNUC__) && defined(__POWER8_VECTOR__) +# define XSUM_ARCH "ppc64 + POWER8 vector" +# else +# define XSUM_ARCH "ppc64" +# endif +#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) +# define XSUM_ARCH "ppc" +#elif defined(__AVR) +# define XSUM_ARCH "AVR" +#elif defined(__mips64) +# define XSUM_ARCH "mips64" +#elif defined(__mips) +# define XSUM_ARCH "mips" +#elif defined(__s390x__) +# define XSUM_ARCH "s390x" +#elif defined(__s390__) +# define XSUM_ARCH "s390" +#else +# define XSUM_ARCH "unknown" +#endif + + +#endif /* XSUM_ARCH_H */ diff --git a/third_party/xxhash/cli/xsum_config.h b/third_party/xxhash/cli/xsum_config.h new file mode 100644 index 00000000000..9222144d0e7 --- /dev/null +++ b/third_party/xxhash/cli/xsum_config.h @@ -0,0 +1,205 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * This contains various configuration parameters and feature detection for + * xxhsum. + * + * Similar to config.h in Autotools, this should be the first header included. + */ + +#ifndef XSUM_CONFIG_H +#define XSUM_CONFIG_H + + +/* ************************************ + * Compiler Options + **************************************/ +/* + * Disable Visual C's warnings when using the "insecure" CRT functions instead + * of the "secure" _s functions. + * + * These functions are not portable, and aren't necessary if you are using the + * original functions properly. + */ +#if defined(_MSC_VER) || defined(_WIN32) +# ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS +# endif +#endif + +/* Under Linux at least, pull in the *64 commands */ +#ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +#endif +#ifndef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 +#endif + +/* + * So we can use __attribute__((__format__)) + */ +#ifdef __GNUC__ +# define XSUM_ATTRIBUTE(x) __attribute__(x) +#else +# define XSUM_ATTRIBUTE(x) +#endif + +#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) /* UNIX-like OS */ \ + || defined(__midipix__) || defined(__VMS)) +# if (defined(__APPLE__) && defined(__MACH__)) || defined(__SVR4) || defined(_AIX) || defined(__hpux) /* POSIX.1-2001 (SUSv3) conformant */ \ + || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) /* BSD distros */ +# define XSUM_PLATFORM_POSIX_VERSION 200112L +# else +# if defined(__linux__) || defined(__linux) +# ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L /* use feature test macro */ +# endif +# endif +# include /* declares _POSIX_VERSION */ +# if defined(_POSIX_VERSION) /* POSIX compliant */ +# define XSUM_PLATFORM_POSIX_VERSION _POSIX_VERSION +# else +# define XSUM_PLATFORM_POSIX_VERSION 0 +# endif +# endif +#endif +#if !defined(XSUM_PLATFORM_POSIX_VERSION) +# define XSUM_PLATFORM_POSIX_VERSION -1 +#endif + +#if !defined(S_ISREG) +# define S_ISREG(x) (((x) & S_IFMT) == S_IFREG) +#endif + + +/* ************************************ + * Windows helpers + **************************************/ + +/* + * Whether to use the Windows UTF-16 APIs instead of the portable libc 8-bit + * ("ANSI") APIs. + * + * Windows is not UTF-8 clean by default, and the only way to access every file + * on the OS is to use UTF-16. + * + * Do note that xxhsum uses UTF-8 internally and only uses UTF-16 for command + * line arguments, console I/O, and opening files. + * + * Additionally, this guarantees all piped output is UTF-8. + */ +#if defined(XSUM_WIN32_USE_WCHAR) && !defined(_WIN32) +/* We use Windows APIs, only use this on Windows. */ +# undef XSUM_WIN32_USE_WCHAR +#endif + +#ifndef XSUM_WIN32_USE_WCHAR +# if defined(_WIN32) +# include +# if WCHAR_MAX == 0xFFFFU /* UTF-16 wchar_t */ +# define XSUM_WIN32_USE_WCHAR 1 +# else +# define XSUM_WIN32_USE_WCHAR 0 +# endif +# else +# define XSUM_WIN32_USE_WCHAR 0 +# endif +#endif + +#if !XSUM_WIN32_USE_WCHAR +/* + * It doesn't make sense to have one without the other. + * Due to XSUM_WIN32_USE_WCHAR being undef'd, this also handles + * non-WIN32 platforms. + */ +# undef XSUM_WIN32_USE_WMAIN +# define XSUM_WIN32_USE_WMAIN 0 +#else +/* + * Whether to use wmain() or main(). + * + * wmain() is preferred because we don't have to mess with internal hidden + * APIs. + * + * It always works on MSVC, but in MinGW, it only works on MinGW-w64 with the + * -municode flag. + * + * Therefore we have to use main() -- there is no better option. + */ +# ifndef XSUM_WIN32_USE_WMAIN +# if defined(_UNICODE) || defined(UNICODE) /* MinGW -municode */ \ + || defined(_MSC_VER) /* MSVC */ +# define XSUM_WIN32_USE_WMAIN 1 +# else +# define XSUM_WIN32_USE_WMAIN 0 +# endif +# endif +/* + * It is always good practice to define these to prevent accidental use of the + * ANSI APIs, even if the program primarily uses UTF-8. + */ +# ifndef _UNICODE +# define _UNICODE +# endif +# ifndef UNICODE +# define UNICODE +# endif +#endif /* XSUM_WIN32_USE_WCHAR */ + +#ifndef XSUM_API +# ifdef XXH_INLINE_ALL +# define XSUM_API static +# else +# define XSUM_API +# endif +#endif + +#ifndef XSUM_NO_TESTS +# define XSUM_NO_TESTS 0 +#endif + +/* *************************** + * Basic types + * ***************************/ + +#if defined(__cplusplus) /* C++ */ \ + || (defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) /* C99 */ +# include + typedef uint8_t XSUM_U8; + typedef uint32_t XSUM_U32; + typedef uint64_t XSUM_U64; +# else +# include + typedef unsigned char XSUM_U8; +# if UINT_MAX == 0xFFFFFFFFUL + typedef unsigned int XSUM_U32; +# else + typedef unsigned long XSUM_U32; +# endif + typedef unsigned long long XSUM_U64; +#endif /* not C++/C99 */ + +#endif /* XSUM_CONFIG_H */ diff --git a/third_party/xxhash/cli/xsum_os_specific.c b/third_party/xxhash/cli/xsum_os_specific.c new file mode 100644 index 00000000000..8f48ce0762b --- /dev/null +++ b/third_party/xxhash/cli/xsum_os_specific.c @@ -0,0 +1,487 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#include "xsum_config.h" +#include "xsum_os_specific.h" +#include +#include +#include +#include /* struct stat / __wstat64 */ +#include /* stat() / _stat64() */ + +/* + * This file contains all of the ugly boilerplate to make xxhsum work across + * platforms. + */ +#if defined(_MSC_VER) || XSUM_WIN32_USE_WCHAR + typedef struct __stat64 XSUM_stat_t; +# if defined(_MSC_VER) + typedef int mode_t; +# endif +#else + typedef struct stat XSUM_stat_t; +#endif + +#if (defined(__linux__) && (XSUM_PLATFORM_POSIX_VERSION >= 1)) \ + || (XSUM_PLATFORM_POSIX_VERSION >= 200112L) \ + || defined(__DJGPP__) \ + || defined(__MSYS__) +# include /* isatty */ +# define XSUM_IS_CONSOLE(stdStream) isatty(fileno(stdStream)) +#elif defined(MSDOS) || defined(OS2) +# include /* _isatty */ +# define XSUM_IS_CONSOLE(stdStream) _isatty(_fileno(stdStream)) +#elif defined(WIN32) || defined(_WIN32) +# include /* _isatty */ +# include /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */ +# include /* FILE */ +static __inline int XSUM_IS_CONSOLE(FILE* stdStream) +{ + DWORD dummy; + return _isatty(_fileno(stdStream)) && GetConsoleMode((HANDLE)_get_osfhandle(_fileno(stdStream)), &dummy); +} +#else +# define XSUM_IS_CONSOLE(stdStream) 0 +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(_WIN32) +# include /* _O_BINARY */ +# include /* _setmode, _fileno, _get_osfhandle */ +# if !defined(__DJGPP__) +# include /* DeviceIoControl, HANDLE, FSCTL_SET_SPARSE */ +# include /* FSCTL_SET_SPARSE */ +# define XSUM_SET_BINARY_MODE(file) { int const unused=_setmode(_fileno(file), _O_BINARY); (void)unused; } +# else +# define XSUM_SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +# endif +#else +# define XSUM_SET_BINARY_MODE(file) ((void)file) +#endif + +XSUM_API int XSUM_isConsole(FILE* stream) +{ + return XSUM_IS_CONSOLE(stream); +} + +XSUM_API void XSUM_setBinaryMode(FILE* stream) +{ + XSUM_SET_BINARY_MODE(stream); +} + +#if !XSUM_WIN32_USE_WCHAR + +XSUM_API FILE* XSUM_fopen(const char* filename, const char* mode) +{ + return fopen(filename, mode); +} +XSUM_ATTRIBUTE((__format__(__printf__, 2, 0))) +XSUM_API int XSUM_vfprintf(FILE* stream, const char* format, va_list ap) +{ + return vfprintf(stream, format, ap); +} + +static int XSUM_stat(const char* infilename, XSUM_stat_t* statbuf) +{ +#if defined(_MSC_VER) + return _stat64(infilename, statbuf); +#else + return stat(infilename, statbuf); +#endif +} + +#ifndef XSUM_NO_MAIN +int main(int argc, char* argv[]) +{ + return XSUM_main(argc, argv); +} +#endif + +/* Unicode helpers for Windows to make UTF-8 act as it should. */ +#else +# include +# include + +/***************************************************************************** + * Unicode conversion tools + *****************************************************************************/ + +/* + * Converts a UTF-8 string to UTF-16. Acts like strdup. The string must be freed afterwards. + * This version allows keeping the output length. + */ +static wchar_t* XSUM_widenString(const char* str, int* lenOut) +{ + int const len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); + if (lenOut != NULL) *lenOut = len; + if (len == 0) return NULL; + { wchar_t* buf = (wchar_t*)malloc((size_t)len * sizeof(wchar_t)); + if (buf != NULL) { + if (MultiByteToWideChar(CP_UTF8, 0, str, -1, buf, len) == 0) { + free(buf); + return NULL; + } } + return buf; + } +} + +/* + * Converts a UTF-16 string to UTF-8. Acts like strdup. The string must be freed afterwards. + * This version allows keeping the output length. + */ +static char* XSUM_narrowString(const wchar_t *str, int *lenOut) +{ + int len = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL); + if (lenOut != NULL) *lenOut = len; + if (len == 0) return NULL; + { char* const buf = (char*)malloc((size_t)len * sizeof(char)); + if (buf != NULL) { + if (WideCharToMultiByte(CP_UTF8, 0, str, -1, buf, len, NULL, NULL) == 0) { + free(buf); + return NULL; + } } + return buf; + } +} + + + +/***************************************************************************** + * File helpers + *****************************************************************************/ +/* + * fopen wrapper that supports UTF-8 + * + * fopen will only accept ANSI filenames, which means that we can't open Unicode filenames. + * + * In order to open a Unicode filename, we need to convert filenames to UTF-16 and use _wfopen. + */ +XSUM_API FILE* XSUM_fopen(const char* filename, const char* mode) +{ + FILE* f = NULL; + wchar_t* const wide_filename = XSUM_widenString(filename, NULL); + if (wide_filename != NULL) { + wchar_t* const wide_mode = XSUM_widenString(mode, NULL); + if (wide_mode != NULL) { + f = _wfopen(wide_filename, wide_mode); + free(wide_mode); + } + free(wide_filename); + } + return f; +} + +/* + * stat() wrapper which supports UTF-8 filenames. + */ +static int XSUM_stat(const char* infilename, XSUM_stat_t* statbuf) +{ + int r = -1; + wchar_t* const wide_filename = XSUM_widenString(infilename, NULL); + if (wide_filename != NULL) { + r = _wstat64(wide_filename, statbuf); + free(wide_filename); + } + return r; +} + +/* + * In case it isn't available, this is what MSVC 2019 defines in stdarg.h. + */ +#if defined(_MSC_VER) && !defined(__clang__) && !defined(va_copy) +# define XSUM_va_copy(destination, source) ((destination) = (source)) +#else +# define XSUM_va_copy(destination, source) va_copy(destination, source) +#endif + +/* + * vasprintf for Windows. + */ +XSUM_ATTRIBUTE((__format__(__printf__, 2, 0))) +static int XSUM_vasprintf(char** strp, const char* format, va_list ap) +{ + int ret; + int size; + va_list copy; + /* + * To be safe, make a va_copy. + * + * Note that Microsoft doesn't use va_copy in its sample code: + * https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/vsprintf-vsprintf-l-vswprintf-vswprintf-l-vswprintf-l?view=vs-2019 + */ + XSUM_va_copy(copy, ap); + /* Calculate how many characters we need */ + size = _vscprintf(format, ap); + va_end(copy); + + if (size < 0) { + *strp = NULL; + return size; + } else { + *strp = (char*) malloc((size_t)size + 1); + if (*strp == NULL) { + return -1; + } + /* vsprintf into the new buffer */ + ret = vsprintf(*strp, format, ap); + if (ret < 0) { + free(*strp); + *strp = NULL; + } + return ret; + } +} + +/* + * fprintf wrapper that supports UTF-8. + * + * fprintf doesn't properly handle Unicode on Windows. + * + * Additionally, it is codepage sensitive on console and may crash the program. + * + * Instead, we use vsnprintf, and either print with fwrite or convert to UTF-16 + * for console output and use the codepage-independent WriteConsoleW. + * + * Credit to t-mat: https://github.com/t-mat/xxHash/commit/5691423 + */ +XSUM_ATTRIBUTE((__format__(__printf__, 2, 0))) +XSUM_API int XSUM_vfprintf(FILE *stream, const char *format, va_list ap) +{ + int result; + char* u8_str = NULL; + + /* + * Generate the UTF-8 output string with vasprintf. + */ + result = XSUM_vasprintf(&u8_str, format, ap); + + if (result >= 0) { + const size_t nchar = (size_t)result + 1; + + /* + * Check if we are outputting to a console. Don't use XSUM_isConsole + * directly -- we don't need to call _get_osfhandle twice. + */ + int fileNb = _fileno(stream); + intptr_t handle_raw = _get_osfhandle(fileNb); + HANDLE handle = (HANDLE)handle_raw; + DWORD dwTemp; + + if (handle_raw < 0) { + result = -1; + } else if (_isatty(fileNb) && GetConsoleMode(handle, &dwTemp)) { + /* + * Convert to UTF-16 and output with WriteConsoleW. + * + * This is codepage independent and works on Windows XP's default + * msvcrt.dll. + */ + int len; + wchar_t* const u16_buf = XSUM_widenString(u8_str, &len); + if (u16_buf == NULL) { + result = -1; + } else { + if (WriteConsoleW(handle, u16_buf, (DWORD)len - 1, &dwTemp, NULL)) { + result = (int)dwTemp; + } else { + result = -1; + } + free(u16_buf); + } + } else { + /* fwrite the UTF-8 string if we are printing to a file */ + result = (int)fwrite(u8_str, 1, nchar - 1, stream); + if (result == 0) { + result = -1; + } + } + free(u8_str); + } + return result; +} + +#ifndef XSUM_NO_MAIN +/***************************************************************************** + * Command Line argument parsing + *****************************************************************************/ + +/* Converts a UTF-16 argv to UTF-8. */ +static char** XSUM_convertArgv(int argc, wchar_t* utf16_argv[]) +{ + char** const utf8_argv = (char**)malloc((size_t)(argc + 1) * sizeof(char*)); + if (utf8_argv != NULL) { + int i; + for (i = 0; i < argc; i++) { + utf8_argv[i] = XSUM_narrowString(utf16_argv[i], NULL); + if (utf8_argv[i] == NULL) { + /* Out of memory, whoops. */ + while (i-- > 0) { + free(utf8_argv[i]); + } + free(utf8_argv); + return NULL; + } + } + utf8_argv[argc] = NULL; + } + return utf8_argv; +} +/* Frees arguments returned by XSUM_convertArgv */ +static void XSUM_freeArgv(int argc, char** argv) +{ + int i; + if (argv == NULL) { + return; + } + for (i = 0; i < argc; i++) { + free(argv[i]); + } + free(argv); +} + +static int XSUM_wmain(int argc, wchar_t* utf16_argv[]) +{ + /* Convert the UTF-16 arguments to UTF-8. */ + char** utf8_argv = XSUM_convertArgv(argc, utf16_argv); + + if (utf8_argv == NULL) { + /* An unfortunate but incredibly unlikely error. */ + fprintf(stderr, "xxhsum: error converting command line arguments!\n"); + abort(); + } else { + int ret; + + /* + * MinGW's terminal uses full block buffering for stderr. + * + * This is nonstandard behavior and causes text to not display until + * the buffer fills. + * + * `setvbuf()` can easily correct this to make text display instantly. + */ + setvbuf(stderr, NULL, _IONBF, 0); + + /* Call our real main function */ + ret = XSUM_main(argc, utf8_argv); + + /* Cleanup */ + XSUM_freeArgv(argc, utf8_argv); + return ret; + } +} + +#if XSUM_WIN32_USE_WMAIN + +/* + * The preferred method of obtaining the real UTF-16 arguments. Always works + * on MSVC, sometimes works on MinGW-w64 depending on the compiler flags. + */ +#ifdef __cplusplus +extern "C" +#endif +int __cdecl wmain(int argc, wchar_t* utf16_argv[]) +{ + return XSUM_wmain(argc, utf16_argv); +} +#else /* !XSUM_WIN32_USE_WMAIN */ + +/* + * Wrap `XSUM_wmain()` using `main()` and `__wgetmainargs()` on MinGW without + * Unicode support. + * + * `__wgetmainargs()` is used in the CRT startup to retrieve the arguments for + * `wmain()`, so we use it on MinGW to emulate `wmain()`. + * + * It is an internal function and not declared in any public headers, so we + * have to declare it manually. + * + * An alternative that doesn't mess with internal APIs is `GetCommandLineW()` + * with `CommandLineToArgvW()`, but the former doesn't expand wildcards and the + * latter requires linking to Shell32.dll and its numerous dependencies. + * + * This method keeps our dependencies to kernel32.dll and the CRT. + * + * https://docs.microsoft.com/en-us/cpp/c-runtime-library/getmainargs-wgetmainargs?view=vs-2019 + */ +typedef struct { + int newmode; +} _startupinfo; + +#ifdef __cplusplus +extern "C" +#endif +int __cdecl __wgetmainargs( + int* Argc, + wchar_t*** Argv, + wchar_t*** Env, + int DoWildCard, + _startupinfo* StartInfo +); + +int main(int ansi_argc, char* ansi_argv[]) +{ + int utf16_argc; + wchar_t** utf16_argv; + wchar_t** utf16_envp; /* Unused but required */ + _startupinfo startinfo = {0}; /* 0 == don't change new mode */ + + /* Get wmain's UTF-16 arguments. Make sure we expand wildcards. */ + if (__wgetmainargs(&utf16_argc, &utf16_argv, &utf16_envp, 1, &startinfo) < 0) + /* In the very unlikely case of an error, use the ANSI arguments. */ + return XSUM_main(ansi_argc, ansi_argv); + + /* Call XSUM_wmain with our UTF-16 arguments */ + return XSUM_wmain(utf16_argc, utf16_argv); +} + +#endif /* !XSUM_WIN32_USE_WMAIN */ +#endif /* !XSUM_NO_MAIN */ +#endif /* XSUM_WIN32_USE_WCHAR */ + + +/* + * Determines whether the file at filename is a directory. + */ +XSUM_API int XSUM_isDirectory(const char* filename) +{ + XSUM_stat_t statbuf; + int r = XSUM_stat(filename, &statbuf); +#ifdef _MSC_VER + if (!r && (statbuf.st_mode & _S_IFDIR)) return 1; +#else + if (!r && S_ISDIR(statbuf.st_mode)) return 1; +#endif + return 0; +} + +/* + * Returns the filesize of the file at filename. + */ +XSUM_API XSUM_U64 XSUM_getFileSize(const char* filename) +{ + XSUM_stat_t statbuf; + int r = XSUM_stat(filename, &statbuf); + if (r || !S_ISREG(statbuf.st_mode)) return 0; /* No good... */ + return (XSUM_U64)statbuf.st_size; +} diff --git a/third_party/xxhash/cli/xsum_os_specific.h b/third_party/xxhash/cli/xsum_os_specific.h new file mode 100644 index 00000000000..b3562b260d5 --- /dev/null +++ b/third_party/xxhash/cli/xsum_os_specific.h @@ -0,0 +1,89 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#ifndef XSUM_OS_SPECIFIC_H +#define XSUM_OS_SPECIFIC_H + +#include "xsum_config.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Declared here to be implemented in user code. + * + * Functions like main(), but is passed UTF-8 arguments even on Windows. + */ +XSUM_API int XSUM_main(int argc, char* argv[]); + +/* + * Returns whether stream is a console. + * + * Functionally equivalent to isatty(fileno(stream)). + */ +XSUM_API int XSUM_isConsole(FILE* stream); + +/* + * Sets stream to pure binary mode (a.k.a. no CRLF conversions). + */ +XSUM_API void XSUM_setBinaryMode(FILE* stream); + +/* + * Returns whether the file at filename is a directory. + */ +XSUM_API int XSUM_isDirectory(const char* filename); + +/* + * Returns the file size of the file at filename. + */ +XSUM_API XSUM_U64 XSUM_getFileSize(const char* filename); + +/* + * UTF-8 stdio wrappers primarily for Windows + */ + +/* + * fopen() wrapper. Accepts UTF-8 filenames on Windows. + * + * Specifically, on Windows, the arguments will be converted to UTF-16 + * and passed to _wfopen(). + */ +XSUM_API FILE* XSUM_fopen(const char* filename, const char* mode); + +/* + * vfprintf() wrapper which prints UTF-8 strings to Windows consoles + * if applicable. + */ +XSUM_ATTRIBUTE((__format__(__printf__, 2, 0))) +XSUM_API int XSUM_vfprintf(FILE* stream, const char* format, va_list ap); + +#ifdef __cplusplus +} +#endif + +#endif /* XSUM_OS_SPECIFIC_H */ diff --git a/third_party/xxhash/cli/xsum_output.c b/third_party/xxhash/cli/xsum_output.c new file mode 100644 index 00000000000..a4d741154d6 --- /dev/null +++ b/third_party/xxhash/cli/xsum_output.c @@ -0,0 +1,67 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#include "xsum_output.h" +#include "xsum_os_specific.h" +#include + +int XSUM_logLevel = 2; + +XSUM_ATTRIBUTE((__format__(__printf__, 1, 2))) +XSUM_API int XSUM_log(const char* format, ...) +{ + int ret; + va_list ap; + va_start(ap, format); + ret = XSUM_vfprintf(stderr, format, ap); + va_end(ap); + return ret; +} + + +XSUM_ATTRIBUTE((__format__(__printf__, 1, 2))) +XSUM_API int XSUM_output(const char* format, ...) +{ + int ret; + va_list ap; + va_start(ap, format); + ret = XSUM_vfprintf(stdout, format, ap); + va_end(ap); + return ret; +} + +XSUM_ATTRIBUTE((__format__(__printf__, 2, 3))) +XSUM_API int XSUM_logVerbose(int minLevel, const char* format, ...) +{ + if (XSUM_logLevel >= minLevel) { + int ret; + va_list ap; + va_start(ap, format); + ret = XSUM_vfprintf(stderr, format, ap); + va_end(ap); + return ret; + } + return 0; +} diff --git a/third_party/xxhash/cli/xsum_output.h b/third_party/xxhash/cli/xsum_output.h new file mode 100644 index 00000000000..8a02c1b777c --- /dev/null +++ b/third_party/xxhash/cli/xsum_output.h @@ -0,0 +1,62 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#ifndef XSUM_OUTPUT_H +#define XSUM_OUTPUT_H + +#include "xsum_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * How verbose the output is. + */ +extern int XSUM_logLevel; + +/* + * Same as fprintf(stderr, format, ...) + */ +XSUM_ATTRIBUTE((__format__(__printf__, 1, 2))) +XSUM_API int XSUM_log(const char *format, ...); + +/* + * Like XSUM_log, but only outputs if XSUM_logLevel >= minLevel. + */ +XSUM_ATTRIBUTE((__format__(__printf__, 2, 3))) +XSUM_API int XSUM_logVerbose(int minLevel, const char *format, ...); + +/* + * Same as printf(format, ...) + */ +XSUM_ATTRIBUTE((__format__(__printf__, 1, 2))) +XSUM_API int XSUM_output(const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* XSUM_OUTPUT_H */ diff --git a/third_party/xxhash/cli/xsum_sanity_check.c b/third_party/xxhash/cli/xsum_sanity_check.c new file mode 100644 index 00000000000..347d1db58e1 --- /dev/null +++ b/third_party/xxhash/cli/xsum_sanity_check.c @@ -0,0 +1,602 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#include "xsum_config.h" +#include "xsum_sanity_check.h" +#include "xsum_output.h" +#include +#include +#include +#ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY +#endif +#include "../xxhash.h" + +/* use #define to make them constant, required for initialization */ +#define PRIME32 2654435761U +#define PRIME64 11400714785074694797ULL + +/* + * Fills a test buffer with pseudorandom data. + * + * This is used in the sanity check - its values must not be changed. + */ +XSUM_API void XSUM_fillTestBuffer(XSUM_U8* buffer, size_t len) +{ + XSUM_U64 byteGen = PRIME32; + size_t i; + + assert(buffer != NULL); + + for (i=0; i>56); + byteGen *= PRIME64; + } +} + + + +/* ************************************************ + * Self-test: + * ensure results consistency accross platforms + *********************************************** */ +#if XSUM_NO_TESTS +XSUM_API void XSUM_sanityCheck(void) +{ + XSUM_log("This version of xxhsum is not verified.\n"); +} +#else + +/* + * Test data vectors + */ +typedef struct { + XSUM_U32 len; + XSUM_U32 seed; + XSUM_U32 Nresult; +} XSUM_testdata32_t; + +typedef struct { + XSUM_U32 len; + XSUM_U64 seed; + XSUM_U64 Nresult; +} XSUM_testdata64_t; + +typedef struct { + XSUM_U32 len; + XSUM_U64 seed; + XXH128_hash_t Nresult; +} XSUM_testdata128_t; + +#define SECRET_SAMPLE_NBBYTES 4 +typedef struct { + XSUM_U32 len; + XSUM_U8 byte[SECRET_SAMPLE_NBBYTES]; +} XSUM_testdata_sample_t; + +/* XXH32 */ +static const XSUM_testdata32_t XSUM_XXH32_testdata[] = { + { 0, 0, 0x02CC5D05U }, + { 0, PRIME32, 0x36B78AE7U }, + { 1, 0, 0xCF65B03EU }, + { 1, PRIME32, 0xB4545AA4U }, + { 14, 0, 0x1208E7E2U }, + { 14, PRIME32, 0x6AF1D1FEU }, + { 222, 0, 0x5BD11DBDU }, + { 222, PRIME32, 0x58803C5FU } +}; + +/* XXH64 */ +static const XSUM_testdata64_t XSUM_XXH64_testdata[] = { + { 0, 0, 0xEF46DB3751D8E999ULL }, + { 0, PRIME32, 0xAC75FDA2929B17EFULL }, + { 1, 0, 0xE934A84ADB052768ULL }, + { 1, PRIME32, 0x5014607643A9B4C3ULL }, + { 4, 0, 0x9136A0DCA57457EEULL }, + { 14, 0, 0x8282DCC4994E35C8ULL }, + { 14, PRIME32, 0xC3BD6BF63DEB6DF0ULL }, + { 222, 0, 0xB641AE8CB691C174ULL }, + { 222, PRIME32, 0x20CB8AB7AE10C14AULL } +}; +/* + * XXH3: + * Due to being a more complex hash function with specializations for certain + * lengths, a more extensive test is used for XXH3. + */ + +/* XXH3_64bits, seeded */ +static const XSUM_testdata64_t XSUM_XXH3_testdata[] = { + { 0, 0, 0x2D06800538D394C2ULL }, /* empty string */ + { 0, PRIME64, 0xA8A6B918B2F0364AULL }, /* empty string */ + { 1, 0, 0xC44BDFF4074EECDBULL }, /* 1 - 3 */ + { 1, PRIME64, 0x032BE332DD766EF8ULL }, /* 1 - 3 */ + { 6, 0, 0x27B56A84CD2D7325ULL }, /* 4 - 8 */ + { 6, PRIME64, 0x84589C116AB59AB9ULL }, /* 4 - 8 */ + { 12, 0, 0xA713DAF0DFBB77E7ULL }, /* 9 - 16 */ + { 12, PRIME64, 0xE7303E1B2336DE0EULL }, /* 9 - 16 */ + { 24, 0, 0xA3FE70BF9D3510EBULL }, /* 17 - 32 */ + { 24, PRIME64, 0x850E80FC35BDD690ULL }, /* 17 - 32 */ + { 48, 0, 0x397DA259ECBA1F11ULL }, /* 33 - 64 */ + { 48, PRIME64, 0xADC2CBAA44ACC616ULL }, /* 33 - 64 */ + { 80, 0, 0xBCDEFBBB2C47C90AULL }, /* 65 - 96 */ + { 80, PRIME64, 0xC6DD0CB699532E73ULL }, /* 65 - 96 */ + { 195, 0, 0xCD94217EE362EC3AULL }, /* 129-240 */ + { 195, PRIME64, 0xBA68003D370CB3D9ULL }, /* 129-240 */ + + { 403, 0, 0xCDEB804D65C6DEA4ULL }, /* one block, last stripe is overlapping */ + { 403, PRIME64, 0x6259F6ECFD6443FDULL }, /* one block, last stripe is overlapping */ + { 512, 0, 0x617E49599013CB6BULL }, /* one block, finishing at stripe boundary */ + { 512, PRIME64, 0x3CE457DE14C27708ULL }, /* one block, finishing at stripe boundary */ + { 2048, 0, 0xDD59E2C3A5F038E0ULL }, /* 2 blocks, finishing at block boundary */ + { 2048, PRIME64, 0x66F81670669ABABCULL }, /* 2 blocks, finishing at block boundary */ + { 2240, 0, 0x6E73A90539CF2948ULL }, /* 3 blocks, finishing at stripe boundary */ + { 2240, PRIME64, 0x757BA8487D1B5247ULL }, /* 3 blocks, finishing at stripe boundary */ + { 2367, 0, 0xCB37AEB9E5D361EDULL }, /* 3 blocks, last stripe is overlapping */ + { 2367, PRIME64, 0xD2DB3415B942B42AULL } /* 3 blocks, last stripe is overlapping */ +}; +/* XXH3_64bits, custom secret */ +static const XSUM_testdata64_t XSUM_XXH3_withSecret_testdata[] = { + { 0, 0, 0x3559D64878C5C66CULL }, /* empty string */ + { 1, 0, 0x8A52451418B2DA4DULL }, /* 1 - 3 */ + { 6, 0, 0x82C90AB0519369ADULL }, /* 4 - 8 */ + { 12, 0, 0x14631E773B78EC57ULL }, /* 9 - 16 */ + { 24, 0, 0xCDD5542E4A9D9FE8ULL }, /* 17 - 32 */ + { 48, 0, 0x33ABD54D094B2534ULL }, /* 33 - 64 */ + { 80, 0, 0xE687BA1684965297ULL }, /* 65 - 96 */ + { 195, 0, 0xA057273F5EECFB20ULL }, /* 129-240 */ + + { 403, 0, 0x14546019124D43B8ULL }, /* one block, last stripe is overlapping */ + { 512, 0, 0x7564693DD526E28DULL }, /* one block, finishing at stripe boundary */ + { 2048, 0, 0xD32E975821D6519FULL }, /* >= 2 blodcks, at least one scrambling */ + { 2367, 0, 0x293FA8E5173BB5E7ULL }, /* >= 2 blocks, at least one scrambling, last stripe unaligned */ + + { 64*10*3, 0, 0x751D2EC54BC6038BULL } /* exactly 3 full blocks, not a multiple of 256 */ +}; +/* XXH3_128bits, seeded */ +static const XSUM_testdata128_t XSUM_XXH128_testdata[] = { + { 0, 0, { 0x6001C324468D497FULL, 0x99AA06D3014798D8ULL } }, /* empty string */ + { 0, PRIME32, { 0x5444F7869C671AB0ULL, 0x92220AE55E14AB50ULL } }, /* empty string */ + { 1, 0, { 0xC44BDFF4074EECDBULL, 0xA6CD5E9392000F6AULL } }, /* 1 - 3 */ + { 1, PRIME32, { 0xB53D5557E7F76F8DULL, 0x89B99554BA22467CULL } }, /* 1 - 3 */ + { 6, 0, { 0x3E7039BDDA43CFC6ULL, 0x082AFE0B8162D12AULL } }, /* 4 - 8 */ + { 6, PRIME32, { 0x269D8F70BE98856EULL, 0x5A865B5389ABD2B1ULL } }, /* 4 - 8 */ + { 12, 0, { 0x061A192713F69AD9ULL, 0x6E3EFD8FC7802B18ULL } }, /* 9 - 16 */ + { 12, PRIME32, { 0x9BE9F9A67F3C7DFBULL, 0xD7E09D518A3405D3ULL } }, /* 9 - 16 */ + { 24, 0, { 0x1E7044D28B1B901DULL, 0x0CE966E4678D3761ULL } }, /* 17 - 32 */ + { 24, PRIME32, { 0xD7304C54EBAD40A9ULL, 0x3162026714A6A243ULL } }, /* 17 - 32 */ + { 48, 0, { 0xF942219AED80F67BULL, 0xA002AC4E5478227EULL } }, /* 33 - 64 */ + { 48, PRIME32, { 0x7BA3C3E453A1934EULL, 0x163ADDE36C072295ULL } }, /* 33 - 64 */ + { 81, 0, { 0x5E8BAFB9F95FB803ULL, 0x4952F58181AB0042ULL } }, /* 65 - 96 */ + { 81, PRIME32, { 0x703FBB3D7A5F755CULL, 0x2724EC7ADC750FB6ULL } }, /* 65 - 96 */ + { 222, 0, { 0xF1AEBD597CEC6B3AULL, 0x337E09641B948717ULL } }, /* 129-240 */ + { 222, PRIME32, { 0xAE995BB8AF917A8DULL, 0x91820016621E97F1ULL } }, /* 129-240 */ + + { 403, 0, { 0xCDEB804D65C6DEA4ULL, 0x1B6DE21E332DD73DULL } }, /* one block, last stripe is overlapping */ + { 403, PRIME64, { 0x6259F6ECFD6443FDULL, 0xBED311971E0BE8F2ULL } }, /* one block, last stripe is overlapping */ + { 512, 0, { 0x617E49599013CB6BULL, 0x18D2D110DCC9BCA1ULL } }, /* one block, finishing at stripe boundary */ + { 512, PRIME64, { 0x3CE457DE14C27708ULL, 0x925D06B8EC5B8040ULL } }, /* one block, finishing at stripe boundary */ + { 2048, 0, { 0xDD59E2C3A5F038E0ULL, 0xF736557FD47073A5ULL } }, /* 2 blocks, finishing at block boundary */ + { 2048, PRIME32, { 0x230D43F30206260BULL, 0x7FB03F7E7186C3EAULL } }, /* 2 blocks, finishing at block boundary */ + { 2240, 0, { 0x6E73A90539CF2948ULL, 0xCCB134FBFA7CE49DULL } }, /* 3 blocks, finishing at stripe boundary */ + { 2240, PRIME32, { 0xED385111126FBA6FULL, 0x50A1FE17B338995FULL } }, /* 3 blocks, finishing at stripe boundary */ + { 2367, 0, { 0xCB37AEB9E5D361EDULL, 0xE89C0F6FF369B427ULL } }, /* 3 blocks, last stripe is overlapping */ + { 2367, PRIME32, { 0x6F5360AE69C2F406ULL, 0xD23AAE4B76C31ECBULL } } /* 3 blocks, last stripe is overlapping */ +}; + +/* XXH128, custom secret */ +static const XSUM_testdata128_t XSUM_XXH128_withSecret_testdata[] = { + { 0, 0, { 0x005923CCEECBE8AEULL, 0x5F70F4EA232F1D38ULL } }, /* empty string */ + { 1, 0, { 0x8A52451418B2DA4DULL, 0x3A66AF5A9819198EULL } }, /* 1 - 3 */ + { 6, 0, { 0x0B61C8ACA7D4778FULL, 0x376BD91B6432F36DULL } }, /* 4 - 8 */ + { 12, 0, { 0xAF82F6EBA263D7D8ULL, 0x90A3C2D839F57D0FULL } } /* 9 - 16 */ +}; + +static const XSUM_testdata_sample_t XSUM_XXH3_generateSecret_testdata[] = { + { 0, { 0xB8, 0x26, 0x83, 0x7E } }, + { 1, { 0xA6, 0x16, 0x06, 0x7B } }, + { XXH3_SECRET_SIZE_MIN - 1, { 0xDA, 0x2A, 0x12, 0x11 } }, + { XXH3_SECRET_DEFAULT_SIZE + 500, { 0x7E, 0x48, 0x0C, 0xA7 } } +}; + +static void XSUM_checkResult32(XXH32_hash_t r1, XXH32_hash_t r2) +{ + static int nbTests = 1; + if (r1!=r2) { + XSUM_log("\rError: 32-bit hash test %i: Internal sanity check failed!\n", nbTests); + XSUM_log("\rGot 0x%08X, expected 0x%08X.\n", (unsigned)r1, (unsigned)r2); + XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n" + "or temporarily recompile with XSUM_NO_TESTS=1.\n"); + exit(1); + } + nbTests++; +} + +static void XSUM_checkResult64(XXH64_hash_t r1, XXH64_hash_t r2) +{ + static int nbTests = 1; + if (r1!=r2) { + XSUM_log("\rError: 64-bit hash test %i: Internal sanity check failed!\n", nbTests); + XSUM_log("\rGot 0x%08X%08XULL, expected 0x%08X%08XULL.\n", + (unsigned)(r1>>32), (unsigned)r1, (unsigned)(r2>>32), (unsigned)r2); + XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n" + "or temporarily recompile with XSUM_NO_TESTS=1.\n"); + exit(1); + } + nbTests++; +} + +static void XSUM_checkResult128(XXH128_hash_t r1, XXH128_hash_t r2) +{ + static int nbTests = 1; + if ((r1.low64 != r2.low64) || (r1.high64 != r2.high64)) { + XSUM_log("\rError: 128-bit hash test %i: Internal sanity check failed.\n", nbTests); + XSUM_log("\rGot { 0x%08X%08XULL, 0x%08X%08XULL }, expected { 0x%08X%08XULL, 0x%08X%08XULL } \n", + (unsigned)(r1.low64>>32), (unsigned)r1.low64, (unsigned)(r1.high64>>32), (unsigned)r1.high64, + (unsigned)(r2.low64>>32), (unsigned)r2.low64, (unsigned)(r2.high64>>32), (unsigned)r2.high64 ); + XSUM_log("\rNote: If you modified the hash functions, make sure to either update the values\n" + "or temporarily recompile with XSUM_NO_TESTS=1.\n"); + exit(1); + } + nbTests++; +} + + +static void XSUM_testXXH32(const void* data, const XSUM_testdata32_t* testData) +{ + XXH32_state_t *state = XXH32_createState(); + size_t pos; + + size_t len = testData->len; + XSUM_U32 seed = testData->seed; + XSUM_U32 Nresult = testData->Nresult; + + if (len == 0) { + data = NULL; + } else { + assert(data != NULL); + } + + assert(state != NULL); + + XSUM_checkResult32(XXH32(data, len, seed), Nresult); + + (void)XXH32_reset(state, seed); + (void)XXH32_update(state, data, len); + XSUM_checkResult32(XXH32_digest(state), Nresult); + + (void)XXH32_reset(state, seed); + for (pos=0; poslen; + XSUM_U64 seed = testData->seed; + XSUM_U64 Nresult = testData->Nresult; + + if (len == 0) { + data = NULL; + } else { + assert(data != NULL); + } + + assert(state != NULL); + + XSUM_checkResult64(XXH64(data, len, seed), Nresult); + + (void)XXH64_reset(state, seed); + (void)XXH64_update(state, data, len); + XSUM_checkResult64(XXH64_digest(state), Nresult); + + (void)XXH64_reset(state, seed); + for (pos=0; pos> 40); +} + +/* + * Technically, XXH3_64bits_update is identical to XXH3_128bits_update as of + * v0.8.0, but we treat them as separate. + */ +typedef XXH_errorcode (*XSUM_XXH3_update_t)(XXH3_state_t* state, const void* input, size_t length); + +/* + * Runs the passed XXH3_update variant on random lengths. This is to test the + * more complex logic of the update function, catching bugs like this one: + * https://github.com/Cyan4973/xxHash/issues/378 + */ +static void XSUM_XXH3_randomUpdate(XXH3_state_t* state, const void* data, + size_t len, XSUM_XXH3_update_t update_fn) +{ + size_t p = 0; + while (p < len) { + size_t const modulo = len > 2 ? len : 2; + size_t l = (size_t)(XSUM_rand()) % modulo; + if (p + l > len) l = len - p; + (void)update_fn(state, (const char*)data+p, l); + p += l; + } +} + +static void XSUM_testXXH3(const void* data, const XSUM_testdata64_t* testData) +{ + size_t len = testData->len; + XSUM_U64 seed = testData->seed; + XSUM_U64 Nresult = testData->Nresult; + if (len == 0) { + data = NULL; + } else { + assert(data != NULL); + } + { XSUM_U64 const Dresult = XXH3_64bits_withSeed(data, len, seed); + XSUM_checkResult64(Dresult, Nresult); + } + + /* check that the no-seed variant produces same result as seed==0 */ + if (seed == 0) { + XSUM_U64 const Dresult = XXH3_64bits(data, len); + XSUM_checkResult64(Dresult, Nresult); + } + + /* streaming API test */ + { XXH3_state_t* const state = XXH3_createState(); + assert(state != NULL); + /* single ingestion */ + (void)XXH3_64bits_reset_withSeed(state, seed); + (void)XXH3_64bits_update(state, data, len); + XSUM_checkResult64(XXH3_64bits_digest(state), Nresult); + + /* random ingestion */ + (void)XXH3_64bits_reset_withSeed(state, seed); + XSUM_XXH3_randomUpdate(state, data, len, &XXH3_64bits_update); + XSUM_checkResult64(XXH3_64bits_digest(state), Nresult); + + /* byte by byte ingestion */ + { size_t pos; + (void)XXH3_64bits_reset_withSeed(state, seed); + for (pos=0; poslen; + XSUM_U64 Nresult = testData->Nresult; + + if (len == 0) { + data = NULL; + } else { + assert(data != NULL); + } + { XSUM_U64 const Dresult = XXH3_64bits_withSecret(data, len, secret, secretSize); + XSUM_checkResult64(Dresult, Nresult); + } + + /* streaming API test */ + { XXH3_state_t *state = XXH3_createState(); + assert(state != NULL); + (void)XXH3_64bits_reset_withSecret(state, secret, secretSize); + (void)XXH3_64bits_update(state, data, len); + XSUM_checkResult64(XXH3_64bits_digest(state), Nresult); + + /* random ingestion */ + (void)XXH3_64bits_reset_withSecret(state, secret, secretSize); + XSUM_XXH3_randomUpdate(state, data, len, &XXH3_64bits_update); + XSUM_checkResult64(XXH3_64bits_digest(state), Nresult); + + /* byte by byte ingestion */ + { size_t pos; + (void)XXH3_64bits_reset_withSecret(state, secret, secretSize); + for (pos=0; poslen; + XSUM_U64 seed = testData->seed; + XXH128_hash_t const Nresult = testData->Nresult; + if (len == 0) { + data = NULL; + } else { + assert(data != NULL); + } + + { XXH128_hash_t const Dresult = XXH3_128bits_withSeed(data, len, seed); + XSUM_checkResult128(Dresult, Nresult); + } + + /* check that XXH128() is identical to XXH3_128bits_withSeed() */ + { XXH128_hash_t const Dresult2 = XXH128(data, len, seed); + XSUM_checkResult128(Dresult2, Nresult); + } + + /* check that the no-seed variant produces same result as seed==0 */ + if (seed == 0) { + XXH128_hash_t const Dresult = XXH3_128bits(data, len); + XSUM_checkResult128(Dresult, Nresult); + } + + /* streaming API test */ + { XXH3_state_t *state = XXH3_createState(); + assert(state != NULL); + + /* single ingestion */ + (void)XXH3_128bits_reset_withSeed(state, seed); + (void)XXH3_128bits_update(state, data, len); + XSUM_checkResult128(XXH3_128bits_digest(state), Nresult); + + /* random ingestion */ + (void)XXH3_128bits_reset_withSeed(state, seed); + XSUM_XXH3_randomUpdate(state, data, len, &XXH3_128bits_update); + XSUM_checkResult128(XXH3_128bits_digest(state), Nresult); + + /* byte by byte ingestion */ + { size_t pos; + (void)XXH3_128bits_reset_withSeed(state, seed); + for (pos=0; poslen; + XXH128_hash_t Nresult = testData->Nresult; + if (len == 0) { + data = NULL; + } else if (len>0) { + assert(data != NULL); + } + { XXH128_hash_t const Dresult = XXH3_128bits_withSecret(data, len, secret, secretSize); + XSUM_checkResult128(Dresult, Nresult); + } + + /* streaming API test */ + { XXH3_state_t* const state = XXH3_createState(); + assert(state != NULL); + (void)XXH3_128bits_reset_withSecret(state, secret, secretSize); + (void)XXH3_128bits_update(state, data, len); + XSUM_checkResult128(XXH3_128bits_digest(state), Nresult); + + /* random ingestion */ + (void)XXH3_128bits_reset_withSecret(state, secret, secretSize); + XSUM_XXH3_randomUpdate(state, data, len, &XXH3_128bits_update); + XSUM_checkResult128(XXH3_128bits_digest(state), Nresult); + + /* byte by byte ingestion */ + { size_t pos; + (void)XXH3_128bits_reset_withSecret(state, secret, secretSize); + for (pos=0; poslen); + for (i=0; ibyte, sizeof(testData->byte))) { + XSUM_log("\rError: Secret generation test %i: Internal sanity check failed. \n", nbTests); + XSUM_log("\rGot { 0x%02X, 0x%02X, 0x%02X, 0x%02X }, expected { 0x%02X, 0x%02X, 0x%02X, 0x%02X } \n", + samples[0], samples[1], samples[2], samples[3], + testData->byte[0], testData->byte[1], testData->byte[2], testData->byte[3] ); + exit(1); + } + nbTests++; +} + +/*! + * XSUM_sanityCheck(): + * Runs a sanity check before the benchmark. + * + * Exits on an incorrect output. + */ +XSUM_API void XSUM_sanityCheck(void) +{ + size_t i; +#define SANITY_BUFFER_SIZE 2367 + XSUM_U8 sanityBuffer[SANITY_BUFFER_SIZE]; + const void* const secret = sanityBuffer + 7; + const size_t secretSize = XXH3_SECRET_SIZE_MIN + 11; + assert(sizeof(sanityBuffer) >= 7 + secretSize); + + XSUM_fillTestBuffer(sanityBuffer, sizeof(sanityBuffer)); + + /* XXH32 */ + for (i = 0; i < (sizeof(XSUM_XXH32_testdata)/sizeof(XSUM_XXH32_testdata[0])); i++) { + XSUM_testXXH32(sanityBuffer, &XSUM_XXH32_testdata[i]); + } + /* XXH64 */ + for (i = 0; i < (sizeof(XSUM_XXH64_testdata)/sizeof(XSUM_XXH64_testdata[0])); i++) { + XSUM_testXXH64(sanityBuffer, &XSUM_XXH64_testdata[i]); + } + /* XXH3_64bits, seeded */ + for (i = 0; i < (sizeof(XSUM_XXH3_testdata)/sizeof(XSUM_XXH3_testdata[0])); i++) { + XSUM_testXXH3(sanityBuffer, &XSUM_XXH3_testdata[i]); + } + /* XXH3_64bits, custom secret */ + for (i = 0; i < (sizeof(XSUM_XXH3_withSecret_testdata)/sizeof(XSUM_XXH3_withSecret_testdata[0])); i++) { + XSUM_testXXH3_withSecret(sanityBuffer, secret, secretSize, &XSUM_XXH3_withSecret_testdata[i]); + } + /* XXH128 */ + for (i = 0; i < (sizeof(XSUM_XXH128_testdata)/sizeof(XSUM_XXH128_testdata[0])); i++) { + XSUM_testXXH128(sanityBuffer, &XSUM_XXH128_testdata[i]); + } + /* XXH128 with custom Secret */ + for (i = 0; i < (sizeof(XSUM_XXH128_withSecret_testdata)/sizeof(XSUM_XXH128_withSecret_testdata[0])); i++) { + XSUM_testXXH128_withSecret(sanityBuffer, secret, secretSize, &XSUM_XXH128_withSecret_testdata[i]); + } + /* secret generator */ + for (i = 0; i < (sizeof(XSUM_XXH3_generateSecret_testdata)/sizeof(XSUM_XXH3_generateSecret_testdata[0])); i++) { + XSUM_testSecretGenerator(sanityBuffer, &XSUM_XXH3_generateSecret_testdata[i]); + } + + XSUM_logVerbose(3, "\r%70s\r", ""); /* Clean display line */ + XSUM_logVerbose(3, "Sanity check -- all tests ok\n"); +} + +#endif /* !XSUM_NO_TESTS */ diff --git a/third_party/xxhash/cli/xsum_sanity_check.h b/third_party/xxhash/cli/xsum_sanity_check.h new file mode 100644 index 00000000000..9f3f2b85f55 --- /dev/null +++ b/third_party/xxhash/cli/xsum_sanity_check.h @@ -0,0 +1,60 @@ +/* + * xxhsum - Command line interface for xxhash algorithms + * Copyright (C) 2013-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#ifndef XSUM_SANITY_CHECK_H +#define XSUM_SANITY_CHECK_H + +#include "xsum_config.h" /* XSUM_API, XSUM_U8 */ + +#include /* size_t */ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Runs a series of self-tests. + * + * Exits if any of these tests fail, printing a message to stderr. + * + * If XSUM_NO_TESTS is defined to non-zero, this will instead print a warning + * if this is called (e.g. via xxhsum -b). + */ +XSUM_API void XSUM_sanityCheck(void); + +/* + * Fills a test buffer with pseudorandom data. + * + * This is used in the sanity check and the benchmarks - its values must not be + * changed. + */ +XSUM_API void XSUM_fillTestBuffer(XSUM_U8* buffer, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* XSUM_SANITY_CHECK_H */ diff --git a/third_party/xxhash/cmake_unofficial/.gitignore b/third_party/xxhash/cmake_unofficial/.gitignore new file mode 100644 index 00000000000..93d9fe4f6d0 --- /dev/null +++ b/third_party/xxhash/cmake_unofficial/.gitignore @@ -0,0 +1,12 @@ +# cmake artifacts + +CMakeCache.txt +CMakeFiles +Makefile +cmake_install.cmake + + +# make compilation results + +*.dylib +*.a diff --git a/third_party/xxhash/cmake_unofficial/CMakeLists.txt b/third_party/xxhash/cmake_unofficial/CMakeLists.txt new file mode 100644 index 00000000000..41c71121d7a --- /dev/null +++ b/third_party/xxhash/cmake_unofficial/CMakeLists.txt @@ -0,0 +1,173 @@ +# To the extent possible under law, the author(s) have dedicated all +# copyright and related and neighboring rights to this software to +# the public domain worldwide. This software is distributed without +# any warranty. +# +# For details, see . + +cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) + +set(XXHASH_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") + +file(STRINGS "${XXHASH_DIR}/xxhash.h" XXHASH_VERSION_MAJOR REGEX "^#define XXH_VERSION_MAJOR +([0-9]+) *$") +string(REGEX REPLACE "^#define XXH_VERSION_MAJOR +([0-9]+) *$" "\\1" XXHASH_VERSION_MAJOR "${XXHASH_VERSION_MAJOR}") +file(STRINGS "${XXHASH_DIR}/xxhash.h" XXHASH_VERSION_MINOR REGEX "^#define XXH_VERSION_MINOR +([0-9]+) *$") +string(REGEX REPLACE "^#define XXH_VERSION_MINOR +([0-9]+) *$" "\\1" XXHASH_VERSION_MINOR "${XXHASH_VERSION_MINOR}") +file(STRINGS "${XXHASH_DIR}/xxhash.h" XXHASH_VERSION_RELEASE REGEX "^#define XXH_VERSION_RELEASE +([0-9]+) *$") +string(REGEX REPLACE "^#define XXH_VERSION_RELEASE +([0-9]+) *$" "\\1" XXHASH_VERSION_RELEASE "${XXHASH_VERSION_RELEASE}") +set(XXHASH_VERSION_STRING "${XXHASH_VERSION_MAJOR}.${XXHASH_VERSION_MINOR}.${XXHASH_VERSION_RELEASE}") +set(XXHASH_LIB_VERSION ${XXHASH_VERSION_STRING}) +set(XXHASH_LIB_SOVERSION "${XXHASH_VERSION_MAJOR}") +mark_as_advanced(XXHASH_VERSION_MAJOR XXHASH_VERSION_MINOR XXHASH_VERSION_RELEASE XXHASH_VERSION_STRING XXHASH_LIB_VERSION XXHASH_LIB_SOVERSION) + +if("${CMAKE_VERSION}" VERSION_LESS "3.13") + #message(WARNING "CMake ${CMAKE_VERSION} has no CMP0077 policy: options will erase uncached/untyped normal vars!") +else() + cmake_policy (SET CMP0077 NEW) +endif() +if("${CMAKE_VERSION}" VERSION_LESS "3.0") + project(xxHash C) +else() + cmake_policy (SET CMP0048 NEW) + project(xxHash + VERSION ${XXHASH_VERSION_STRING} + LANGUAGES C) +endif() + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Project build type" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE + PROPERTY STRINGS "Debug" "Release" "RelWithDebInfo" "MinSizeRel") +endif() +if(NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "xxHash build type: ${CMAKE_BUILD_TYPE}") +endif() + +option(BUILD_SHARED_LIBS "Build shared library" ON) +option(XXHASH_BUILD_XXHSUM "Build the xxhsum binary" ON) + +# If XXHASH is being bundled in another project, we don't want to +# install anything. However, we want to let people override this, so +# we'll use the XXHASH_BUNDLED_MODE variable to let them do that; just +# set it to OFF in your project before you add_subdirectory(xxhash/cmake_unofficial). +if(NOT DEFINED XXHASH_BUNDLED_MODE) + if("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") + set(XXHASH_BUNDLED_MODE OFF) + else() + set(XXHASH_BUNDLED_MODE ON) + endif() +endif() +set(XXHASH_BUNDLED_MODE ${XXHASH_BUNDLED_MODE} CACHE BOOL "" FORCE) +mark_as_advanced(XXHASH_BUNDLED_MODE) + +# Allow people to choose whether to build shared or static libraries +# via the BUILD_SHARED_LIBS option unless we are in bundled mode, in +# which case we always use static libraries. +include(CMakeDependentOption) +CMAKE_DEPENDENT_OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON "NOT XXHASH_BUNDLED_MODE" OFF) + +# libxxhash +add_library(xxhash "${XXHASH_DIR}/xxhash.c") +add_library(${PROJECT_NAME}::xxhash ALIAS xxhash) + +target_include_directories(xxhash + PUBLIC + $ + $) +if (BUILD_SHARED_LIBS) + target_compile_definitions(xxhash PUBLIC XXH_EXPORT) +endif () +set_target_properties(xxhash PROPERTIES + SOVERSION "${XXHASH_VERSION_STRING}" + VERSION "${XXHASH_VERSION_STRING}") + +if(XXHASH_BUILD_XXHSUM) + set(XXHSUM_DIR "${XXHASH_DIR}/cli") + # xxhsum + add_executable(xxhsum "${XXHASH_DIR}/xxhsum.c" + "${XXHSUM_DIR}/xsum_os_specific.c" + "${XXHSUM_DIR}/xsum_output.c" + "${XXHSUM_DIR}/xsum_sanity_check.c" + ) + add_executable(${PROJECT_NAME}::xxhsum ALIAS xxhsum) + + target_link_libraries(xxhsum PRIVATE xxhash) + target_include_directories(xxhsum PRIVATE "${XXHASH_DIR}") +endif(XXHASH_BUILD_XXHSUM) + +# Extra warning flags +include (CheckCCompilerFlag) +if (XXHASH_C_FLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${XXHASH_C_FLAGS}") +endif() +foreach (flag + -Wall -Wextra -Wcast-qual -Wcast-align -Wshadow + -Wstrict-aliasing=1 -Wswitch-enum -Wdeclaration-after-statement + -Wstrict-prototypes -Wundef) + # Because https://gcc.gnu.org/wiki/FAQ#wnowarning + string(REGEX REPLACE "\\-Wno\\-(.+)" "-W\\1" flag_to_test "${flag}") + string(REGEX REPLACE "[^a-zA-Z0-9]+" "_" test_name "CFLAG_${flag_to_test}") + + check_c_compiler_flag("${ADD_COMPILER_FLAGS_PREPEND} ${flag_to_test}" ${test_name}) + + if(${test_name}) + set(CMAKE_C_FLAGS "${flag} ${CMAKE_C_FLAGS}") + endif() + + unset(test_name) + unset(flag_to_test) +endforeach (flag) + +if(NOT XXHASH_BUNDLED_MODE) + include(GNUInstallDirs) + + install(TARGETS xxhash + EXPORT xxHashTargets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}") + install(FILES "${XXHASH_DIR}/xxhash.h" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install(FILES "${XXHASH_DIR}/xxh3.h" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + if(XXHASH_BUILD_XXHSUM) + install(TARGETS xxhsum + EXPORT xxHashTargets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(FILES "${XXHASH_DIR}/xxhsum.1" + DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") + endif(XXHASH_BUILD_XXHSUM) + + include(CMakePackageConfigHelpers) + + set(xxHash_VERSION_CONFIG "${PROJECT_BINARY_DIR}/xxHashConfigVersion.cmake") + set(xxHash_PROJECT_CONFIG "${PROJECT_BINARY_DIR}/xxHashConfig.cmake") + set(xxHash_TARGETS_CONFIG "${PROJECT_BINARY_DIR}/xxHashTargets.cmake") + set(xxHash_CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/xxHash/") + write_basic_package_version_file(${xxHash_VERSION_CONFIG} + VERSION ${XXHASH_VERSION_STRING} + COMPATIBILITY AnyNewerVersion) + configure_package_config_file( + ${PROJECT_SOURCE_DIR}/xxHashConfig.cmake.in + ${xxHash_PROJECT_CONFIG} + INSTALL_DESTINATION ${xxHash_CONFIG_INSTALL_DIR}) + if("${CMAKE_VERSION}" VERSION_LESS "3.0") + set(XXHASH_EXPORT_SET xxhash) + if(XXHASH_BUILD_XXHSUM) + set(XXHASH_EXPORT_SET ${XXHASH_EXPORT_SET} xxhsum) + endif() + export(TARGETS ${XXHASH_EXPORT_SET} + FILE ${xxHash_TARGETS_CONFIG} + NAMESPACE ${PROJECT_NAME}::) + else() + export(EXPORT xxHashTargets + FILE ${xxHash_TARGETS_CONFIG} + NAMESPACE ${PROJECT_NAME}::) + endif() + + install(FILES ${xxHash_PROJECT_CONFIG} ${xxHash_VERSION_CONFIG} + DESTINATION ${xxHash_CONFIG_INSTALL_DIR}) + install(EXPORT xxHashTargets + DESTINATION ${xxHash_CONFIG_INSTALL_DIR} + NAMESPACE ${PROJECT_NAME}::) +endif(NOT XXHASH_BUNDLED_MODE) diff --git a/third_party/xxhash/cmake_unofficial/README.md b/third_party/xxhash/cmake_unofficial/README.md new file mode 100644 index 00000000000..66df7909a73 --- /dev/null +++ b/third_party/xxhash/cmake_unofficial/README.md @@ -0,0 +1,36 @@ + +## Usage + +### Way 1: import targets +Build xxHash targets: + + cd + mkdir build + cd build + cmake ../cmake_unofficial [options] + cmake --build . + cmake --build . --target install #optional + +Where possible options are: +- `-DXXHASH_BUILD_ENABLE_INLINE_API=`: adds xxhash.c for the `-DXXH_INLINE_ALL` api. ON by default. +- `-DXXHASH_BUILD_XXHSUM=`: build the command line binary. ON by default +- `-DBUILD_SHARED_LIBS=`: build dynamic library. ON by default. +- `-DCMAKE_INSTALL_PREFIX=`: use custom install prefix path. + +Add lines into downstream CMakeLists.txt: + + find_package(xxHash 0.7 CONFIG REQUIRED) + ... + target_link_libraries(MyTarget PRIVATE xxHash::xxhash) + +### Way 2: Add subdirectory +Add lines into downstream CMakeLists.txt: + + option(BUILD_SHARED_LIBS "Build shared libs" OFF) #optional + ... + set(XXHASH_BUILD_ENABLE_INLINE_API OFF) #optional + set(XXHASH_BUILD_XXHSUM OFF) #optional + add_subdirectory( EXCLUDE_FROM_ALL) + ... + target_link_libraries(MyTarget PRIVATE xxHash::xxhash) + diff --git a/third_party/xxhash/cmake_unofficial/xxHashConfig.cmake.in b/third_party/xxhash/cmake_unofficial/xxHashConfig.cmake.in new file mode 100644 index 00000000000..fd282bee667 --- /dev/null +++ b/third_party/xxhash/cmake_unofficial/xxHashConfig.cmake.in @@ -0,0 +1,4 @@ +@PACKAGE_INIT@ + +include(${CMAKE_CURRENT_LIST_DIR}/xxHashTargets.cmake) + diff --git a/third_party/xxhash/doc/README.md b/third_party/xxhash/doc/README.md new file mode 100644 index 00000000000..a73ad72907c --- /dev/null +++ b/third_party/xxhash/doc/README.md @@ -0,0 +1,9 @@ +xxHash Specification +======================= + +This directory contains material defining the xxHash algorithm. +It's described in [this specification document](xxhash_spec.md). + +The algorithm is also be illustrated by a [simple educational library](https://github.com/easyaspi314/xxhash-clean), +written by @easyaspi314 and designed for readability +(as opposed to the reference library which is designed for speed). diff --git a/third_party/xxhash/doc/xxhash.cry b/third_party/xxhash/doc/xxhash.cry new file mode 100644 index 00000000000..984e1c8b6b6 --- /dev/null +++ b/third_party/xxhash/doc/xxhash.cry @@ -0,0 +1,206 @@ +module xxhash where + +/** + * The 32-bit variant of xxHash. The first argument is the sequence + * of L bytes to hash. The second argument is a seed value. + */ +XXH32 : {L} (fin L) => [L][8] -> [32] -> [32] +XXH32 input seed = XXH32_avalanche acc1 + where (stripes16 # stripes4 # stripes1) = input + accR = foldl XXH32_rounds (XXH32_init seed) (split stripes16 : [L/16][16][8]) + accL = `(L % 2^^32) + if (`L:Integer) < 16 + then seed + PRIME32_5 + else XXH32_converge accR + acc4 = foldl XXH32_digest4 accL (split stripes4 : [(L%16)/4][4][8]) + acc1 = foldl XXH32_digest1 acc4 (stripes1 : [L%4][8]) + +/** + * The 64-bit variant of xxHash. The first argument is the sequence + * of L bytes to hash. The second argument is a seed value. + */ +XXH64 : {L} (fin L) => [L][8] -> [64] -> [64] +XXH64 input seed = XXH64_avalanche acc1 + where (stripes32 # stripes8 # stripes4 # stripes1) = input + accR = foldl XXH64_rounds (XXH64_init seed) (split stripes32 : [L/32][32][8]) + accL = `(L % 2^^64) + if (`L:Integer) < 32 + then seed + PRIME64_5 + else XXH64_converge accR + acc8 = foldl XXH64_digest8 accL (split stripes8 : [(L%32)/8][8][8]) + acc4 = foldl XXH64_digest4 acc8 (split stripes4 : [(L%8)/4][4][8]) + acc1 = foldl XXH64_digest1 acc4 (stripes1 : [L%4][8]) + +private + + //Utility functions + + /** + * Combines a sequence of bytes into a word using the little-endian + * convention. + */ + toLE bytes = join (reverse bytes) + + //32-bit xxHash helper functions + + //32-bit prime number constants + PRIME32_1 = 0x9E3779B1 : [32] + PRIME32_2 = 0x85EBCA77 : [32] + PRIME32_3 = 0xC2B2AE3D : [32] + PRIME32_4 = 0x27D4EB2F : [32] + PRIME32_5 = 0x165667B1 : [32] + + /** + * The property shows that the hexadecimal representation of the + * PRIME32 constants is the same as the binary representation. + */ + property PRIME32s_as_bits_correct = + (PRIME32_1 == 0b10011110001101110111100110110001) /\ + (PRIME32_2 == 0b10000101111010111100101001110111) /\ + (PRIME32_3 == 0b11000010101100101010111000111101) /\ + (PRIME32_4 == 0b00100111110101001110101100101111) /\ + (PRIME32_5 == 0b00010110010101100110011110110001) + + /** + * This function initializes the four internal accumulators of XXH32. + */ + XXH32_init : [32] -> [4][32] + XXH32_init seed = [acc1, acc2, acc3, acc4] + where acc1 = seed + PRIME32_1 + PRIME32_2 + acc2 = seed + PRIME32_2 + acc3 = seed + 0 + acc4 = seed - PRIME32_1 + + /** + * This processes a single lane of the main round function of XXH32. + */ + XXH32_round : [32] -> [32] -> [32] + XXH32_round accN laneN = ((accN + laneN * PRIME32_2) <<< 13) * PRIME32_1 + + /** + * This is the main round function of XXH32 and processes a stripe, + * i.e. 4 lanes with 4 bytes each. + */ + XXH32_rounds : [4][32] -> [16][8] -> [4][32] + XXH32_rounds accs stripe = + [ XXH32_round accN (toLE laneN) | accN <- accs | laneN <- split stripe ] + + /** + * This function combines the four lane accumulators into a single + * 32-bit value. + */ + XXH32_converge : [4][32] -> [32] + XXH32_converge [acc1, acc2, acc3, acc4] = + (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18) + + /** + * This function digests a four byte lane + */ + XXH32_digest4 : [32] -> [4][8] -> [32] + XXH32_digest4 acc lane = ((acc + toLE lane * PRIME32_3) <<< 17) * PRIME32_4 + + /** + * This function digests a single byte lane + */ + XXH32_digest1 : [32] -> [8] -> [32] + XXH32_digest1 acc lane = ((acc + (0 # lane) * PRIME32_5) <<< 11) * PRIME32_1 + + /** + * This function ensures that all input bits have a chance to impact + * any bit in the output digest, resulting in an unbiased + * distribution. + */ + XXH32_avalanche : [32] -> [32] + XXH32_avalanche acc0 = acc5 + where acc1 = acc0 ^ (acc0 >> 15) + acc2 = acc1 * PRIME32_2 + acc3 = acc2 ^ (acc2 >> 13) + acc4 = acc3 * PRIME32_3 + acc5 = acc4 ^ (acc4 >> 16) + + //64-bit xxHash helper functions + + //64-bit prime number constants + PRIME64_1 = 0x9E3779B185EBCA87 : [64] + PRIME64_2 = 0xC2B2AE3D27D4EB4F : [64] + PRIME64_3 = 0x165667B19E3779F9 : [64] + PRIME64_4 = 0x85EBCA77C2B2AE63 : [64] + PRIME64_5 = 0x27D4EB2F165667C5 : [64] + + /** + * The property shows that the hexadecimal representation of the + * PRIME64 constants is the same as the binary representation. + */ + property PRIME64s_as_bits_correct = + (PRIME64_1 == 0b1001111000110111011110011011000110000101111010111100101010000111) /\ + (PRIME64_2 == 0b1100001010110010101011100011110100100111110101001110101101001111) /\ + (PRIME64_3 == 0b0001011001010110011001111011000110011110001101110111100111111001) /\ + (PRIME64_4 == 0b1000010111101011110010100111011111000010101100101010111001100011) /\ + (PRIME64_5 == 0b0010011111010100111010110010111100010110010101100110011111000101) + + /** + * This function initializes the four internal accumulators of XXH64. + */ + XXH64_init : [64] -> [4][64] + XXH64_init seed = [acc1, acc2, acc3, acc4] + where acc1 = seed + PRIME64_1 + PRIME64_2 + acc2 = seed + PRIME64_2 + acc3 = seed + 0 + acc4 = seed - PRIME64_1 + + /** + * This processes a single lane of the main round function of XXH64. + */ + XXH64_round : [64] -> [64] -> [64] + XXH64_round accN laneN = ((accN + laneN * PRIME64_2) <<< 31) * PRIME64_1 + + /** + * This is the main round function of XXH64 and processes a stripe, + * i.e. 4 lanes with 8 bytes each. + */ + XXH64_rounds : [4][64] -> [32][8] -> [4][64] + XXH64_rounds accs stripe = + [ XXH64_round accN (toLE laneN) | accN <- accs | laneN <- split stripe ] + + /** + * This is a helper function, used to merge the four lane accumulators. + */ + mergeAccumulator : [64] -> [64] -> [64] + mergeAccumulator acc accN = (acc ^ XXH64_round 0 accN) * PRIME64_1 + PRIME64_4 + + /** + * This function combines the four lane accumulators into a single + * 64-bit value. + */ + XXH64_converge : [4][64] -> [64] + XXH64_converge [acc1, acc2, acc3, acc4] = + foldl mergeAccumulator ((acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18)) [acc1, acc2, acc3, acc4] + + /** + * This function digests an eight byte lane + */ + XXH64_digest8 : [64] -> [8][8] -> [64] + XXH64_digest8 acc lane = ((acc ^ XXH64_round 0 (toLE lane)) <<< 27) * PRIME64_1 + PRIME64_4 + + /** + * This function digests a four byte lane + */ + XXH64_digest4 : [64] -> [4][8] -> [64] + XXH64_digest4 acc lane = ((acc ^ (0 # toLE lane) * PRIME64_1) <<< 23) * PRIME64_2 + PRIME64_3 + + /** + * This function digests a single byte lane + */ + XXH64_digest1 : [64] -> [8] -> [64] + XXH64_digest1 acc lane = ((acc ^ (0 # lane) * PRIME64_5) <<< 11) * PRIME64_1 + + /** + * This function ensures that all input bits have a chance to impact + * any bit in the output digest, resulting in an unbiased + * distribution. + */ + XXH64_avalanche : [64] -> [64] + XXH64_avalanche acc0 = acc5 + where acc1 = acc0 ^ (acc0 >> 33) + acc2 = acc1 * PRIME64_2 + acc3 = acc2 ^ (acc2 >> 29) + acc4 = acc3 * PRIME64_3 + acc5 = acc4 ^ (acc4 >> 32) diff --git a/third_party/xxhash/doc/xxhash_spec.md b/third_party/xxhash/doc/xxhash_spec.md new file mode 100644 index 00000000000..af7ba90d9d0 --- /dev/null +++ b/third_party/xxhash/doc/xxhash_spec.md @@ -0,0 +1,317 @@ +xxHash fast digest algorithm +====================== + +### Notices + +Copyright (c) Yann Collet + +Permission is granted to copy and distribute this document +for any purpose and without charge, +including translations into other languages +and incorporation into compilations, +provided that the copyright notice and this notice are preserved, +and that any substantive changes or deletions from the original +are clearly marked. +Distribution of this document is unlimited. + +### Version + +0.1.1 (10/10/18) + + +Table of Contents +--------------------- +- [Introduction](#introduction) +- [XXH32 algorithm description](#xxh32-algorithm-description) +- [XXH64 algorithm description](#xxh64-algorithm-description) +- [Performance considerations](#performance-considerations) +- [Reference Implementation](#reference-implementation) + + +Introduction +---------------- + +This document describes the xxHash digest algorithm for both 32-bit and 64-bit variants, named `XXH32` and `XXH64`. The algorithm takes an input a message of arbitrary length and an optional seed value, then produces an output of 32 or 64-bit as "fingerprint" or "digest". + +xxHash is primarily designed for speed. It is labeled non-cryptographic, and is not meant to avoid intentional collisions (same digest for 2 different messages), or to prevent producing a message with a predefined digest. + +XXH32 is designed to be fast on 32-bit machines. +XXH64 is designed to be fast on 64-bit machines. +Both variants produce different output. +However, a given variant shall produce exactly the same output, irrespective of the cpu / os used. In particular, the result remains identical whatever the endianness and width of the cpu is. + +### Operation notations + +All operations are performed modulo {32,64} bits. Arithmetic overflows are expected. +`XXH32` uses 32-bit modular operations. `XXH64` uses 64-bit modular operations. + +- `+`: denotes modular addition +- `*`: denotes modular multiplication +- `X <<< s`: denotes the value obtained by circularly shifting (rotating) `X` left by `s` bit positions. +- `X >> s`: denotes the value obtained by shifting `X` right by s bit positions. Upper `s` bits become `0`. +- `X xor Y`: denotes the bit-wise XOR of `X` and `Y` (same width). + + +XXH32 Algorithm Description +------------------------------------- + +### Overview + +We begin by supposing that we have a message of any length `L` as input, and that we wish to find its digest. Here `L` is an arbitrary nonnegative integer; `L` may be zero. The following steps are performed to compute the digest of the message. + +The algorithm collect and transform input in _stripes_ of 16 bytes. The transforms are stored inside 4 "accumulators", each one storing an unsigned 32-bit value. Each accumulator can be processed independently in parallel, speeding up processing for cpu with multiple execution units. + +The algorithm uses 32-bits addition, multiplication, rotate, shift and xor operations. Many operations require some 32-bits prime number constants, all defined below: + + static const u32 PRIME32_1 = 0x9E3779B1U; // 0b10011110001101110111100110110001 + static const u32 PRIME32_2 = 0x85EBCA77U; // 0b10000101111010111100101001110111 + static const u32 PRIME32_3 = 0xC2B2AE3DU; // 0b11000010101100101010111000111101 + static const u32 PRIME32_4 = 0x27D4EB2FU; // 0b00100111110101001110101100101111 + static const u32 PRIME32_5 = 0x165667B1U; // 0b00010110010101100110011110110001 + +These constants are prime numbers, and feature a good mix of bits 1 and 0, neither too regular, nor too dissymmetric. These properties help dispersion capabilities. + +### Step 1. Initialize internal accumulators + +Each accumulator gets an initial value based on optional `seed` input. Since the `seed` is optional, it can be `0`. + + u32 acc1 = seed + PRIME32_1 + PRIME32_2; + u32 acc2 = seed + PRIME32_2; + u32 acc3 = seed + 0; + u32 acc4 = seed - PRIME32_1; + +#### Special case: input is less than 16 bytes + +When the input is too small (< 16 bytes), the algorithm will not process any stripes. Consequently, it will not make use of parallel accumulators. + +In this case, a simplified initialization is performed, using a single accumulator: + + u32 acc = seed + PRIME32_5; + +The algorithm then proceeds directly to step 4. + +### Step 2. Process stripes + +A stripe is a contiguous segment of 16 bytes. +It is evenly divided into 4 _lanes_, of 4 bytes each. +The first lane is used to update accumulator 1, the second lane is used to update accumulator 2, and so on. + +Each lane read its associated 32-bit value using __little-endian__ convention. + +For each {lane, accumulator}, the update process is called a _round_, and applies the following formula: + + accN = accN + (laneN * PRIME32_2); + accN = accN <<< 13; + accN = accN * PRIME32_1; + +This shuffles the bits so that any bit from input _lane_ impacts several bits in output _accumulator_. All operations are performed modulo 2^32. + +Input is consumed one full stripe at a time. Step 2 is looped as many times as necessary to consume the whole input, except for the last remaining bytes which cannot form a stripe (< 16 bytes). +When that happens, move to step 3. + +### Step 3. Accumulator convergence + +All 4 lane accumulators from the previous steps are merged to produce a single remaining accumulator of the same width (32-bit). The associated formula is as follows: + + acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18); + +### Step 4. Add input length + +The input total length is presumed known at this stage. This step is just about adding the length to accumulator, so that it participates to final mixing. + + acc = acc + (u32)inputLength; + +Note that, if input length is so large that it requires more than 32-bits, only the lower 32-bits are added to the accumulator. + +### Step 5. Consume remaining input + +There may be up to 15 bytes remaining to consume from the input. +The final stage will digest them according to following pseudo-code: + + while (remainingLength >= 4) { + lane = read_32bit_little_endian(input_ptr); + acc = acc + lane * PRIME32_3; + acc = (acc <<< 17) * PRIME32_4; + input_ptr += 4; remainingLength -= 4; + } + + while (remainingLength >= 1) { + lane = read_byte(input_ptr); + acc = acc + lane * PRIME32_5; + acc = (acc <<< 11) * PRIME32_1; + input_ptr += 1; remainingLength -= 1; + } + +This process ensures that all input bytes are present in the final mix. + +### Step 6. Final mix (avalanche) + +The final mix ensures that all input bits have a chance to impact any bit in the output digest, resulting in an unbiased distribution. This is also called avalanche effect. + + acc = acc xor (acc >> 15); + acc = acc * PRIME32_2; + acc = acc xor (acc >> 13); + acc = acc * PRIME32_3; + acc = acc xor (acc >> 16); + +### Step 7. Output + +The `XXH32()` function produces an unsigned 32-bit value as output. + +For systems which require to store and/or display the result in binary or hexadecimal format, the canonical format is defined to reproduce the same value as the natural decimal format, hence follows __big-endian__ convention (most significant byte first). + + +XXH64 Algorithm Description +------------------------------------- + +### Overview + +`XXH64`'s algorithm structure is very similar to `XXH32` one. The major difference is that `XXH64` uses 64-bit arithmetic, speeding up memory transfer for 64-bit compliant systems, but also relying on cpu capability to efficiently perform 64-bit operations. + +The algorithm collects and transforms input in _stripes_ of 32 bytes. The transforms are stored inside 4 "accumulators", each one storing an unsigned 64-bit value. Each accumulator can be processed independently in parallel, speeding up processing for cpu with multiple execution units. + +The algorithm uses 64-bit addition, multiplication, rotate, shift and xor operations. Many operations require some 64-bit prime number constants, all defined below: + + static const u64 PRIME64_1 = 0x9E3779B185EBCA87ULL; // 0b1001111000110111011110011011000110000101111010111100101010000111 + static const u64 PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; // 0b1100001010110010101011100011110100100111110101001110101101001111 + static const u64 PRIME64_3 = 0x165667B19E3779F9ULL; // 0b0001011001010110011001111011000110011110001101110111100111111001 + static const u64 PRIME64_4 = 0x85EBCA77C2B2AE63ULL; // 0b1000010111101011110010100111011111000010101100101010111001100011 + static const u64 PRIME64_5 = 0x27D4EB2F165667C5ULL; // 0b0010011111010100111010110010111100010110010101100110011111000101 + +These constants are prime numbers, and feature a good mix of bits 1 and 0, neither too regular, nor too dissymmetric. These properties help dispersion capabilities. + +### Step 1. Initialise internal accumulators + +Each accumulator gets an initial value based on optional `seed` input. Since the `seed` is optional, it can be `0`. + + u64 acc1 = seed + PRIME64_1 + PRIME64_2; + u64 acc2 = seed + PRIME64_2; + u64 acc3 = seed + 0; + u64 acc4 = seed - PRIME64_1; + +#### Special case: input is less than 32 bytes + +When the input is too small (< 32 bytes), the algorithm will not process any stripes. Consequently, it will not make use of parallel accumulators. + +In this case, a simplified initialization is performed, using a single accumulator: + + u64 acc = seed + PRIME64_5; + +The algorithm then proceeds directly to step 4. + +### Step 2. Process stripes + +A stripe is a contiguous segment of 32 bytes. +It is evenly divided into 4 _lanes_, of 8 bytes each. +The first lane is used to update accumulator 1, the second lane is used to update accumulator 2, and so on. + +Each lane read its associated 64-bit value using __little-endian__ convention. + +For each {lane, accumulator}, the update process is called a _round_, and applies the following formula: + + round(accN,laneN): + accN = accN + (laneN * PRIME64_2); + accN = accN <<< 31; + return accN * PRIME64_1; + +This shuffles the bits so that any bit from input _lane_ impacts several bits in output _accumulator_. All operations are performed modulo 2^64. + +Input is consumed one full stripe at a time. Step 2 is looped as many times as necessary to consume the whole input, except for the last remaining bytes which cannot form a stripe (< 32 bytes). +When that happens, move to step 3. + +### Step 3. Accumulator convergence + +All 4 lane accumulators from previous steps are merged to produce a single remaining accumulator of same width (64-bit). The associated formula is as follows. + +Note that accumulator convergence is more complex than 32-bit variant, and requires to define another function called _mergeAccumulator()_: + + mergeAccumulator(acc,accN): + acc = acc xor round(0, accN); + acc = acc * PRIME64_1; + return acc + PRIME64_4; + +which is then used in the convergence formula: + + acc = (acc1 <<< 1) + (acc2 <<< 7) + (acc3 <<< 12) + (acc4 <<< 18); + acc = mergeAccumulator(acc, acc1); + acc = mergeAccumulator(acc, acc2); + acc = mergeAccumulator(acc, acc3); + acc = mergeAccumulator(acc, acc4); + +### Step 4. Add input length + +The input total length is presumed known at this stage. This step is just about adding the length to accumulator, so that it participates to final mixing. + + acc = acc + inputLength; + +### Step 5. Consume remaining input + +There may be up to 31 bytes remaining to consume from the input. +The final stage will digest them according to following pseudo-code: + + while (remainingLength >= 8) { + lane = read_64bit_little_endian(input_ptr); + acc = acc xor round(0, lane); + acc = (acc <<< 27) * PRIME64_1; + acc = acc + PRIME64_4; + input_ptr += 8; remainingLength -= 8; + } + + if (remainingLength >= 4) { + lane = read_32bit_little_endian(input_ptr); + acc = acc xor (lane * PRIME64_1); + acc = (acc <<< 23) * PRIME64_2; + acc = acc + PRIME64_3; + input_ptr += 4; remainingLength -= 4; + } + + while (remainingLength >= 1) { + lane = read_byte(input_ptr); + acc = acc xor (lane * PRIME64_5); + acc = (acc <<< 11) * PRIME64_1; + input_ptr += 1; remainingLength -= 1; + } + +This process ensures that all input bytes are present in the final mix. + +### Step 6. Final mix (avalanche) + +The final mix ensures that all input bits have a chance to impact any bit in the output digest, resulting in an unbiased distribution. This is also called avalanche effect. + + acc = acc xor (acc >> 33); + acc = acc * PRIME64_2; + acc = acc xor (acc >> 29); + acc = acc * PRIME64_3; + acc = acc xor (acc >> 32); + +### Step 7. Output + +The `XXH64()` function produces an unsigned 64-bit value as output. + +For systems which require to store and/or display the result in binary or hexadecimal format, the canonical format is defined to reproduce the same value as the natural decimal format, hence follows __big-endian__ convention (most significant byte first). + +Performance considerations +---------------------------------- + +The xxHash algorithms are simple and compact to implement. They provide a system independent "fingerprint" or digest of a message of arbitrary length. + +The algorithm allows input to be streamed and processed in multiple steps. In such case, an internal buffer is needed to ensure data is presented to the algorithm in full stripes. + +On 64-bit systems, the 64-bit variant `XXH64` is generally faster to compute, so it is a recommended variant, even when only 32-bit are needed. + +On 32-bit systems though, positions are reversed: `XXH64` performance is reduced, due to its usage of 64-bit arithmetic. `XXH32` becomes a faster variant. + + +Reference Implementation +---------------------------------------- + +A reference library written in C is available at https://www.xxhash.com. +The web page also links to multiple other implementations written in many different languages. +It links to the [github project page](https://github.com/Cyan4973/xxHash) where an [issue board](https://github.com/Cyan4973/xxHash/issues) can be used for further public discussions on the topic. + + +Version changes +-------------------- +v0.7.3: Minor fixes +v0.1.1: added a note on rationale for selection of constants +v0.1.0: initial release diff --git a/third_party/xxhash/libxxhash.pc.in b/third_party/xxhash/libxxhash.pc.in new file mode 100644 index 00000000000..28c16448567 --- /dev/null +++ b/third_party/xxhash/libxxhash.pc.in @@ -0,0 +1,15 @@ +# xxHash - Extremely fast hash algorithm +# Copyright (C) 2012-2020, Yann Collet, Facebook +# BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + +prefix=@PREFIX@ +exec_prefix=@EXECPREFIX@ +includedir=${prefix}/@INCLUDEDIR@ +libdir=${exec_prefix}/@LIBDIR@ + +Name: xxhash +Description: extremely fast hash algorithm +URL: http://www.xxhash.com/ +Version: @VERSION@ +Libs: -L${libdir} -lxxhash +Cflags: -I${includedir} diff --git a/third_party/xxhash/tests/Makefile b/third_party/xxhash/tests/Makefile new file mode 100644 index 00000000000..092711adb86 --- /dev/null +++ b/third_party/xxhash/tests/Makefile @@ -0,0 +1,83 @@ +CFLAGS += -Wall -Wextra -Wundef -g + +NM = nm +GREP = grep + +# Define *.exe as extension for Windows systems +ifneq (,$(filter Windows%,$(OS))) +EXT =.exe +else +EXT = +endif + +ifneq (,$(filter %UTF-8,$(LANG))) +ENABLE_UNICODE ?= 1 +else +ENABLE_UNICODE ?= 0 +endif + +.PHONY: default +default: all + +.PHONY: all +all: test + +.PHONY: test +test: test_multiInclude test_unicode + +.PHONY: test_multiInclude +test_multiInclude: + @$(MAKE) clean + # compile without xxhash.o, ensure symbols exist within target + # Note: built using only default rules + $(MAKE) multiInclude + @$(MAKE) clean + # compile with xxhash.o, to detect duplicated symbols + $(MAKE) multiInclude_withxxhash + @$(MAKE) clean + # Note: XXH_INLINE_ALL with XXH_NAMESPACE is currently disabled + # compile with XXH_NAMESPACE + # CPPFLAGS=-DXXH_NAMESPACE=TESTN_ $(MAKE) multiInclude_withxxhash + # no symbol prefixed TESTN_ should exist + # ! $(NM) multiInclude_withxxhash | $(GREP) TESTN_ + #$(MAKE) clean + # compile with XXH_NAMESPACE and without xxhash.o + # CPPFLAGS=-DXXH_NAMESPACE=TESTN_ $(MAKE) multiInclude + # no symbol prefixed TESTN_ should exist + # ! $(NM) multiInclude | $(GREP) TESTN_ + #@$(MAKE) clean + +.PHONY: test_ppc_redefine +test_ppc_redefine: ppc_define.c + @$(MAKE) clean + $(CC) $(CPPFLAGS) $(CFLAGS) -c $^ + +xxhsum$(EXT): ../xxhash.c ../xxhash.h ../xxhsum.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -DXXH_INLINE_ALL ../xxhsum.c -o $@ + +# Make sure that Unicode filenames work. +# https://github.com/Cyan4973/xxHash/issues/293 +.PHONY: test_unicode +ifeq (0,$(ENABLE_UNICODE)) +test_unicode: + @echo "Skipping Unicode test, your terminal doesn't appear to support UTF-8." + @echo "Try with ENABLE_UNICODE=1" +else +test_unicode: xxhsum$(EXT) generate_unicode_test.c + # Generate a Unicode filename test dynamically + # to keep UTF-8 out of the source tree. + $(CC) $(CFLAGS) $(LDFLAGS) generate_unicode_test.c -o generate_unicode_test$(EXT) + ./generate_unicode_test$(EXT) + $(SHELL) ./unicode_test.sh +endif + +xxhash.o: ../xxhash.c ../xxhash.h + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -c -o $@ $< + +multiInclude_withxxhash: multiInclude.o xxhash.o + $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $^ + +clean: + @$(RM) *.o + @$(RM) multiInclude multiInclude_withxxhash + @$(RM) *.unicode generate_unicode_test$(EXT) unicode_test.* xxhsum$(EXT) diff --git a/third_party/xxhash/tests/bench/.clang_complete b/third_party/xxhash/tests/bench/.clang_complete new file mode 100644 index 00000000000..87dff6b82cb --- /dev/null +++ b/third_party/xxhash/tests/bench/.clang_complete @@ -0,0 +1 @@ +-I../.. diff --git a/third_party/xxhash/tests/bench/.gitignore b/third_party/xxhash/tests/bench/.gitignore new file mode 100644 index 00000000000..ede2d5880f6 --- /dev/null +++ b/third_party/xxhash/tests/bench/.gitignore @@ -0,0 +1,11 @@ +# build artifacts + +*.o +benchHash +benchHash32 +benchHash_avx2 +benchHash_hw + +# test files + +test* diff --git a/third_party/xxhash/tests/bench/LICENSE b/third_party/xxhash/tests/bench/LICENSE new file mode 100644 index 00000000000..d159169d105 --- /dev/null +++ b/third_party/xxhash/tests/bench/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/third_party/xxhash/tests/bench/Makefile b/third_party/xxhash/tests/bench/Makefile new file mode 100644 index 00000000000..cdccfffd65b --- /dev/null +++ b/third_party/xxhash/tests/bench/Makefile @@ -0,0 +1,67 @@ +# ################################################################ +# xxHash benchHash Makefile +# Copyright (C) 2019-2020 Yann Collet +# +# GPL v2 License +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# You can contact the author at: +# - xxHash homepage: https://www.xxhash.com +# - xxHash source repository: https://github.com/Cyan4973/xxHash +# ################################################################ +# benchHash: A generic benchmark for hash algorithms +# measuring throughput, latency and bandwidth +# ################################################################ + + +CPPFLAGS += -I../.. # directory of xxHash source files +CFLAGS ?= -O3 +CFLAGS += -std=c99 -Wall -Wextra -Wstrict-aliasing=1 +CFLAGS += $(MOREFLAGS) # custom way to add flags +CXXFLAGS ?= -O3 +LDFLAGS += $(MOREFLAGS) + + +OBJ_LIST = main.o bhDisplay.o benchHash.o benchfn.o timefn.o + + +default: benchHash + +all: benchHash + +benchHash32: CFLAGS += -m32 +benchHash32: CXXFLAGS += -m32 + +benchHash_avx2: CFLAGS += -mavx2 +benchHash_avx2: CXXFLAGS += -mavx2 + +benchHash_hw: CPPFLAGS += -DHARDWARE_SUPPORT +benchHash_hw: CFLAGS += -mavx2 -maes +benchHash_hw: CXXFLAGS += -mavx2 -mpclmul -std=c++14 + +benchHash benchHash32 benchHash_avx2 benchHash_nosimd benchHash_hw: $(OBJ_LIST) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ $(LDFLAGS) -o $@ + + +main.o: bhDisplay.h hashes.h + +bhDisplay.o: bhDisplay.h benchHash.h + +benchHash.o: benchHash.h + + +clean: + $(RM) *.o benchHash benchHash32 benchHash_avx2 benchHash_hw diff --git a/third_party/xxhash/tests/bench/benchHash.c b/third_party/xxhash/tests/bench/benchHash.c new file mode 100644 index 00000000000..05739c7b5cd --- /dev/null +++ b/third_party/xxhash/tests/bench/benchHash.c @@ -0,0 +1,164 @@ +/* +* Hash benchmark module +* Part of the xxHash project +* Copyright (C) 2019-2020 Yann Collet +* +* GPL v2 License +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* You can contact the author at: +* - xxHash homepage: https://www.xxhash.com +* - xxHash source repository: https://github.com/Cyan4973/xxHash +*/ + +/* benchmark hash functions */ + +#include // malloc +#include + +#include "benchHash.h" + + +static void initBuffer(void* buffer, size_t size) +{ + const unsigned long long k1 = 11400714785074694791ULL; /* 0b1001111000110111011110011011000110000101111010111100101010000111 */ + const unsigned long long k2 = 14029467366897019727ULL; /* 0b1100001010110010101011100011110100100111110101001110101101001111 */ + unsigned long long acc = k2; + unsigned char* const p = (unsigned char*)buffer; + for (size_t s = 0; s < size; s++) { + acc *= k1; + p[s] = (unsigned char)(acc >> 56); + } +} + + +#define MARGIN_FOR_LATENCY 1024 +#define START_MASK (MARGIN_FOR_LATENCY-1) + +typedef size_t (*sizeFunction_f)(size_t targetSize); + +/* + * bench_hash_internal(): + * Benchmarks hashfn repeateadly over single input of size `size` + * return: nb of hashes per second + */ +static double +bench_hash_internal(BMK_benchFn_t hashfn, void* payload, + size_t nbBlocks, sizeFunction_f selectSize, size_t size, + unsigned total_time_ms, unsigned iter_time_ms) +{ + BMK_timedFnState_shell shell; + BMK_timedFnState_t* const txf = BMK_initStatic_timedFnState(&shell, sizeof(shell), total_time_ms, iter_time_ms); + assert(txf != NULL); + + size_t const srcSize = (size_t)size; + size_t const srcBufferSize = srcSize + MARGIN_FOR_LATENCY; + void* const srcBuffer = malloc(srcBufferSize); + assert(srcBuffer != NULL); + initBuffer(srcBuffer, srcBufferSize); + #define FAKE_DSTSIZE 32 + size_t const dstSize = FAKE_DSTSIZE; + char dstBuffer_static[FAKE_DSTSIZE] = {0}; + + #define NB_BLOCKS_MAX 1024 + const void* srcBuffers[NB_BLOCKS_MAX]; + size_t srcSizes[NB_BLOCKS_MAX]; + void* dstBuffers[NB_BLOCKS_MAX]; + size_t dstCapacities[NB_BLOCKS_MAX]; + assert(nbBlocks < NB_BLOCKS_MAX); + + assert(size > 0); + for (size_t n=0; n < nbBlocks; n++) { + srcBuffers[n] = srcBuffer; + srcSizes[n] = selectSize(size); + dstBuffers[n] = dstBuffer_static; + dstCapacities[n] = dstSize; + } + + + BMK_benchParams_t params = { + .benchFn = hashfn, + .benchPayload = payload, + .initFn = NULL, + .initPayload = NULL, + .errorFn = NULL, + .blockCount = nbBlocks, + .srcBuffers = srcBuffers, + .srcSizes = srcSizes, + .dstBuffers = dstBuffers, + .dstCapacities = dstCapacities, + .blockResults = NULL + }; + BMK_runOutcome_t result; + + while (!BMK_isCompleted_TimedFn(txf)) { + result = BMK_benchTimedFn(txf, params); + assert(BMK_isSuccessful_runOutcome(result)); + } + + BMK_runTime_t const runTime = BMK_extract_runTime(result); + + free(srcBuffer); + assert(runTime.nanoSecPerRun != 0); + return (1000000000U / runTime.nanoSecPerRun) * nbBlocks; + +} + + +static size_t rand_1_N(size_t N) { return ((size_t)rand() % N) + 1; } + +static size_t identity(size_t s) { return s; } + +static size_t +benchLatency(const void* src, size_t srcSize, + void* dst, size_t dstCapacity, + void* customPayload) +{ + (void)dst; (void)dstCapacity; + BMK_benchFn_t benchfn = (BMK_benchFn_t)customPayload; + static size_t hash = 0; + + const void* const start = (const char*)src + (hash & START_MASK); + + return hash = benchfn(start, srcSize, dst, dstCapacity, NULL); +} + + + +#ifndef SIZE_TO_HASH_PER_ROUND +# define SIZE_TO_HASH_PER_ROUND 200000 +#endif + +#ifndef NB_HASH_ROUNDS_MAX +# define NB_HASH_ROUNDS_MAX 1000 +#endif + +double bench_hash(BMK_benchFn_t hashfn, + BMK_benchMode benchMode, + size_t size, BMK_sizeMode sizeMode, + unsigned total_time_ms, unsigned iter_time_ms) +{ + sizeFunction_f const sizef = (sizeMode == BMK_fixedSize) ? identity : rand_1_N; + BMK_benchFn_t const benchfn = (benchMode == BMK_throughput) ? hashfn : benchLatency; + BMK_benchFn_t const payload = (benchMode == BMK_throughput) ? NULL : hashfn; + + size_t nbBlocks = (SIZE_TO_HASH_PER_ROUND / size) + 1; + if (nbBlocks > NB_HASH_ROUNDS_MAX) nbBlocks = NB_HASH_ROUNDS_MAX; + + return bench_hash_internal(benchfn, payload, + nbBlocks, sizef, size, + total_time_ms, iter_time_ms); +} diff --git a/third_party/xxhash/tests/bench/benchHash.h b/third_party/xxhash/tests/bench/benchHash.h new file mode 100644 index 00000000000..6c9ba910473 --- /dev/null +++ b/third_party/xxhash/tests/bench/benchHash.h @@ -0,0 +1,67 @@ +/* +* Hash benchmark module +* Part of the xxHash project +* Copyright (C) 2019-2020 Yann Collet +* +* GPL v2 License +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* You can contact the author at: +* - xxHash homepage: https://www.xxhash.com +* - xxHash source repository: https://github.com/Cyan4973/xxHash +*/ + + +#ifndef BENCH_HASH_H_983426678 +#define BENCH_HASH_H_983426678 + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* === Dependencies === */ + +#include "benchfn.h" /* BMK_benchFn_t */ + + +/* === Declarations === */ + +typedef enum { BMK_throughput, BMK_latency } BMK_benchMode; + +typedef enum { BMK_fixedSize, /* hash always `size` bytes */ + BMK_randomSize, /* hash a random nb of bytes, between 1 and `size` (inclusive) */ +} BMK_sizeMode; + +/* + * bench_hash(): + * Returns speed expressed as nb hashes per second. + * total_time_ms: time spent benchmarking the hash function with given parameters + * iter_time_ms: time spent for one round. If multiple rounds are run, + * bench_hash() will report the speed of best round. + */ +double bench_hash(BMK_benchFn_t hashfn, + BMK_benchMode benchMode, + size_t size, BMK_sizeMode sizeMode, + unsigned total_time_ms, unsigned iter_time_ms); + + + +#if defined (__cplusplus) +} +#endif + +#endif /* BENCH_HASH_H_983426678 */ diff --git a/third_party/xxhash/tests/bench/benchfn.c b/third_party/xxhash/tests/bench/benchfn.c new file mode 100644 index 00000000000..ec7e9a25d0e --- /dev/null +++ b/third_party/xxhash/tests/bench/benchfn.c @@ -0,0 +1,252 @@ +/* + * Copyright (C) 2016-2020 Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + + +/* ************************************* +* Includes +***************************************/ +#include /* malloc, free */ +#include /* memset */ +#undef NDEBUG /* assert must not be disabled */ +#include /* assert */ + +#include "timefn.h" /* UTIL_time_t, UTIL_getTime */ +#include "benchfn.h" + + +/* ************************************* +* Constants +***************************************/ +#define TIMELOOP_MICROSEC SEC_TO_MICRO /* 1 second */ +#define TIMELOOP_NANOSEC (1*1000000000ULL) /* 1 second */ + +#define KB *(1 <<10) +#define MB *(1 <<20) +#define GB *(1U<<30) + + +/* ************************************* +* Debug errors +***************************************/ +#if defined(DEBUG) && (DEBUG >= 1) +# include /* fprintf */ +# define DISPLAY(...) fprintf(stderr, __VA_ARGS__) +# define DEBUGOUTPUT(...) { if (DEBUG) DISPLAY(__VA_ARGS__); } +#else +# define DEBUGOUTPUT(...) +#endif + + +/* error without displaying */ +#define RETURN_QUIET_ERROR(retValue, ...) { \ + DEBUGOUTPUT("%s: %i: \n", __FILE__, __LINE__); \ + DEBUGOUTPUT("Error : "); \ + DEBUGOUTPUT(__VA_ARGS__); \ + DEBUGOUTPUT(" \n"); \ + return retValue; \ +} + + +/* ************************************* +* Benchmarking an arbitrary function +***************************************/ + +int BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome) +{ + return outcome.error_tag_never_ever_use_directly == 0; +} + +/* warning : this function will stop program execution if outcome is invalid ! + * check outcome validity first, using BMK_isValid_runResult() */ +BMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome) +{ + assert(outcome.error_tag_never_ever_use_directly == 0); + return outcome.internal_never_ever_use_directly; +} + +size_t BMK_extract_errorResult(BMK_runOutcome_t outcome) +{ + assert(outcome.error_tag_never_ever_use_directly != 0); + return outcome.error_result_never_ever_use_directly; +} + +static BMK_runOutcome_t BMK_runOutcome_error(size_t errorResult) +{ + BMK_runOutcome_t b; + memset(&b, 0, sizeof(b)); + b.error_tag_never_ever_use_directly = 1; + b.error_result_never_ever_use_directly = errorResult; + return b; +} + +static BMK_runOutcome_t BMK_setValid_runTime(BMK_runTime_t runTime) +{ + BMK_runOutcome_t outcome; + outcome.error_tag_never_ever_use_directly = 0; + outcome.internal_never_ever_use_directly = runTime; + return outcome; +} + + +/* initFn will be measured once, benchFn will be measured `nbLoops` times */ +/* initFn is optional, provide NULL if none */ +/* benchFn must return a size_t value that errorFn can interpret */ +/* takes # of blocks and list of size & stuff for each. */ +/* can report result of benchFn for each block into blockResult. */ +/* blockResult is optional, provide NULL if this information is not required */ +/* note : time per loop can be reported as zero if run time < timer resolution */ +BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t p, + unsigned nbLoops) +{ + /* init */ + { size_t i; + for (i = 0; i < p.blockCount; i++) { + memset(p.dstBuffers[i], 0xE5, p.dstCapacities[i]); /* warm up and erase result buffer */ + } } + + /* benchmark */ + { UTIL_time_t const clockStart = UTIL_getTime(); + size_t dstSize = 0; + unsigned loopNb, blockNb; + nbLoops += !nbLoops; /* minimum nbLoops is 1 */ + if (p.initFn != NULL) p.initFn(p.initPayload); + for (loopNb = 0; loopNb < nbLoops; loopNb++) { + for (blockNb = 0; blockNb < p.blockCount; blockNb++) { + size_t const res = p.benchFn(p.srcBuffers[blockNb], p.srcSizes[blockNb], + p.dstBuffers[blockNb], p.dstCapacities[blockNb], + p.benchPayload); + if (loopNb == 0) { + if (p.blockResults != NULL) p.blockResults[blockNb] = res; + if ((p.errorFn != NULL) && (p.errorFn(res))) { + RETURN_QUIET_ERROR(BMK_runOutcome_error(res), + "Function benchmark failed on block %u (of size %u) with error %i", + blockNb, (unsigned)p.srcSizes[blockNb], (int)res); + } + dstSize += res; + } } + } /* for (loopNb = 0; loopNb < nbLoops; loopNb++) */ + + { PTime const totalTime = UTIL_clockSpanNano(clockStart); + BMK_runTime_t rt; + rt.nanoSecPerRun = (double)totalTime / nbLoops; + rt.sumOfReturn = dstSize; + return BMK_setValid_runTime(rt); + } } +} + + +/* ==== Benchmarking any function, providing intermediate results ==== */ + +struct BMK_timedFnState_s { + PTime timeSpent_ns; + PTime timeBudget_ns; + PTime runBudget_ns; + BMK_runTime_t fastestRun; + unsigned nbLoops; + UTIL_time_t coolTime; +}; /* typedef'd to BMK_timedFnState_t within bench.h */ + +BMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms) +{ + BMK_timedFnState_t* const r = (BMK_timedFnState_t*)malloc(sizeof(*r)); + if (r == NULL) return NULL; /* malloc() error */ + BMK_resetTimedFnState(r, total_ms, run_ms); + return r; +} + +void BMK_freeTimedFnState(BMK_timedFnState_t* state) { free(state); } + +BMK_timedFnState_t* +BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms) +{ + typedef char check_size[ 2 * (sizeof(BMK_timedFnState_shell) >= sizeof(struct BMK_timedFnState_s)) - 1]; /* static assert : a compilation failure indicates that BMK_timedFnState_shell is not large enough */ + typedef struct { check_size c; BMK_timedFnState_t tfs; } tfs_align; /* force tfs to be aligned at its next best position */ + size_t const tfs_alignment = offsetof(tfs_align, tfs); /* provides the minimal alignment restriction for BMK_timedFnState_t */ + BMK_timedFnState_t* const r = (BMK_timedFnState_t*)buffer; + if (buffer == NULL) return NULL; + if (size < sizeof(struct BMK_timedFnState_s)) return NULL; + if ((size_t)buffer % tfs_alignment) return NULL; /* buffer must be properly aligned */ + BMK_resetTimedFnState(r, total_ms, run_ms); + return r; +} + +void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms) +{ + if (!total_ms) total_ms = 1 ; + if (!run_ms) run_ms = 1; + if (run_ms > total_ms) run_ms = total_ms; + timedFnState->timeSpent_ns = 0; + timedFnState->timeBudget_ns = (PTime)total_ms * TIMELOOP_NANOSEC / 1000; + timedFnState->runBudget_ns = (PTime)run_ms * TIMELOOP_NANOSEC / 1000; + timedFnState->fastestRun.nanoSecPerRun = (double)TIMELOOP_NANOSEC * 2000000000; /* hopefully large enough : must be larger than any potential measurement */ + timedFnState->fastestRun.sumOfReturn = (size_t)(-1LL); + timedFnState->nbLoops = 1; + timedFnState->coolTime = UTIL_getTime(); +} + +/* Tells if nb of seconds set in timedFnState for all runs is spent. + * note : this function will return 1 if BMK_benchFunctionTimed() has actually errored. */ +int BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState) +{ + return (timedFnState->timeSpent_ns >= timedFnState->timeBudget_ns); +} + + +#undef MIN +#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) + +#define MINUSABLETIME (TIMELOOP_NANOSEC / 2) /* 0.5 seconds */ + +BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* cont, + BMK_benchParams_t p) +{ + PTime const runBudget_ns = cont->runBudget_ns; + PTime const runTimeMin_ns = runBudget_ns / 2; + BMK_runTime_t bestRunTime = cont->fastestRun; + + for (;;) { + BMK_runOutcome_t const runResult = BMK_benchFunction(p, cont->nbLoops); + + if (!BMK_isSuccessful_runOutcome(runResult)) { /* error : move out */ + return runResult; + } + + { BMK_runTime_t const newRunTime = BMK_extract_runTime(runResult); + double const loopDuration_ns = newRunTime.nanoSecPerRun * cont->nbLoops; + + cont->timeSpent_ns += (unsigned long long)loopDuration_ns; + + /* estimate nbLoops for next run to last approximately 1 second */ + if (loopDuration_ns > (runBudget_ns / 50)) { + double const fastestRun_ns = MIN(bestRunTime.nanoSecPerRun, newRunTime.nanoSecPerRun); + cont->nbLoops = (unsigned)(runBudget_ns / fastestRun_ns) + 1; + } else { + /* previous run was too short : blindly increase workload by x multiplier */ + const unsigned multiplier = 10; + assert(cont->nbLoops < ((unsigned)-1) / multiplier); /* avoid overflow */ + cont->nbLoops *= multiplier; + } + + if (loopDuration_ns < runTimeMin_ns) { + /* When benchmark run time is too small : don't report results. + * increased risks of rounding errors */ + continue; + } + + if (newRunTime.nanoSecPerRun < bestRunTime.nanoSecPerRun) { + bestRunTime = newRunTime; + } + } + break; + } /* while (!completed) */ + + return BMK_setValid_runTime(bestRunTime); +} diff --git a/third_party/xxhash/tests/bench/benchfn.h b/third_party/xxhash/tests/bench/benchfn.h new file mode 100644 index 00000000000..42d10338304 --- /dev/null +++ b/third_party/xxhash/tests/bench/benchfn.h @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2016-2020 Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/* benchfn : + * benchmark any function on a set of input + * providing result in nanoSecPerRun + * or detecting and returning an error + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +#ifndef BENCH_FN_H_23876 +#define BENCH_FN_H_23876 + +/* === Dependencies === */ +#include /* size_t */ + + +/* ==== Benchmark any function, iterated on a set of blocks ==== */ + +/* BMK_runTime_t: valid result return type */ + +typedef struct { + double nanoSecPerRun; /* time per iteration (over all blocks) */ + size_t sumOfReturn; /* sum of return values */ +} BMK_runTime_t; + + +/* BMK_runOutcome_t: + * type expressing the outcome of a benchmark run by BMK_benchFunction(), + * which can be either valid or invalid. + * benchmark outcome can be invalid if errorFn is provided. + * BMK_runOutcome_t must be considered "opaque" : never access its members directly. + * Instead, use its assigned methods : + * BMK_isSuccessful_runOutcome, BMK_extract_runTime, BMK_extract_errorResult. + * The structure is only described here to allow its allocation on stack. */ + +typedef struct { + BMK_runTime_t internal_never_ever_use_directly; + size_t error_result_never_ever_use_directly; + int error_tag_never_ever_use_directly; +} BMK_runOutcome_t; + + +/* prototypes for benchmarked functions */ +typedef size_t (*BMK_benchFn_t)(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload); +typedef size_t (*BMK_initFn_t)(void* initPayload); +typedef unsigned (*BMK_errorFn_t)(size_t); + + +/* BMK_benchFunction() parameters are provided via the following structure. + * A structure is preferable for readability, + * as the number of parameters required is fairly large. + * No initializer is provided, because it doesn't make sense to provide some "default" : + * all parameters must be specified by the caller. + * optional parameters are labelled explicitly, and accept value NULL when not used */ +typedef struct { + BMK_benchFn_t benchFn; /* the function to benchmark, over the set of blocks */ + void* benchPayload; /* pass custom parameters to benchFn : + * (*benchFn)(srcBuffers[i], srcSizes[i], dstBuffers[i], dstCapacities[i], benchPayload) */ + BMK_initFn_t initFn; /* (*initFn)(initPayload) is run once per run, at the beginning. */ + void* initPayload; /* Both arguments can be NULL, in which case nothing is run. */ + BMK_errorFn_t errorFn; /* errorFn will check each return value of benchFn over each block, to determine if it failed or not. + * errorFn can be NULL, in which case no check is performed. + * errorFn must return 0 when benchFn was successful, and >= 1 if it detects an error. + * Execution is stopped as soon as an error is detected. + * the triggering return value can be retrieved using BMK_extract_errorResult(). */ + size_t blockCount; /* number of blocks to operate benchFn on. + * It's also the size of all array parameters : + * srcBuffers, srcSizes, dstBuffers, dstCapacities, blockResults */ + const void *const * srcBuffers; /* read-only array of buffers to be operated on by benchFn */ + const size_t* srcSizes; /* read-only array containing sizes of srcBuffers */ + void *const * dstBuffers; /* array of buffers to be written into by benchFn. This array is not optional, it must be provided even if unused by benchfn. */ + const size_t* dstCapacities; /* read-only array containing capacities of dstBuffers. This array must be present. */ + size_t* blockResults; /* Optional: store the return value of benchFn for each block. Use NULL if this result is not requested. */ +} BMK_benchParams_t; + + +/* BMK_benchFunction() : + * This function benchmarks benchFn and initFn, providing a result. + * + * params : see description of BMK_benchParams_t above. + * nbLoops: defines number of times benchFn is run over the full set of blocks. + * Minimum value is 1. A 0 is interpreted as a 1. + * + * @return: can express either an error or a successful result. + * Use BMK_isSuccessful_runOutcome() to check if benchmark was successful. + * If yes, extract the result with BMK_extract_runTime(), + * it will contain : + * .sumOfReturn : the sum of all return values of benchFn through all of blocks + * .nanoSecPerRun : time per run of benchFn + (time for initFn / nbLoops) + * .sumOfReturn is generally intended for functions which return a # of bytes written into dstBuffer, + * in which case, this value will be the total amount of bytes written into dstBuffer. + * + * blockResults : when provided (!= NULL), and when benchmark is successful, + * params.blockResults contains all return values of `benchFn` over all blocks. + * when provided (!= NULL), and when benchmark failed, + * params.blockResults contains return values of `benchFn` over all blocks preceding and including the failed block. + */ +BMK_runOutcome_t BMK_benchFunction(BMK_benchParams_t params, unsigned nbLoops); + + + +/* check first if the benchmark was successful or not */ +int BMK_isSuccessful_runOutcome(BMK_runOutcome_t outcome); + +/* If the benchmark was successful, extract the result. + * note : this function will abort() program execution if benchmark failed ! + * always check if benchmark was successful first ! + */ +BMK_runTime_t BMK_extract_runTime(BMK_runOutcome_t outcome); + +/* when benchmark failed, it means one invocation of `benchFn` failed. + * The failure was detected by `errorFn`, operating on return values of `benchFn`. + * Returns the faulty return value. + * note : this function will abort() program execution if benchmark did not failed. + * always check if benchmark failed first ! + */ +size_t BMK_extract_errorResult(BMK_runOutcome_t outcome); + + + +/* ==== Benchmark any function, returning intermediate results ==== */ + +/* state information tracking benchmark session */ +typedef struct BMK_timedFnState_s BMK_timedFnState_t; + +/* BMK_benchTimedFn() : + * Similar to BMK_benchFunction(), most arguments being identical. + * Automatically determines `nbLoops` so that each result is regularly produced at interval of about run_ms. + * Note : minimum `nbLoops` is 1, therefore a run may last more than run_ms, and possibly even more than total_ms. + * Usage - initialize timedFnState, select benchmark duration (total_ms) and each measurement duration (run_ms) + * call BMK_benchTimedFn() repetitively, each measurement is supposed to last about run_ms + * Check if total time budget is spent or exceeded, using BMK_isCompleted_TimedFn() + */ +BMK_runOutcome_t BMK_benchTimedFn(BMK_timedFnState_t* timedFnState, + BMK_benchParams_t params); + +/* Tells if duration of all benchmark runs has exceeded total_ms + */ +int BMK_isCompleted_TimedFn(const BMK_timedFnState_t* timedFnState); + +/* BMK_createTimedFnState() and BMK_resetTimedFnState() : + * Create/Set BMK_timedFnState_t for next benchmark session, + * which shall last a minimum of total_ms milliseconds, + * producing intermediate results, paced at interval of (approximately) run_ms. + */ +BMK_timedFnState_t* BMK_createTimedFnState(unsigned total_ms, unsigned run_ms); +void BMK_resetTimedFnState(BMK_timedFnState_t* timedFnState, unsigned total_ms, unsigned run_ms); +void BMK_freeTimedFnState(BMK_timedFnState_t* state); + + +/* BMK_timedFnState_shell and BMK_initStatic_timedFnState() : + * Makes it possible to statically allocate a BMK_timedFnState_t on stack. + * BMK_timedFnState_shell is only there to allocate space, + * never ever access its members. + * BMK_timedFnState_t() actually accepts any buffer. + * It will check if provided buffer is large enough and is correctly aligned, + * and will return NULL if conditions are not respected. + */ +#define BMK_TIMEDFNSTATE_SIZE 64 +typedef union { + char never_access_space[BMK_TIMEDFNSTATE_SIZE]; + long long alignment_enforcer; /* must be aligned on 8-bytes boundaries */ +} BMK_timedFnState_shell; +BMK_timedFnState_t* BMK_initStatic_timedFnState(void* buffer, size_t size, unsigned total_ms, unsigned run_ms); + + +#endif /* BENCH_FN_H_23876 */ + +#if defined (__cplusplus) +} +#endif diff --git a/third_party/xxhash/tests/bench/bhDisplay.c b/third_party/xxhash/tests/bench/bhDisplay.c new file mode 100644 index 00000000000..601ca1f3f13 --- /dev/null +++ b/third_party/xxhash/tests/bench/bhDisplay.c @@ -0,0 +1,160 @@ +/* +* CSV Display module for the hash benchmark program +* Part of the xxHash project +* Copyright (C) 2019-2020 Yann Collet +* +* GPL v2 License +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* You can contact the author at : +* - xxHash homepage : https://www.xxhash.com +* - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + + +/* === Dependencies === */ + +#include /* rand */ +#include /* printf */ +#include + +#include "benchHash.h" +#include "bhDisplay.h" + + +/* === benchmark large input === */ + +#define MB_UNIT 1000000 +#define BENCH_LARGE_ITER_MS 490 +#define BENCH_LARGE_TOTAL_MS 1010 +static void bench_oneHash_largeInput(Bench_Entry hashDesc, int minlog, int maxlog) +{ + printf("%-7s", hashDesc.name); + for (int sizelog=minlog; sizelog<=maxlog; sizelog++) { + size_t const inputSize = (size_t)1 << sizelog; + double const nbhps = bench_hash(hashDesc.hash, BMK_throughput, + inputSize, BMK_fixedSize, + BENCH_LARGE_TOTAL_MS, BENCH_LARGE_ITER_MS); + printf(",%6.0f", nbhps * inputSize / MB_UNIT); fflush(NULL); + } + printf("\n"); +} + +void bench_largeInput(Bench_Entry const* hashDescTable, int nbHashes, int minlog, int maxlog) +{ + assert(maxlog < 31); + assert(minlog >= 0); + printf("benchmarking large inputs : from %u bytes (log%i) to %u MB (log%i) \n", + 1U << minlog, minlog, + (1U << maxlog) >> 20, maxlog); + for (int i=0; i /* size_t */ + + +/* ================================================== + * Non-portable hash algorithms + * =============================================== */ + + +#ifdef HARDWARE_SUPPORT + +/* + * List any hash algorithms that depend on specific hardware support, + * including for example: + * - Hardware crc32c + * - Hardware AES support + * - Carryless Multipliers (clmul) + * - AVX2 + */ + +#endif + + + +/* ================================================== + * List of hashes + * ================================================== + * Each hash must be wrapped in a thin redirector conformant with the BMK_benchfn_t. + * BMK_benchfn_t is generic, not specifically designed for hashes. + * For hashes, the following parameters are expected to be useless: + * dst, dstCapacity, customPayload. + * + * The result of each hash is assumed to be provided as function return value. + * This condition is important for latency measurements. + */ + + /* === xxHash === */ +#define XXH_INLINE_ALL +#include "xxhash.h" + +size_t XXH32_wrapper(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload) +{ + (void)dst; (void)dstCapacity; (void)customPayload; + return (size_t) XXH32(src, srcSize, 0); +} + + +size_t XXH64_wrapper(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload) +{ + (void)dst; (void)dstCapacity; (void)customPayload; + return (size_t) XXH64(src, srcSize, 0); +} + + +size_t xxh3_wrapper(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload) +{ + (void)dst; (void)dstCapacity; (void)customPayload; + return (size_t) XXH3_64bits(src, srcSize); +} + + +size_t XXH128_wrapper(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload) +{ + (void)dst; (void)dstCapacity; (void)customPayload; + return (size_t) XXH3_128bits(src, srcSize).low64; +} + + + +/* ================================================== + * Table of hashes + * =============================================== */ + +#include "bhDisplay.h" /* Bench_Entry */ + +#ifndef HARDWARE_SUPPORT +# define NB_HASHES 4 +#else +# define NB_HASHES 4 +#endif + +Bench_Entry const hashCandidates[NB_HASHES] = { + { "xxh3" , xxh3_wrapper }, + { "XXH32" , XXH32_wrapper }, + { "XXH64" , XXH64_wrapper }, + { "XXH128", XXH128_wrapper }, +#ifdef HARDWARE_SUPPORT + /* list here codecs which require specific hardware support, such SSE4.1, PCLMUL, AVX2, etc. */ +#endif +}; diff --git a/third_party/xxhash/tests/bench/main.c b/third_party/xxhash/tests/bench/main.c new file mode 100644 index 00000000000..1cf6e80f696 --- /dev/null +++ b/third_party/xxhash/tests/bench/main.c @@ -0,0 +1,220 @@ +/* + * Main program to benchmark hash functions + * Part of the xxHash project + * Copyright (C) 2019-2020 Yann Collet + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + + +/* === dependencies === */ + +#include /* printf */ +#include /* INT_MAX */ +#include "bhDisplay.h" /* bench_x */ + + +/* === defines list of hashes `hashCandidates` and NB_HASHES *** */ + +#include "hashes.h" + + +/* === parse command line === */ + +#undef NDEBUG +#include + + +/*! + * readIntFromChar(): + * Allows and interprets K, KB, KiB, M, MB and MiB suffix. + * Will also modify `*stringPtr`, advancing it to position where it stopped reading. + */ +static int readIntFromChar(const char** stringPtr) +{ + static int const max = (INT_MAX / 10) - 1; + int result = 0; + while ((**stringPtr >='0') && (**stringPtr <='9')) { + assert(result < max); + result *= 10; + result += (unsigned)(**stringPtr - '0'); + (*stringPtr)++ ; + } + if ((**stringPtr=='K') || (**stringPtr=='M')) { + int const maxK = INT_MAX >> 10; + assert(result < maxK); + result <<= 10; + if (**stringPtr=='M') { + assert(result < maxK); + result <<= 10; + } + (*stringPtr)++; /* skip `K` or `M` */ + if (**stringPtr=='i') (*stringPtr)++; + if (**stringPtr=='B') (*stringPtr)++; + } + return result; +} + + +/** + * isCommand(): + * Checks if string is the same as longCommand. + * If yes, @return 1, otherwise @return 0 + */ +static int isCommand(const char* string, const char* longCommand) +{ + assert(string); + assert(longCommand); + size_t const comSize = strlen(longCommand); + return !strncmp(string, longCommand, comSize); +} + +/* + * longCommandWArg(): + * Checks if *stringPtr is the same as longCommand. + * If yes, @return 1 and advances *stringPtr to the position which immediately + * follows longCommand. + * @return 0 and doesn't modify *stringPtr otherwise. + */ +static int longCommandWArg(const char** stringPtr, const char* longCommand) +{ + assert(stringPtr); + assert(longCommand); + size_t const comSize = strlen(longCommand); + int const result = isCommand(*stringPtr, longCommand); + if (result) *stringPtr += comSize; + return result; +} + + +/* === default values - can be redefined at compilation time === */ + +#ifndef SMALL_SIZE_MIN_DEFAULT +# define SMALL_SIZE_MIN_DEFAULT 1 +#endif +#ifndef SMALL_SIZE_MAX_DEFAULT +# define SMALL_SIZE_MAX_DEFAULT 127 +#endif +#ifndef LARGE_SIZELOG_MIN_DEFAULT +# define LARGE_SIZELOG_MIN_DEFAULT 9 +#endif +#ifndef LARGE_SIZELOG_MAX_DEFAULT +# define LARGE_SIZELOG_MAX_DEFAULT 27 +#endif + + +static int display_hash_names(void) +{ + int i; + printf("available hashes : \n"); + for (i=0; i= 1); return help(exename); } + if (isCommand(*arg, "--list")) { return display_hash_names(); } + if (longCommandWArg(arg, "--n=")) { nb_h_test = readIntFromChar(arg); continue; } /* hidden command */ + if (longCommandWArg(arg, "--minl=")) { largeTest_log_min = readIntFromChar(arg); continue; } + if (longCommandWArg(arg, "--maxl=")) { largeTest_log_max = readIntFromChar(arg); continue; } + if (longCommandWArg(arg, "--mins=")) { smallTest_size_min = (size_t)readIntFromChar(arg); continue; } + if (longCommandWArg(arg, "--maxs=")) { smallTest_size_max = (size_t)readIntFromChar(arg); continue; } + /* not a command: must be a hash name */ + hashNb = hashID(*arg); + if (hashNb >= 0) { + nb_h_test = 1; + } else { + /* not a hash name: error */ + return badusage(exename); + } + } + + /* border case (requires (mis)using hidden command `--n=#`) */ + if (hashNb + nb_h_test > NB_HASHES) { + printf("wrong hash selection \n"); + return 1; + } + + printf(" === benchmarking %i hash functions === \n", nb_h_test); + if (largeTest_log_max >= largeTest_log_min) { + bench_largeInput(hashCandidates+hashNb, nb_h_test, largeTest_log_min, largeTest_log_max); + } + if (smallTest_size_max >= smallTest_size_min) { + bench_throughput_smallInputs(hashCandidates+hashNb, nb_h_test, smallTest_size_min, smallTest_size_max); + bench_throughput_randomInputLength(hashCandidates+hashNb, nb_h_test, smallTest_size_min, smallTest_size_max); + bench_latency_smallInputs(hashCandidates+hashNb, nb_h_test, smallTest_size_min, smallTest_size_max); + bench_latency_randomInputLength(hashCandidates+hashNb, nb_h_test, smallTest_size_min, smallTest_size_max); + } + + return 0; +} diff --git a/third_party/xxhash/tests/bench/timefn.c b/third_party/xxhash/tests/bench/timefn.c new file mode 100644 index 00000000000..856812898cf --- /dev/null +++ b/third_party/xxhash/tests/bench/timefn.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2019-2020 Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/* === Dependencies === */ + +#include "timefn.h" + + +/*-**************************************** +* Time functions +******************************************/ + +#if defined(_WIN32) /* Windows */ + +#include /* abort */ +#include /* perror */ + +UTIL_time_t UTIL_getTime(void) { UTIL_time_t x; QueryPerformanceCounter(&x); return x; } + +PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) +{ + static LARGE_INTEGER ticksPerSecond; + static int init = 0; + if (!init) { + if (!QueryPerformanceFrequency(&ticksPerSecond)) { + perror("timefn::QueryPerformanceFrequency"); + abort(); + } + init = 1; + } + return 1000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; +} + +PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) +{ + static LARGE_INTEGER ticksPerSecond; + static int init = 0; + if (!init) { + if (!QueryPerformanceFrequency(&ticksPerSecond)) { + perror("timefn::QueryPerformanceFrequency"); + abort(); + } + init = 1; + } + return 1000000000ULL*(clockEnd.QuadPart - clockStart.QuadPart)/ticksPerSecond.QuadPart; +} + + + +#elif defined(__APPLE__) && defined(__MACH__) + +UTIL_time_t UTIL_getTime(void) { return mach_absolute_time(); } + +PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) +{ + static mach_timebase_info_data_t rate; + static int init = 0; + if (!init) { + mach_timebase_info(&rate); + init = 1; + } + return (((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom))/1000ULL; +} + +PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) +{ + static mach_timebase_info_data_t rate; + static int init = 0; + if (!init) { + mach_timebase_info(&rate); + init = 1; + } + return ((clockEnd - clockStart) * (PTime)rate.numer) / ((PTime)rate.denom); +} + + + +#elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \ + && defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ + +#include /* abort */ +#include /* perror */ + +UTIL_time_t UTIL_getTime(void) +{ + /* time must be initialized, othersize it may fail msan test. + * No good reason, likely a limitation of timespec_get() for some target */ + UTIL_time_t time = UTIL_TIME_INITIALIZER; + if (timespec_get(&time, TIME_UTC) != TIME_UTC) { + perror("timefn::timespec_get"); + abort(); + } + return time; +} + +static UTIL_time_t UTIL_getSpanTime(UTIL_time_t begin, UTIL_time_t end) +{ + UTIL_time_t diff; + if (end.tv_nsec < begin.tv_nsec) { + diff.tv_sec = (end.tv_sec - 1) - begin.tv_sec; + diff.tv_nsec = (end.tv_nsec + 1000000000ULL) - begin.tv_nsec; + } else { + diff.tv_sec = end.tv_sec - begin.tv_sec; + diff.tv_nsec = end.tv_nsec - begin.tv_nsec; + } + return diff; +} + +PTime UTIL_getSpanTimeMicro(UTIL_time_t begin, UTIL_time_t end) +{ + UTIL_time_t const diff = UTIL_getSpanTime(begin, end); + PTime micro = 0; + micro += 1000000ULL * diff.tv_sec; + micro += diff.tv_nsec / 1000ULL; + return micro; +} + +PTime UTIL_getSpanTimeNano(UTIL_time_t begin, UTIL_time_t end) +{ + UTIL_time_t const diff = UTIL_getSpanTime(begin, end); + PTime nano = 0; + nano += 1000000000ULL * diff.tv_sec; + nano += diff.tv_nsec; + return nano; +} + + + +#else /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */ + +UTIL_time_t UTIL_getTime(void) { return clock(); } +PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; } +PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd) { return 1000000000ULL * (clockEnd - clockStart) / CLOCKS_PER_SEC; } + +#endif + + + +/* returns time span in microseconds */ +PTime UTIL_clockSpanMicro(UTIL_time_t clockStart ) +{ + UTIL_time_t const clockEnd = UTIL_getTime(); + return UTIL_getSpanTimeMicro(clockStart, clockEnd); +} + +/* returns time span in microseconds */ +PTime UTIL_clockSpanNano(UTIL_time_t clockStart ) +{ + UTIL_time_t const clockEnd = UTIL_getTime(); + return UTIL_getSpanTimeNano(clockStart, clockEnd); +} + +void UTIL_waitForNextTick(void) +{ + UTIL_time_t const clockStart = UTIL_getTime(); + UTIL_time_t clockEnd; + do { + clockEnd = UTIL_getTime(); + } while (UTIL_getSpanTimeNano(clockStart, clockEnd) == 0); +} diff --git a/third_party/xxhash/tests/bench/timefn.h b/third_party/xxhash/tests/bench/timefn.h new file mode 100644 index 00000000000..41007f30ca2 --- /dev/null +++ b/third_party/xxhash/tests/bench/timefn.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016-2020 Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef TIME_FN_H_MODULE_287987 +#define TIME_FN_H_MODULE_287987 + +#if defined (__cplusplus) +extern "C" { +#endif + + +/*-**************************************** +* Dependencies +******************************************/ +#include /* utime */ +#if defined(_MSC_VER) +# include /* utime */ +#else +# include /* utime */ +#endif +#include /* clock_t, clock, CLOCKS_PER_SEC */ + + + +/*-**************************************** +* Local Types +******************************************/ + +#if !defined (__VMS) && (defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint64_t PTime; /* Precise Time */ +#else + typedef unsigned long long PTime; /* does not support compilers without long long support */ +#endif + + + +/*-**************************************** +* Time functions +******************************************/ +#if defined(_WIN32) /* Windows */ + + #include /* LARGE_INTEGER */ + typedef LARGE_INTEGER UTIL_time_t; + #define UTIL_TIME_INITIALIZER { { 0, 0 } } + +#elif defined(__APPLE__) && defined(__MACH__) + + #include + typedef PTime UTIL_time_t; + #define UTIL_TIME_INITIALIZER 0 + +#elif (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */) \ + && defined(TIME_UTC) /* C11 requires timespec_get, but FreeBSD 11 lacks it, while still claiming C11 compliance */ + + typedef struct timespec UTIL_time_t; + #define UTIL_TIME_INITIALIZER { 0, 0 } + +#else /* relies on standard C90 (note : clock_t measurements can be wrong when using multi-threading) */ + + typedef clock_t UTIL_time_t; + #define UTIL_TIME_INITIALIZER 0 + +#endif + + +UTIL_time_t UTIL_getTime(void); +PTime UTIL_getSpanTimeMicro(UTIL_time_t clockStart, UTIL_time_t clockEnd); +PTime UTIL_getSpanTimeNano(UTIL_time_t clockStart, UTIL_time_t clockEnd); + +#define SEC_TO_MICRO ((PTime)1000000) +PTime UTIL_clockSpanMicro(UTIL_time_t clockStart); +PTime UTIL_clockSpanNano(UTIL_time_t clockStart); + +void UTIL_waitForNextTick(void); + + +#if defined (__cplusplus) +} +#endif + +#endif /* TIME_FN_H_MODULE_287987 */ diff --git a/third_party/xxhash/tests/collisions/.gitignore b/third_party/xxhash/tests/collisions/.gitignore new file mode 100644 index 00000000000..f85592639b4 --- /dev/null +++ b/third_party/xxhash/tests/collisions/.gitignore @@ -0,0 +1,2 @@ +#build artefacts +collisionsTest diff --git a/third_party/xxhash/tests/collisions/LICENSE b/third_party/xxhash/tests/collisions/LICENSE new file mode 100644 index 00000000000..d159169d105 --- /dev/null +++ b/third_party/xxhash/tests/collisions/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/third_party/xxhash/tests/collisions/Makefile b/third_party/xxhash/tests/collisions/Makefile new file mode 100644 index 00000000000..bad9835b0f9 --- /dev/null +++ b/third_party/xxhash/tests/collisions/Makefile @@ -0,0 +1,74 @@ +# Brute force collision tester for 64-bit hashes +# Part of xxHash project +# Copyright (C) 2019-2020 Yann Collet +# +# GPL v2 License +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# You can contact the author at: +# - xxHash homepage: https://www.xxhash.com +# - xxHash source repository: https://github.com/Cyan4973/xxHash +# + +SRC_DIRS = ./ ../../ allcodecs/ +VPATH = $(SRC_DIRS) +CPPFLAGS += $(addprefix -I ,$(SRC_DIRS)) +CFLAGS ?= -std=c99 \ + -Wall -Wextra -Wconversion +CXXFLAGS ?= -Wall -Wextra -Wconversion -std=c++11 +LDFLAGS += -pthread +TESTHASHES = 110000000 + +HASH_SRC := $(sort $(wildcard allcodecs/*.c allcodecs/*.cc)) +HASH_OBJ := $(patsubst %.c,%.o,$(HASH_SRC)) + + +.PHONY: default +default: release + +.PHONY: all +all: release + +collisionsTest: main.o pool.o threading.o sort.o $(HASH_OBJ) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) $^ $(LDFLAGS) -o $@ + +main.o: hashes.h xxhash.h + +release: CXXFLAGS += -O3 +release: CFLAGS += -O3 +release: collisionsTest + +debug: CXXFLAGS += -g3 -O0 -DDEBUG +debug: CFLAGS += -g3 -O0 -DDEBUG +debug: collisionsTest + +.PHONY: check +check: test + +.PHONY: test +test: debug + @echo "" + @echo "## $(TESTHASHES) hashes with original and 0 threads" + @time ./collisionsTest --nbh=$(TESTHASHES) + @echo "" + @echo "## $(TESTHASHES) hashes with original and 4 threads" + @time ./collisionsTest --nbh=$(TESTHASHES) --threadlog=2 + @echo "" + +.PHONY: clean +clean: + $(RM) *.o allcodecs/*.o + $(RM) collisionsTest diff --git a/third_party/xxhash/tests/collisions/README.md b/third_party/xxhash/tests/collisions/README.md new file mode 100644 index 00000000000..683b1151863 --- /dev/null +++ b/third_party/xxhash/tests/collisions/README.md @@ -0,0 +1,122 @@ + +__collisionsTest__ is a brute force hash analyzer +which will measure a 64-bit hash algorithm's collision rate +by generating billions of hashes, +and comparing the result to an "ideal" target. + +The test requires a very large amount of memory. +By default, it will generate 24 billion of 64-bit hashes, +requiring __192 GB of RAM__ for their storage. +The number of hashes can be modified using command `--nbh=`. +Be aware that testing the collision ratio of 64-bit hashes +requires a very large amount of hashes (several billion) for meaningful measurements. + +To reduce RAM usage, an optional filter can be requested, with `--filter`. +It reduces the nb of candidates to analyze, hence associated RAM budget. +Note that the filter itself requires a lot of RAM +(32 GB by default, can be modified using `--filterlog=`, +a too small filter will not be efficient, aim at ~2 bytes per hash), +and reading and writing into filter cost a significant CPU budget, +so this method is slower. +It also doesn't allow advanced analysis of partial bitfields, +since most hashes will be discarded and not stored. + +When using the filter, the RAM budget consists of the filter and a list of candidates, +which will be a fraction of the original hash list. +Using default settings (24 billion hashes, 32 GB filter), +the number of potential candidates should be reduced to less than 2 billion, +requiring ~14 GB for their storage. +Such a result also depends on hash algorithm's efficiency. +The number of effective candidates is likely to be lower, at ~ 1 billion, +but storage must allocate an upper bound. + +For the default test, the expected "optimal" collision rate for a 64-bit hash function is ~18 collisions. + +#### How to build +``` +make +``` + +Note: the code is a mix of C99 and C++14, +it's not compatible with a C90-only compiler. + +#### Build modifier + +- `SLAB5`: use alternative pattern generator, friendlier for weak hash algorithms +- `POOL_MT`: if `=0`, disable multi-threading code (enabled by default) + +#### How to integrate any hash in the tester + +The build script will compile files found in `./allcodecs`. +Put the source code here. +This also works if the hash is a single `*.h` file. + +The glue happens in `hashes.h`. +In this file, there are 2 sections: +- Adds the required `#include "header.h"`, and creates a wrapper +to respect the format expected by the function pointer. +- Adds the wrapper, along with the name and an indication of the output width, +to the table, at the end of `hashes.h` + +Build with `make`. Locate your new hash with `./collisionsTest -h`, +it should be listed. + + +#### Usage + +``` +usage: ./collisionsTest [hashName] [opt] + +list of hashNames: (...) + +Optional parameters: + --nbh=NB Select nb of hashes to generate (25769803776 by default) + --filter Enable the filter. Slower, but reduces memory usage for same nb of hashes. + --threadlog=NB Use 2^NB threads + --len=NB Select length of input (255 bytes by default) +``` + +#### Some advises on how to setup a collisions test + +Most tests are primarily driven by the amount of RAM available. +Here's a method to decide the size of the test. + +Presuming that RAM budget is not plentiful, for this example 32 GB, +the `--filter` mode is actually compulsory to measure anything meaningful. +Let's plan 50% of memory for the filter, that's 16 GB. +This will be good enough to filter about 10% less hashes than this size. +Let's round down to 14 G. + +By requesting 14G, the expectation is that the program will automatically +size the filter to 16 GB, and expect to store ~1G candidates, +leaving enough room to breeze for the system. + +The command line becomes: +``` +./collisionsTest --nbh=14G --filter NameOfHash +``` + +#### Examples: + +Here are a few results produced with this tester: + +| Algorithm | Input Len | Nb Hashes | Expected | Nb Collisions | Notes | +| --- | --- | --- | --- | --- | --- | +| __XXH3__ | 255 | 100 Gi | 312.5 | 326 | | +| __XXH64__ | 255 | 100 Gi | 312.5 | 294 | | +| __XXH128__ low64 | 512 | 100 Gi | 312.5 | 321 | | +| __XXH128__ high64| 512 | 100 Gi | 312.5 | 325 | | +| __XXH128__ | 255 | 100 Gi | 0.0 | 0 | a 128-bit hash is expected to generate 0 collisions | + +Test on small inputs: + +| Algorithm | Input Len | Nb Hashes | Expected | Nb Collisions | Notes | +| --- | --- | --- | --- | --- | --- | +| __XXH64__ | 8 | 100 Gi | 312.5 | __0__ | `XXH64` is bijective for `len==8` | +| __XXH3__ | 8 | 100 Gi | 312.5 | __0__ | `XXH3` is also bijective for `len==8` | +| __XXH3__ | 16 | 100 Gi | 312.5 | 332 | | +| __XXH3__ | 32 | 14 Gi | 6.1 | 3 | | +| __XXH128__ | 16 | 25 Gi | 0.0 | 0 | test range 9-16 | +| __XXH128__ | 32 | 25 Gi | 0.0 | 0 | test range 17-128 | +| __XXH128__ | 100 | 13 Gi | 0.0 | 0 | test range 17-128 | +| __XXH128__ | 200 | 13 Gi | 0.0 | 0 | test range 129-240 | diff --git a/third_party/xxhash/tests/collisions/allcodecs/README.md b/third_party/xxhash/tests/collisions/allcodecs/README.md new file mode 100644 index 00000000000..d41fc2dbbfc --- /dev/null +++ b/third_party/xxhash/tests/collisions/allcodecs/README.md @@ -0,0 +1 @@ +Put in this directory all hash algorithms to test diff --git a/third_party/xxhash/tests/collisions/allcodecs/dummy.c b/third_party/xxhash/tests/collisions/allcodecs/dummy.c new file mode 100644 index 00000000000..547d5c7366d --- /dev/null +++ b/third_party/xxhash/tests/collisions/allcodecs/dummy.c @@ -0,0 +1,38 @@ +/* + * dummy.c, a fake hash algorithm, just to test integration capabilities. + * Part of the xxHash project + * Copyright (C) 2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + + +#include + +unsigned badsum32(const void* input, size_t len, unsigned seed) +{ + unsigned sum = seed; + const unsigned char* in8 = input; + size_t c; + for (c=0; c /* size_t */ + +unsigned badsum32(const void* input, size_t len, unsigned seed); + + +#if defined (__cplusplus) +} +#endif + +#endif /* DUMMY_H_987987 */ diff --git a/third_party/xxhash/tests/collisions/hashes.h b/third_party/xxhash/tests/collisions/hashes.h new file mode 100644 index 00000000000..0b7223d9f17 --- /dev/null +++ b/third_party/xxhash/tests/collisions/hashes.h @@ -0,0 +1,127 @@ +/* + * List of hashes for the brute force collision tester + * Part of xxHash project + * Copyright (C) 2019-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#ifndef HASHES_H_1235465 +#define HASHES_H_1235465 + +#include /* size_t */ +#include /* uint64_t */ +#define XXH_INLINE_ALL /* XXH128_hash_t */ +#include "xxhash.h" + + +/* return type */ + +typedef union { + uint64_t h64; + XXH128_hash_t h128; +} UniHash; + +UniHash uniHash32(uint64_t v32) +{ UniHash unih; + unih.h64 = v32; + return unih; +} + +UniHash uniHash64(uint64_t v64) +{ UniHash unih; + unih.h64 = v64; + return unih; +} + +UniHash uniHash128(XXH128_hash_t v128) +{ UniHash unih; + unih.h128 = v128; + return unih; +} + + +/* === xxHash === */ + +UniHash XXH3_wrapper (const void* data, size_t size) +{ + return uniHash64( XXH3_64bits(data, size) ); +} + +UniHash XXH128_wrapper (const void* data, size_t size) +{ + return uniHash128( XXH3_128bits(data, size) ); +} + +UniHash XXH128l_wrapper (const void* data, size_t size) +{ + return uniHash64( XXH3_128bits(data, size).low64 ); +} + +UniHash XXH128h_wrapper (const void* data, size_t size) +{ + return uniHash64( XXH3_128bits(data, size).high64 ); +} + +UniHash XXH64_wrapper (const void* data, size_t size) +{ + return uniHash64 ( XXH64(data, size, 0) ); +} + +UniHash XXH32_wrapper (const void* data, size_t size) +{ + return uniHash32( XXH32(data, size, 0) ); +} + +/* === Dummy integration example === */ + +#include "dummy.h" + +UniHash badsum32_wrapper (const void* data, size_t size) +{ + return uniHash32( badsum32(data, size, 0) ); +} + + + +/* === Table === */ + +typedef UniHash (*hashfn) (const void* data, size_t size); + +typedef struct { + const char* name; + hashfn fn; + int bits; +} hashDescription; + +#define HASH_FN_TOTAL 7 + +hashDescription hashfnTable[HASH_FN_TOTAL] = { + { "xxh3" , XXH3_wrapper, 64 }, + { "xxh64" , XXH64_wrapper, 64 }, + { "xxh128", XXH128_wrapper, 128 }, + { "xxh128l", XXH128l_wrapper, 64 }, + { "xxh128h", XXH128h_wrapper, 64 }, + { "xxh32" , XXH32_wrapper, 32 }, + { "badsum32",badsum32_wrapper, 32 }, +}; + +#endif /* HASHES_H_1235465 */ diff --git a/third_party/xxhash/tests/collisions/main.c b/third_party/xxhash/tests/collisions/main.c new file mode 100644 index 00000000000..a857341b5d2 --- /dev/null +++ b/third_party/xxhash/tests/collisions/main.c @@ -0,0 +1,1120 @@ +/* + * Brute force collision tester for 64-bit hashes + * Part of the xxHash project + * Copyright (C) 2019-2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * The collision tester will generate 24 billion hashes (by default), + * and count how many collisions were produced by the 64-bit hash algorithm. + * The optimal amount of collisions for 64-bit is ~18 collisions. + * A good hash should be close to this figure. + * + * This program requires a lot of memory: + * - Either store hash values directly => 192 GB + * - Or use a filter: + * - 32 GB (by default) for the filter itself + * - + ~14 GB for the list of hashes (depending on the filter's outcome) + * Due to these memory constraints, it requires a 64-bit system. + */ + + + /* === Dependencies === */ + +#include /* uint64_t */ +#include /* malloc, free, qsort, exit */ +#include /* memset */ +#include /* printf, fflush */ + +#undef NDEBUG /* ensure assert is _not_ disabled */ +#include + +#include "hashes.h" /* UniHash, hashfn, hashfnTable */ + +#include "sort.hh" /* sort64 */ + + + +typedef enum { ht32, ht64, ht128 } Htype_e; + +/* === Debug === */ + +#define EXIT(...) { printf(__VA_ARGS__); printf("\n"); exit(1); } + +static void hexRaw(const void* buffer, size_t size) +{ + const unsigned char* p = (const unsigned char*)buffer; + for (size_t i=0; i> 33; + h64 *= prime64_2; + h64 ^= h64 >> 29; + h64 *= prime64_3; + h64 ^= h64 >> 32; + return h64; +} + +static unsigned char randomByte(size_t n) +{ + uint64_t n64 = avalanche64(n+1); + n64 *= prime64_1; + return (unsigned char)(n64 >> 56); +} + +typedef enum { sf_slab5, sf_sparse } sf_genMode; + + +#ifdef SLAB5 + +/* + * Slab5 sample generation. + * This algorithm generates unique inputs flipping on average 16 bits per candidate. + * It is generally much more friendly for most hash algorithms, especially + * weaker ones, as it shuffles more the input. + * The algorithm also avoids overfitting the per4 or per8 ingestion patterns. + */ + +#define SLAB_SIZE 5 + +typedef struct { + void* buffer; + size_t size; + sf_genMode mode; + size_t prngSeed; + uint64_t hnb; +} sampleFactory; + +static void init_sampleFactory(sampleFactory* sf, uint64_t htotal) +{ + uint64_t const minNbSlabs = ((htotal-1) >> 32) + 1; + uint64_t const minSize = minNbSlabs * SLAB_SIZE; + if (sf->size < minSize) + EXIT("sample size must be >= %i bytes for this amount of hashes", + (int)minSize); + + unsigned char* const p = (unsigned char*)sf->buffer; + for (size_t n=0; n < sf->size; n++) + p[n] = randomByte(n); + sf->hnb = 0; +} + +static sampleFactory* +create_sampleFactory(size_t size, uint64_t htotal, uint64_t seed) +{ + sampleFactory* const sf = malloc(sizeof(sampleFactory)); + if (!sf) EXIT("not enough memory"); + void* const buffer = malloc(size); + if (!buffer) EXIT("not enough memory"); + sf->buffer = buffer; + sf->size = size; + sf->mode = sf_slab5; + sf->prngSeed = seed; + init_sampleFactory(sf, htotal); + return sf; +} + +static void free_sampleFactory(sampleFactory* sf) +{ + if (!sf) return; + free(sf->buffer); + free(sf); +} + +static inline void update_sampleFactory(sampleFactory* sf) +{ + size_t const nbSlabs = sf->size / SLAB_SIZE; + size_t const SlabNb = sf->hnb % nbSlabs; + sf->hnb++; + + char* const ptr = (char*)sf->buffer; + size_t const start = (SlabNb * SLAB_SIZE) + 1; + uint32_t val32; + memcpy(&val32, ptr+start, sizeof(val32)); + static const uint32_t prime32_5 = 374761393U; + val32 += prime32_5; + memcpy(ptr+start, &val32, sizeof(val32)); +} + +#else + +/* + * Sparse sample generation. + * This is the default pattern generator. + * It only flips one bit at a time (mostly). + * Low hamming distance scenario is more difficult for weak hash algorithms. + * Note that CRC is immune to this scenario, since they are specifically + * designed to detect low hamming distances. + * Prefer the Slab5 pattern generator for collisions on CRC algorithms. + */ + +#define SPARSE_LEVEL_MAX 15 + +/* Nb of combinations of m bits in a register of n bits */ +static double Cnm(int n, int m) +{ + assert(n > 0); + assert(m > 0); + assert(m <= m); + double acc = 1; + for (int i=0; i= SPARSE_LEVEL_MAX) return 0; + acc += (uint64_t)Cnm((int)srcBits, nbBitsSet); + } + return 1; +} + +typedef struct { + void* buffer; + size_t size; + sf_genMode mode; + /* sparse */ + size_t bitIdx[SPARSE_LEVEL_MAX]; + int level; + size_t maxBitIdx; + /* slab5 */ + size_t nbSlabs; + size_t current; + size_t prngSeed; +} sampleFactory; + +static void init_sampleFactory(sampleFactory* sf, uint64_t htotal) +{ + if (!enoughCombos(sf->size, htotal)) { + EXIT("sample size must be larger for this amount of hashes"); + } + + memset(sf->bitIdx, 0, sizeof(sf->bitIdx)); + sf->level = 0; + + unsigned char* const p = (unsigned char*)sf->buffer; + for (size_t n=0; nsize; n++) + p[n] = randomByte(sf->prngSeed + n); +} + +static sampleFactory* +create_sampleFactory(size_t size, uint64_t htotal, uint64_t seed) +{ + sampleFactory* const sf = malloc(sizeof(sampleFactory)); + if (!sf) EXIT("not enough memory"); + void* const buffer = malloc(size); + if (!buffer) EXIT("not enough memory"); + sf->buffer = buffer; + sf->size = size; + sf->mode = sf_sparse; + sf->maxBitIdx = size * 8; + sf->prngSeed = seed; + init_sampleFactory(sf, htotal); + return sf; +} + +static void free_sampleFactory(sampleFactory* sf) +{ + if (!sf) return; + free(sf->buffer); + free(sf); +} + +static void flipbit(void* buffer, uint64_t bitID) +{ + size_t const pos = bitID >> 3; + unsigned char const mask = (unsigned char)(1 << (bitID & 7)); + unsigned char* const p = (unsigned char*)buffer; + p[pos] ^= mask; +} + +static int updateBit(void* buffer, size_t* bitIdx, int level, size_t max) +{ + if (level==0) return 0; /* can't progress further */ + + flipbit(buffer, bitIdx[level]); /* erase previous bits */ + + if (bitIdx[level] < max-1) { /* simple case: go to next bit */ + bitIdx[level]++; + flipbit(buffer, bitIdx[level]); /* set new bit */ + return 1; + } + + /* reached last bit: need to update a bit from lower level */ + if (!updateBit(buffer, bitIdx, level-1, max-1)) return 0; + bitIdx[level] = bitIdx[level-1] + 1; + flipbit(buffer, bitIdx[level]); /* set new bit */ + return 1; +} + +static inline void update_sampleFactory(sampleFactory* sf) +{ + if (!updateBit(sf->buffer, sf->bitIdx, sf->level, sf->maxBitIdx)) { + /* no more room => move to next level */ + sf->level++; + assert(sf->level < SPARSE_LEVEL_MAX); + + /* set new bits */ + for (int i=1; i <= sf->level; i++) { + sf->bitIdx[i] = (size_t)(i-1); + flipbit(sf->buffer, sf->bitIdx[i]); + } + } +} + +#endif /* pattern generator selection */ + + +/* === Candidate Filter === */ + +typedef unsigned char Filter; + +Filter* create_Filter(int bflog) +{ + assert(bflog < 64 && bflog > 1); + size_t bfsize = (size_t)1 << bflog; + Filter* bf = malloc(bfsize); + assert(((void)"Filter creation failed", bf)); + memset(bf, 0, bfsize); + return bf; +} + +void free_Filter(Filter* bf) +{ + free(bf); +} + +#ifdef FILTER_1_PROBE + +/* + * Attach hash to a slot + * return: Nb of potential collision candidates detected + * 0: position not yet occupied + * 2: position previously occupied by a single candidate + * 1: position already occupied by multiple candidates + */ +inline int Filter_insert(Filter* bf, int bflog, uint64_t hash) +{ + int const slotNb = hash & 3; + int const shift = slotNb * 2 ; + + size_t const bfmask = ((size_t)1 << bflog) - 1; + size_t const pos = (hash >> 2) & bfmask; + + int const existingCandidates = ((((unsigned char*)bf)[pos]) >> shift) & 3; + + static const int addCandidates[4] = { 0, 2, 1, 1 }; + static const int nextValue[4] = { 1, 2, 3, 3 }; + + ((unsigned char*)bf)[pos] |= (unsigned char)(nextValue[existingCandidates] << shift); + return addCandidates[existingCandidates]; +} + +/* + * Check if provided 64-bit hash is a collision candidate + * Requires the slot to be occupied by at least 2 candidates. + * return >0 if hash is a collision candidate + * 0 otherwise (slot unoccupied, or only one candidate) + * note: unoccupied slots should not happen in this algorithm, + * since all hashes are supposed to have been inserted at least once. + */ +inline int Filter_check(const Filter* bf, int bflog, uint64_t hash) +{ + int const slotNb = hash & 3; + int const shift = slotNb * 2; + + size_t const bfmask = ((size_t)1 << bflog) - 1; + size_t const pos = (hash >> 2) & bfmask; + + return (((const unsigned char*)bf)[pos]) >> (shift+1) & 1; +} + +#else + +/* + * 2-probes strategy, + * more efficient at filtering candidates, + * requires filter size to be > nb of hashes + */ + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +/* + * Attach hash to 2 slots + * return: Nb of potential candidates detected + * 0: position not yet occupied + * 2: position previously occupied by a single candidate (at most) + * 1: position already occupied by multiple candidates + */ +static inline int Filter_insert(Filter* bf, int bflog, uint64_t hash) + { + hash = avalanche64(hash); + unsigned const slot1 = hash & 255; + hash >>= 8; + unsigned const slot2 = hash & 255; + hash >>= 8; + + size_t const fclmask = ((size_t)1 << (bflog-6)) - 1; + size_t const cacheLineNb = hash & fclmask; + + size_t const pos1 = (cacheLineNb << 6) + (slot1 >> 2); + unsigned const shift1 = (slot1 & 3) * 2; + unsigned const ex1 = (bf[pos1] >> shift1) & 3; + + size_t const pos2 = (cacheLineNb << 6) + (slot2 >> 2); + unsigned const shift2 = (slot2 & 3) * 2; + unsigned const ex2 = (bf[pos2] >> shift2) & 3; + + unsigned const existing = MIN(ex1, ex2); + + static const int addCandidates[4] = { 0, 2, 1, 1 }; + static const unsigned nextValue[4] = { 1, 2, 3, 3 }; + + bf[pos1] &= (Filter)(~(3 << shift1)); /* erase previous value */ + bf[pos1] |= (Filter)(MAX(ex1, nextValue[existing]) << shift1); + bf[pos2] |= (Filter)(MAX(ex2, nextValue[existing]) << shift2); + + return addCandidates[existing]; + } + + +/* + * Check if provided 64-bit hash is a collision candidate + * Requires the slot to be occupied by at least 2 candidates. + * return >0 if hash is a collision candidate + * 0 otherwise (slot unoccupied, or only one candidate) + * note: unoccupied slots should not happen in this algorithm, + * since all hashes are supposed to have been inserted at least once. + */ +static inline int Filter_check(const Filter* bf, int bflog, uint64_t hash) + { + hash = avalanche64(hash); + unsigned const slot1 = hash & 255; + hash >>= 8; + unsigned const slot2 = hash & 255; + hash >>= 8; + + size_t const fclmask = ((size_t)1 << (bflog-6)) - 1; + size_t const cacheLineNb = hash & fclmask; + + size_t const pos1 = (cacheLineNb << 6) + (slot1 >> 2); + unsigned const shift1 = (slot1 & 3) * 2; + unsigned const ex1 = (bf[pos1] >> shift1) & 3; + + size_t const pos2 = (cacheLineNb << 6) + (slot2 >> 2); + unsigned const shift2 = (slot2 & 3) * 2; + unsigned const ex2 = (bf[pos2] >> shift2) & 3; + + return (ex1 >= 2) && (ex2 >= 2); + } + +#endif // FILTER_1_PROBE + + +/* === Display === */ + +#include /* clock_t, clock, time_t, time, difftime */ + +void update_indicator(uint64_t v, uint64_t total) +{ + static clock_t start = 0; + if (start==0) start = clock(); + clock_t const updateRate = CLOCKS_PER_SEC / 2; + + clock_t const clockSpan = (clock_t)(clock() - start); + if (clockSpan > updateRate) { + start = clock(); + assert(v <= total); + assert(total > 0); + double share = ((double)v / (double)total) * 100; + printf("%6.2f%% (%llu) \r", share, (unsigned long long)v); + fflush(NULL); + } +} + +/* note: not thread safe */ +const char* displayDelay(double delay_s) +{ + static char delayString[50]; + memset(delayString, 0, sizeof(delayString)); + + int const mn = ((int)delay_s / 60) % 60; + int const h = (int)delay_s / 3600; + int const sec = (int)delay_s % 60; + + char* p = delayString; + if (h) sprintf(p, "%i h ", h); + if (mn || h) { + p = delayString + strlen(delayString); + sprintf(p, "%i mn ", mn); + } + p = delayString + strlen(delayString); + sprintf(p, "%is ", sec); + + return delayString; +} + + +/* === Math === */ + +static double power(uint64_t base, int p) +{ + double value = 1; + assert(p>=0); + for (int i=0; i>= 1) bitId++; + return bitId; +} + + +/* === Filter and search collisions === */ + +#undef NDEBUG /* ensure assert is not disabled */ +#include + +/* will recommend 24 billion samples for 64-bit hashes, + * expecting 18 collisions for a good 64-bit hash */ +#define NB_BITS_MAX 64 /* can't store nor analyze hash wider than 64-bits for the time being */ +uint64_t select_nbh(int nbBits) +{ + assert(nbBits > 0); + if (nbBits > NB_BITS_MAX) nbBits = NB_BITS_MAX; + double targetColls = (double)((128 + 17) - (nbBits * 2)); + uint64_t nbH = 24; + while (estimateNbCollisions(nbH, nbBits) < targetColls) nbH *= 2; + return nbH; +} + + +typedef struct { + uint64_t nbCollisions; +} searchCollisions_results; + +typedef struct { + uint64_t nbH; + uint64_t mask; + uint64_t maskSelector; + size_t sampleSize; + uint64_t prngSeed; + int filterLog; /* <0 = disable filter; 0 = auto-size; */ + int hashID; + int display; + int nbThreads; + searchCollisions_results* resultPtr; +} searchCollisions_parameters; + +#define DISPLAY(...) { if (display) printf(__VA_ARGS__); } + +static int isEqual(void* hTablePtr, size_t index1, size_t index2, Htype_e htype) +{ + if ((htype == ht64) || (htype == ht32)) { + uint64_t const h1 = ((const uint64_t*)hTablePtr)[index1]; + uint64_t const h2 = ((const uint64_t*)hTablePtr)[index2]; + return (h1 == h2); + } else { + assert(htype == ht128); + XXH128_hash_t const h1 = ((const XXH128_hash_t*)hTablePtr)[index1]; + XXH128_hash_t const h2 = ((const XXH128_hash_t*)hTablePtr)[index2]; + return XXH128_isEqual(h1, h2); + } +} + +static int isHighEqual(void* hTablePtr, size_t index1, size_t index2, Htype_e htype, int rShift) +{ + uint64_t h1, h2; + if ((htype == ht64) || (htype == ht32)) { + h1 = ((const uint64_t*)hTablePtr)[index1]; + h2 = ((const uint64_t*)hTablePtr)[index2]; + } else { + assert(htype == ht128); + h1 = ((const XXH128_hash_t*)hTablePtr)[index1].high64; + h2 = ((const XXH128_hash_t*)hTablePtr)[index2].high64; + assert(rShift >= 64); + rShift -= 64; + } + assert(0 <= rShift && rShift < 64); + return (h1 >> rShift) == (h2 >> rShift); +} + +/* assumption: (htype*)hTablePtr[index] is valid */ +static void addHashCandidate(void* hTablePtr, UniHash h, Htype_e htype, size_t index) +{ + if ((htype == ht64) || (htype == ht32)) { + ((uint64_t*)hTablePtr)[index] = h.h64; + } else { + assert(htype == ht128); + ((XXH128_hash_t*)hTablePtr)[index] = h.h128; + } +} + +static int getNbBits_fromHtype(Htype_e htype) { + switch(htype) { + case ht32: return 32; + case ht64: return 64; + case ht128:return 128; + default: EXIT("hash size not supported"); + } +} + +static Htype_e getHtype_fromHbits(int nbBits) { + switch(nbBits) { + case 32 : return ht32; + case 64 : return ht64; + case 128: return ht128; + default: EXIT("hash size not supported"); + } +} + +static size_t search_collisions( + searchCollisions_parameters param) +{ + uint64_t totalH = param.nbH; + const uint64_t hMask = param.mask; + const uint64_t hSelector = param.maskSelector; + int bflog = param.filterLog; + const int filter = (param.filterLog >= 0); + const size_t sampleSize = param.sampleSize; + const int hashID = param.hashID; + const Htype_e htype = getHtype_fromHbits(hashfnTable[hashID].bits); + const int display = param.display; + /* init */ + sampleFactory* const sf = create_sampleFactory(sampleSize, totalH, param.prngSeed); + if (!sf) EXIT("not enough memory"); + + //const char* const hname = hashfnTable[hashID].name; + hashfn const hfunction = hashfnTable[hashID].fn; + int const hwidth = hashfnTable[hashID].bits; + if (totalH == 0) totalH = select_nbh(hwidth); + if (bflog == 0) bflog = highestBitSet(totalH) + 1; /* auto-size filter */ + uint64_t const bfsize = (1ULL << bflog); + + + /* === filter hashes (optional) === */ + + Filter* bf = NULL; + uint64_t nbPresents = totalH; + + if (filter) { + time_t const filterTBegin = time(NULL); + DISPLAY(" Creating filter (%i GB) \n", (int)(bfsize >> 30)); + bf = create_Filter(bflog); + if (!bf) EXIT("not enough memory for filter"); + + + DISPLAY(" Generate %llu hashes from samples of %u bytes \n", + (unsigned long long)totalH, (unsigned)sampleSize); + nbPresents = 0; + + for (uint64_t n=0; n < totalH; n++) { + if (display && ((n&0xFFFFF) == 1) ) + update_indicator(n, totalH); + update_sampleFactory(sf); + + UniHash const h = hfunction(sf->buffer, sampleSize); + if ((h.h64 & hMask) != hSelector) continue; + + nbPresents += (uint64_t)Filter_insert(bf, bflog, h.h64); + } + + if (nbPresents==0) { + DISPLAY(" Analysis completed: No collision detected \n"); + if (param.resultPtr) param.resultPtr->nbCollisions = 0; + free_Filter(bf); + free_sampleFactory(sf); + return 0; + } + + { double const filterDelay = difftime(time(NULL), filterTBegin); + DISPLAY(" Generation and filter completed in %s, detected up to %llu candidates \n", + displayDelay(filterDelay), (unsigned long long) nbPresents); + } } + + + /* === store hash candidates: duplicates will be present here === */ + + time_t const storeTBegin = time(NULL); + size_t const hashByteSize = (htype == ht128) ? 16 : 8; + size_t const tableSize = (nbPresents+1) * hashByteSize; + assert(tableSize > nbPresents); /* check tableSize calculation overflow */ + DISPLAY(" Storing hash candidates (%i MB) \n", (int)(tableSize >> 20)); + + /* Generate and store hashes */ + void* const hashCandidates = malloc(tableSize); + if (!hashCandidates) EXIT("not enough memory to store candidates"); + init_sampleFactory(sf, totalH); + size_t nbCandidates = 0; + for (uint64_t n=0; n < totalH; n++) { + if (display && ((n&0xFFFFF) == 1) ) update_indicator(n, totalH); + update_sampleFactory(sf); + + UniHash const h = hfunction(sf->buffer, sampleSize); + if ((h.h64 & hMask) != hSelector) continue; + + if (filter) { + if (Filter_check(bf, bflog, h.h64)) { + assert(nbCandidates < nbPresents); + addHashCandidate(hashCandidates, h, htype, nbCandidates++); + } + } else { + assert(nbCandidates < nbPresents); + addHashCandidate(hashCandidates, h, htype, nbCandidates++); + } + } + if (nbCandidates < nbPresents) { + /* Try to mitigate gnuc_quicksort behavior, by reducing allocated memory, + * since gnuc_quicksort uses a lot of additional memory for mergesort */ + void* const checkPtr = realloc(hashCandidates, nbCandidates * hashByteSize); + assert(checkPtr != NULL); + assert(checkPtr == hashCandidates); /* simplification: since we are reducing the size, + * we hope to keep the same ptr position. + * Otherwise, hashCandidates must be mutable. */ + DISPLAY(" List of hashes reduced to %u MB from %u MB (saved %u MB) \n", + (unsigned)((nbCandidates * hashByteSize) >> 20), + (unsigned)(tableSize >> 20), + (unsigned)((tableSize - (nbCandidates * hashByteSize)) >> 20) ); + } + double const storeTDelay = difftime(time(NULL), storeTBegin); + DISPLAY(" Stored %llu hash candidates in %s \n", + (unsigned long long) nbCandidates, displayDelay(storeTDelay)); + free_Filter(bf); + free_sampleFactory(sf); + + + /* === step 3: look for duplicates === */ + time_t const sortTBegin = time(NULL); + DISPLAY(" Sorting candidates... "); + fflush(NULL); + if ((htype == ht64) || (htype == ht32)) { + /* + * Use C++'s std::sort, as it's faster than C stdlib's qsort, and + * doesn't suffer from gnuc_libsort's memory expansion + */ + sort64(hashCandidates, nbCandidates); + } else { + assert(htype == ht128); + sort128(hashCandidates, nbCandidates); /* sort with custom comparator */ + } + double const sortTDelay = difftime(time(NULL), sortTBegin); + DISPLAY(" Completed in %s \n", displayDelay(sortTDelay)); + + /* scan and count duplicates */ + time_t const countBegin = time(NULL); + DISPLAY(" Looking for duplicates: "); + fflush(NULL); + size_t collisions = 0; + for (size_t n=1; n nbCandidates * 100) /* within range for meaningfull collision analysis results */ + && (expectedCollisions > 18.0) ) { + int const rShift = hashBits - nbHBits; + size_t HBits_collisions = 0; + for (size_t n=1; n 2.0) DISPLAY("WARNING !!! ===> "); + DISPLAY(" high %i bits: %zu collision (%.1f expected): x%.2f \n", + nbHBits, HBits_collisions, expectedCollisions, collisionRatio); + if (collisionRatio > worstRatio) { + worstNbHBits = nbHBits; + worstRatio = collisionRatio; + } } } + DISPLAY("Worst collision ratio at %i high bits: x%.2f \n", + worstNbHBits, worstRatio); + } + double const countDelay = difftime(time(NULL), countBegin); + DISPLAY(" Completed in %s \n", displayDelay(countDelay)); + + /* clean and exit */ + free (hashCandidates); + +#if 0 /* debug */ + for (size_t n=0; nnbCollisions = collisions; + return collisions; +} + + + +#if defined(__MACH__) || defined(__linux__) +#include +static size_t getProcessMemUsage(int children) +{ + struct rusage stats; + if (getrusage(children ? RUSAGE_CHILDREN : RUSAGE_SELF, &stats) == 0) + return (size_t)stats.ru_maxrss; + return 0; +} +#else +static size_t getProcessMemUsage(int ignore) { return 0; } +#endif + +void time_collisions(searchCollisions_parameters param) +{ + uint64_t totalH = param.nbH; + int hashID = param.hashID; + int display = param.display; + + /* init */ + assert(0 <= hashID && hashID < HASH_FN_TOTAL); + //const char* const hname = hashfnTable[hashID].name; + int const hwidth = hashfnTable[hashID].bits; + if (totalH == 0) totalH = select_nbh(hwidth); + double const targetColls = estimateNbCollisions(totalH, hwidth); + + /* Start the timer to measure start/end of hashing + collision detection. */ + time_t const programTBegin = time(NULL); + + /* Generate hashes, and count collisions */ + size_t const collisions = search_collisions(param); + + /* display results */ + double const programTDelay = difftime(time(NULL), programTBegin); + size_t const programBytesSelf = getProcessMemUsage(0); + size_t const programBytesChildren = getProcessMemUsage(1); + DISPLAY("\n\n"); + DISPLAY("===> Found %llu collisions (x%.2f, %.1f expected) in %s\n", + (unsigned long long)collisions, + (double)collisions / targetColls, + targetColls, + displayDelay(programTDelay)); + if (programBytesSelf) + DISPLAY("===> MaxRSS(self) %zuMB, MaxRSS(children) %zuMB\n", + programBytesSelf>>20, + programBytesChildren>>20); + DISPLAY("------------------------------------------ \n"); +} + +// wrapper for pthread interface +void MT_searchCollisions(void* payload) +{ + search_collisions(*(searchCollisions_parameters*)payload); +} + +/* === Command Line === */ + +/*! + * readU64FromChar(): + * Allows and interprets K, KB, KiB, M, MB and MiB suffix. + * Will also modify `*stringPtr`, advancing it to the position where it stopped reading. + */ +static uint64_t readU64FromChar(const char** stringPtr) +{ + static uint64_t const max = (((uint64_t)(-1)) / 10) - 1; + uint64_t result = 0; + while ((**stringPtr >='0') && (**stringPtr <='9')) { + assert(result < max); + result *= 10; + result += (unsigned)(**stringPtr - '0'); + (*stringPtr)++ ; + } + if ((**stringPtr=='K') || (**stringPtr=='M') || (**stringPtr=='G')) { + uint64_t const maxK = ((uint64_t)(-1)) >> 10; + assert(result < maxK); + result <<= 10; + if ((**stringPtr=='M') || (**stringPtr=='G')) { + assert(result < maxK); + result <<= 10; + if (**stringPtr=='G') { + assert(result < maxK); + result <<= 10; + } + } + (*stringPtr)++; /* skip `K` or `M` */ + if (**stringPtr=='i') (*stringPtr)++; + if (**stringPtr=='B') (*stringPtr)++; + } + return result; +} + + +/** + * longCommandWArg(): + * Checks if *stringPtr is the same as longCommand. + * If yes, @return 1 and advances *stringPtr to the position which immediately follows longCommand. + * @return 0 and doesn't modify *stringPtr otherwise. + */ +static int longCommandWArg(const char** stringPtr, const char* longCommand) +{ + assert(longCommand); assert(stringPtr); assert(*stringPtr); + size_t const comSize = strlen(longCommand); + int const result = !strncmp(*stringPtr, longCommand, comSize); + if (result) *stringPtr += comSize; + return result; +} + + +#include "pool.h" + +/* + * As some hashes use different algorithms depending on input size, + * it can be necessary to test multiple input sizes + * to paint an accurate picture of collision performance + */ +#define SAMPLE_SIZE_DEFAULT 256 +#define HASHFN_ID_DEFAULT 0 + +void help(const char* exeName) +{ + printf("usage: %s [hashName] [opt] \n\n", exeName); + printf("list of hashNames:"); + printf("%s ", hashfnTable[0].name); + for (int i=1; i < HASH_FN_TOTAL; i++) { + printf(", %s ", hashfnTable[i].name); + } + printf(" \n"); + printf("Default hashName is %s\n", hashfnTable[HASHFN_ID_DEFAULT].name); + + printf(" \n"); + printf("Optional parameters: \n"); + printf(" --nbh=NB Select nb of hashes to generate (%llu by default) \n", (unsigned long long)select_nbh(64)); + printf(" --filter Activates the filter. Slower, but reduces memory usage for the same nb of hashes.\n"); + printf(" --threadlog=NB Use 2^NB threads.\n"); + printf(" --len=MB Set length of the input (%i bytes by default) \n", SAMPLE_SIZE_DEFAULT); +} + +int bad_argument(const char* exeName) +{ + printf("incorrect command: \n"); + help(exeName); + return 1; +} + + +int main(int argc, const char** argv) +{ + if (sizeof(size_t) < 8) return 1; // cannot work on systems without ability to allocate objects >= 4 GB + + assert(argc > 0); + const char* const exeName = argv[0]; + uint64_t totalH = 0; /* auto, based on nbBits */ + int bflog = 0; /* auto */ + int filter = 0; /* disabled */ + size_t sampleSize = SAMPLE_SIZE_DEFAULT; + int hashID = HASHFN_ID_DEFAULT; + int threadlog = 0; + uint64_t prngSeed = 0; + + int arg_nb; + for (arg_nb = 1; arg_nb < argc; arg_nb++) { + const char** arg = argv + arg_nb; + + if (!strcmp(*arg, "-h")) { help(exeName); return 0; } + if (longCommandWArg(arg, "-T")) { threadlog = (int)readU64FromChar(arg); continue; } + + if (!strcmp(*arg, "--filter")) { filter=1; continue; } + if (!strcmp(*arg, "--no-filter")) { filter=0; continue; } + + if (longCommandWArg(arg, "--seed")) { prngSeed = readU64FromChar(arg); continue; } + if (longCommandWArg(arg, "--nbh=")) { totalH = readU64FromChar(arg); continue; } + if (longCommandWArg(arg, "--filter=")) { filter=1; bflog = (int)readU64FromChar(arg); assert(bflog < 64); continue; } + if (longCommandWArg(arg, "--filterlog=")) { filter=1; bflog = (int)readU64FromChar(arg); assert(bflog < 64); continue; } + if (longCommandWArg(arg, "--size=")) { sampleSize = (size_t)readU64FromChar(arg); continue; } + if (longCommandWArg(arg, "--len=")) { sampleSize = (size_t)readU64FromChar(arg); continue; } + if (longCommandWArg(arg, "--threadlog=")) { threadlog = (int)readU64FromChar(arg); continue; } + + /* argument understood as hash name (must be correct) */ + int hnb; + for (hnb=0; hnb < HASH_FN_TOTAL; hnb++) { + if (!strcmp(*arg, hashfnTable[hnb].name)) { hashID = hnb; break; } + } + if (hnb == HASH_FN_TOTAL) return bad_argument(exeName); + } + + /* init */ + const char* const hname = hashfnTable[hashID].name; + int const hwidth = hashfnTable[hashID].bits; + if (totalH == 0) totalH = select_nbh(hwidth); + double const targetColls = estimateNbCollisions(totalH, hwidth); + if (bflog == 0) bflog = highestBitSet(totalH) + 1; /* auto-size filter */ + if (!filter) bflog = -1; // disable filter + + if (sizeof(size_t) < 8) + EXIT("This program has not been validated on architectures other than " + "64bit \n"); + + printf(" *** Collision tester for 64+ bit hashes *** \n\n"); + printf("Testing %s algorithm (%i-bit) \n", hname, hwidth); + printf("This program will allocate a lot of memory,\n"); + printf("generate %llu %i-bit hashes from samples of %u bytes, \n", + (unsigned long long)totalH, hwidth, (unsigned)sampleSize); + printf("and attempt to produce %.0f collisions. \n\n", targetColls); + + int const nbThreads = 1 << threadlog; + if (nbThreads <= 0) EXIT("Invalid --threadlog value."); + + if (nbThreads == 1) { + + searchCollisions_parameters params; + params.nbH = totalH; + params.mask = 0; + params.maskSelector = 0; + params.sampleSize = sampleSize; + params.filterLog = bflog; + params.hashID = hashID; + params.display = 1; + params.resultPtr = NULL; + params.prngSeed = prngSeed; + params.nbThreads = 1; + time_collisions(params); + + } else { /* nbThreads > 1 */ + + /* use multithreading */ + if (threadlog >= 30) EXIT("too many threads requested"); + if ((uint64_t)nbThreads > (totalH >> 16)) + EXIT("too many threads requested"); + if (bflog > 0 && threadlog > (bflog-10)) + EXIT("too many threads requested"); + printf("using %i threads ... \n", nbThreads); + + /* allocation */ + time_t const programTBegin = time(NULL); + POOL_ctx* const pt = POOL_create((size_t)nbThreads, 1); + if (!pt) EXIT("not enough memory for threads"); + searchCollisions_results* const MTresults = calloc (sizeof(searchCollisions_results), (size_t)nbThreads); + if (!MTresults) EXIT("not enough memory"); + searchCollisions_parameters* const MTparams = calloc (sizeof(searchCollisions_parameters), (size_t)nbThreads); + if (!MTparams) EXIT("not enough memory"); + + /* distribute jobs */ + for (int tnb=0; tnb Found %llu collisions (x%.2f, %.1f expected) in %s\n", + (unsigned long long)nbCollisions, + (double)nbCollisions / targetColls, + targetColls, + displayDelay(programTDelay)); + if (programBytesSelf) + printf("===> MaxRSS(self) %zuMB, MaxRSS(children) %zuMB\n", + programBytesSelf>>20, + programBytesChildren>>20); + printf("------------------------------------------ \n"); + + /* Clean up */ + free(MTparams); + free(MTresults); + } + + return 0; +} diff --git a/third_party/xxhash/tests/collisions/pool.c b/third_party/xxhash/tests/collisions/pool.c new file mode 100644 index 00000000000..c0eaefd4767 --- /dev/null +++ b/third_party/xxhash/tests/collisions/pool.c @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2016-2020 Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + + +/* ====== Dependencies ======= */ +#include /* size_t */ +#include /* malloc, calloc, free */ +#include /* memcpy */ +#include + +#include "pool.h" + + +/* ====== Compiler specifics ====== */ +#if defined(_MSC_VER) +# pragma warning(disable : 4204) /* disable: C4204: non-constant aggregate initializer */ +#endif + + +/* === Build Macro === */ + +#ifndef POOL_MT // can be defined on command line +# define POOL_MT 1 +#endif + + +/* === Implementation === */ + +#if POOL_MT + +#include "threading.h" /* pthread adaptation */ + +/* A job is a function and an opaque argument */ +typedef struct POOL_job_s { + POOL_function function; + void *opaque; +} POOL_job; + +struct POOL_ctx_s { + /* Keep track of the threads */ + ZSTD_pthread_t* threads; + size_t threadCapacity; + size_t threadLimit; + + /* The queue is a circular buffer */ + POOL_job *queue; + size_t queueHead; + size_t queueTail; + size_t queueSize; + + /* The number of threads working on jobs */ + size_t numThreadsBusy; + /* Indicates if the queue is empty */ + int queueEmpty; + + /* The mutex protects the queue */ + ZSTD_pthread_mutex_t queueMutex; + /* Condition variable for pushers to wait on when the queue is full */ + ZSTD_pthread_cond_t queuePushCond; + /* Condition variables for poppers to wait on when the queue is empty */ + ZSTD_pthread_cond_t queuePopCond; + /* Indicates if the queue is shutting down */ + int shutdown; +}; + +/* POOL_thread() : + * Work thread for the thread pool. + * Waits for jobs and executes them. + * @returns : NULL on failure else non-null. + */ +static void* POOL_thread(void* opaque) +{ + POOL_ctx* const ctx = (POOL_ctx*)opaque; + if (!ctx) { return NULL; } + for (;;) { + /* Lock the mutex and wait for a non-empty queue or until shutdown */ + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + + while ( ctx->queueEmpty + || (ctx->numThreadsBusy >= ctx->threadLimit) ) { + if (ctx->shutdown) { + /* even if !queueEmpty, (possible if numThreadsBusy >= threadLimit), + * a few threads will be shutdown while !queueEmpty, + * but enough threads will remain active to finish the queue */ + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return opaque; + } + ZSTD_pthread_cond_wait(&ctx->queuePopCond, &ctx->queueMutex); + } + /* Pop a job off the queue */ + { POOL_job const job = ctx->queue[ctx->queueHead]; + ctx->queueHead = (ctx->queueHead + 1) % ctx->queueSize; + ctx->numThreadsBusy++; + ctx->queueEmpty = ctx->queueHead == ctx->queueTail; + /* Unlock the mutex, signal a pusher, and run the job */ + ZSTD_pthread_cond_signal(&ctx->queuePushCond); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + + job.function(job.opaque); + + /* If the intended queue size was 0, signal after finishing job */ + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + ctx->numThreadsBusy--; + if (ctx->queueSize == 1) { + ZSTD_pthread_cond_signal(&ctx->queuePushCond); + } + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + } + } /* for (;;) */ + assert(0); /* Unreachable */ +} + +POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) +{ + POOL_ctx* ctx; + /* Check parameters */ + if (!numThreads) { return NULL; } + /* Allocate the context and zero initialize */ + ctx = (POOL_ctx*)calloc(1, sizeof(POOL_ctx)); + if (!ctx) { return NULL; } + /* Initialize the job queue. + * It needs one extra space since one space is wasted to differentiate + * empty and full queues. + */ + ctx->queueSize = queueSize + 1; + ctx->queue = (POOL_job*)malloc(ctx->queueSize * sizeof(POOL_job)); + ctx->queueHead = 0; + ctx->queueTail = 0; + ctx->numThreadsBusy = 0; + ctx->queueEmpty = 1; + (void)ZSTD_pthread_mutex_init(&ctx->queueMutex, NULL); + (void)ZSTD_pthread_cond_init(&ctx->queuePushCond, NULL); + (void)ZSTD_pthread_cond_init(&ctx->queuePopCond, NULL); + ctx->shutdown = 0; + /* Allocate space for the thread handles */ + ctx->threads = (ZSTD_pthread_t*)malloc(numThreads * sizeof(ZSTD_pthread_t)); + ctx->threadCapacity = 0; + /* Check for errors */ + if (!ctx->threads || !ctx->queue) { POOL_free(ctx); return NULL; } + /* Initialize the threads */ + { size_t i; + for (i = 0; i < numThreads; ++i) { + if (ZSTD_pthread_create(&ctx->threads[i], NULL, &POOL_thread, ctx)) { + ctx->threadCapacity = i; + POOL_free(ctx); + return NULL; + } } + ctx->threadCapacity = numThreads; + ctx->threadLimit = numThreads; + } + return ctx; +} + +/*! POOL_join() : + Shutdown the queue, wake any sleeping threads, and join all of the threads. +*/ +static void POOL_join(POOL_ctx* ctx) { + /* Shut down the queue */ + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + ctx->shutdown = 1; + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + + /* Wake up sleeping threads */ + ZSTD_pthread_cond_broadcast(&ctx->queuePushCond); + ZSTD_pthread_cond_broadcast(&ctx->queuePopCond); + + /* Join all of the threads */ + { size_t i; + for (i = 0; i < ctx->threadCapacity; ++i) { + ZSTD_pthread_join(ctx->threads[i], NULL); /* note : could fail */ + } } +} + +void POOL_free(POOL_ctx *ctx) { + if (!ctx) { return; } + POOL_join(ctx); + ZSTD_pthread_mutex_destroy(&ctx->queueMutex); + ZSTD_pthread_cond_destroy(&ctx->queuePushCond); + ZSTD_pthread_cond_destroy(&ctx->queuePopCond); + free(ctx->queue); + free(ctx->threads); + free(ctx); +} + + + +size_t POOL_sizeof(POOL_ctx *ctx) { + if (ctx==NULL) return 0; /* supports sizeof NULL */ + return sizeof(*ctx) + + ctx->queueSize * sizeof(POOL_job) + + ctx->threadCapacity * sizeof(ZSTD_pthread_t); +} + + +/* @return : 0 on success, 1 on error */ +static int POOL_resize_internal(POOL_ctx* ctx, size_t numThreads) +{ + if (numThreads <= ctx->threadCapacity) { + if (!numThreads) return 1; + ctx->threadLimit = numThreads; + return 0; + } + /* numThreads > threadCapacity */ + { ZSTD_pthread_t* const threadPool = (ZSTD_pthread_t*)malloc(numThreads * sizeof(ZSTD_pthread_t)); + if (!threadPool) return 1; + /* replace existing thread pool */ + memcpy(threadPool, ctx->threads, ctx->threadCapacity * sizeof(*threadPool)); + free(ctx->threads); + ctx->threads = threadPool; + /* Initialize additional threads */ + { size_t threadId; + for (threadId = ctx->threadCapacity; threadId < numThreads; ++threadId) { + if (ZSTD_pthread_create(&threadPool[threadId], NULL, &POOL_thread, ctx)) { + ctx->threadCapacity = threadId; + return 1; + } } + } } + /* successfully expanded */ + ctx->threadCapacity = numThreads; + ctx->threadLimit = numThreads; + return 0; +} + +/* @return : 0 on success, 1 on error */ +int POOL_resize(POOL_ctx* ctx, size_t numThreads) +{ + int result; + if (ctx==NULL) return 1; + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + result = POOL_resize_internal(ctx, numThreads); + ZSTD_pthread_cond_broadcast(&ctx->queuePopCond); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return result; +} + +/** + * Returns 1 if the queue is full and 0 otherwise. + * + * When queueSize is 1 (pool was created with an intended queueSize of 0), + * then a queue is empty if there is a thread free _and_ no job is waiting. + */ +static int isQueueFull(POOL_ctx const* ctx) { + if (ctx->queueSize > 1) { + return ctx->queueHead == ((ctx->queueTail + 1) % ctx->queueSize); + } else { + return (ctx->numThreadsBusy == ctx->threadLimit) || + !ctx->queueEmpty; + } +} + + +static void POOL_add_internal(POOL_ctx* ctx, POOL_function function, void *opaque) +{ + POOL_job const job = {function, opaque}; + assert(ctx != NULL); + if (ctx->shutdown) return; + + ctx->queueEmpty = 0; + ctx->queue[ctx->queueTail] = job; + ctx->queueTail = (ctx->queueTail + 1) % ctx->queueSize; + ZSTD_pthread_cond_signal(&ctx->queuePopCond); +} + +void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) +{ + assert(ctx != NULL); + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + /* Wait until there is space in the queue for the new job */ + while (isQueueFull(ctx) && (!ctx->shutdown)) { + ZSTD_pthread_cond_wait(&ctx->queuePushCond, &ctx->queueMutex); + } + POOL_add_internal(ctx, function, opaque); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); +} + + +int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) +{ + assert(ctx != NULL); + ZSTD_pthread_mutex_lock(&ctx->queueMutex); + if (isQueueFull(ctx)) { + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return 0; + } + POOL_add_internal(ctx, function, opaque); + ZSTD_pthread_mutex_unlock(&ctx->queueMutex); + return 1; +} + + +#else /* POOL_MT not defined */ + +/* ========================== */ +/* No multi-threading support */ +/* ========================== */ + + +/* We don't need any data, but if it is empty, malloc() might return NULL. */ +struct POOL_ctx_s { + int dummy; +}; +static POOL_ctx g_ctx; + +POOL_ctx* POOL_create(size_t numThreads, size_t queueSize) { + (void)numThreads; + (void)queueSize; + return &g_ctx; +} + +void POOL_free(POOL_ctx* ctx) { + assert(!ctx || ctx == &g_ctx); + (void)ctx; +} + +int POOL_resize(POOL_ctx* ctx, size_t numThreads) { + (void)ctx; (void)numThreads; + return 0; +} + +void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque) { + (void)ctx; + function(opaque); +} + +int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque) { + (void)ctx; + function(opaque); + return 1; +} + +size_t POOL_sizeof(POOL_ctx* ctx) { + if (ctx==NULL) return 0; /* supports sizeof NULL */ + assert(ctx == &g_ctx); + return sizeof(*ctx); +} + +#endif /* ZSTD_MULTITHREAD */ diff --git a/third_party/xxhash/tests/collisions/pool.h b/third_party/xxhash/tests/collisions/pool.h new file mode 100644 index 00000000000..7c5e867d2f4 --- /dev/null +++ b/third_party/xxhash/tests/collisions/pool.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016-2020 Yann Collet, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * You may select, at your option, one of the above-listed licenses. + */ + +#ifndef POOL_H +#define POOL_H + +#if defined (__cplusplus) +extern "C" { +#endif + + +#include /* size_t */ + +typedef struct POOL_ctx_s POOL_ctx; + +/*! POOL_create() : + * Create a thread pool with at most `numThreads` threads. + * `numThreads` must be at least 1. + * The maximum number of queued jobs before blocking is `queueSize`. + * @return : POOL_ctx pointer on success, else NULL. +*/ +POOL_ctx* POOL_create(size_t numThreads, size_t queueSize); + +/*! POOL_free() : + * Free a thread pool returned by POOL_create(). + */ +void POOL_free(POOL_ctx* ctx); + +/*! POOL_resize() : + * Expands or shrinks pool's number of threads. + * This is more efficient than releasing + creating a new context, + * since it tries to preserve and re-use existing threads. + * `numThreads` must be at least 1. + * @return : 0 when resize was successful, + * !0 (typically 1) if there is an error. + * note : only numThreads can be resized, queueSize remains unchanged. + */ +int POOL_resize(POOL_ctx* ctx, size_t numThreads); + +/*! POOL_sizeof() : + * @return threadpool memory usage + * note : compatible with NULL (returns 0 in this case) + */ +size_t POOL_sizeof(POOL_ctx* ctx); + +/*! POOL_function : + * The function type that can be added to a thread pool. + */ +typedef void (*POOL_function)(void*); + +/*! POOL_add() : + * Add the job `function(opaque)` to the thread pool. `ctx` must be valid. + * Possibly blocks until there is room in the queue. + * Note : The function may be executed asynchronously, + * therefore, `opaque` must live until function has been completed. + */ +void POOL_add(POOL_ctx* ctx, POOL_function function, void* opaque); + + +/*! POOL_tryAdd() : + * Add the job `function(opaque)` to thread pool _if_ a worker is available. + * Returns immediately even if not (does not block). + * @return : 1 if successful, 0 if not. + */ +int POOL_tryAdd(POOL_ctx* ctx, POOL_function function, void* opaque); + + + +#if defined (__cplusplus) +} +#endif + +#endif diff --git a/third_party/xxhash/tests/collisions/sort.cc b/third_party/xxhash/tests/collisions/sort.cc new file mode 100644 index 00000000000..237a114fc9c --- /dev/null +++ b/third_party/xxhash/tests/collisions/sort.cc @@ -0,0 +1,59 @@ +/* + * sort.cc - C++ sort functions + * Copyright (C) 2019-2020 Yann Collet + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * C++ sort functions tend to run faster than C ones due to templates allowing + * inline optimizations. + * Also, glibc's qsort() seems to inflate memory usage, resulting in OOM + * crashes on the test server. + */ + +#include // std::sort +#define XXH_INLINE_ALL // XXH128_cmp +#include + +#include "sort.hh" + +void sort64(uint64_t* table, size_t size) +{ + std::sort(table, table + size); +} + +#include // qsort + +void sort128(XXH128_hash_t* table, size_t size) +{ +#if 0 + // C++ sort using a custom function object + struct { + bool operator()(XXH128_hash_t a, XXH128_hash_t b) const + { + return XXH128_cmp(&a, &b); + } + } customLess; + std::sort(table, table + size, customLess); +#else + qsort(table, size, sizeof(*table), XXH128_cmp); +#endif +} diff --git a/third_party/xxhash/tests/collisions/sort.hh b/third_party/xxhash/tests/collisions/sort.hh new file mode 100644 index 00000000000..278ce05c65f --- /dev/null +++ b/third_party/xxhash/tests/collisions/sort.hh @@ -0,0 +1,40 @@ +/* + * sort.hh - headers for C++ sort functions + * Copyright (C) 2019-2020 Yann Collet + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at : + * - xxHash homepage : https://www.xxhash.com + * - xxHash source repository : https://github.com/Cyan4973/xxHash + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include // size +#include // uint64_t +#define XXH_STATIC_LINKING_ONLY // XXH128_hash_t +#include "xxhash.h" + +void sort64(uint64_t* table, size_t size); + +void sort128(XXH128_hash_t* table, size_t size); + +#ifdef __cplusplus +} // extern C +#endif diff --git a/third_party/xxhash/tests/collisions/threading.c b/third_party/xxhash/tests/collisions/threading.c new file mode 100644 index 00000000000..51646671923 --- /dev/null +++ b/third_party/xxhash/tests/collisions/threading.c @@ -0,0 +1,82 @@ +/** + * Copyright (c) 2016 Tino Reichardt + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * + * You can contact the author at: + * - zstdmt source repository: https://github.com/mcmilk/zstdmt + */ + +/** + * This file will hold wrapper for systems, which do not support pthreads + */ + + + /* === Build Macro === */ + + #ifndef POOL_MT // can be defined on command line + # define POOL_MT 1 + #endif + + +/* create fake symbol to avoid empty translation unit warning */ +int g_ZSTD_threading_useles_symbol; + +#if POOL_MT && defined(_WIN32) + +/** + * Windows minimalist Pthread Wrapper + */ + + +/* === Dependencies === */ +#include +#include +#include "threading.h" + + +/* === Implementation === */ + +static unsigned __stdcall worker(void *arg) +{ + ZSTD_pthread_t* const thread = (ZSTD_pthread_t*) arg; + thread->arg = thread->start_routine(thread->arg); + return 0; +} + +int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused, + void* (*start_routine) (void*), void* arg) +{ + (void)unused; + thread->arg = arg; + thread->start_routine = start_routine; + thread->handle = (HANDLE) _beginthreadex(NULL, 0, worker, thread, 0, NULL); + + if (!thread->handle) + return errno; + else + return 0; +} + +int ZSTD_pthread_join(ZSTD_pthread_t thread, void **value_ptr) +{ + DWORD result; + + if (!thread.handle) return 0; + + result = WaitForSingleObject(thread.handle, INFINITE); + switch (result) { + case WAIT_OBJECT_0: + if (value_ptr) *value_ptr = thread.arg; + return 0; + case WAIT_ABANDONED: + return EINVAL; + default: + return (int)GetLastError(); + } +} + +#endif /* POOL_MT */ diff --git a/third_party/xxhash/tests/collisions/threading.h b/third_party/xxhash/tests/collisions/threading.h new file mode 100644 index 00000000000..700bf44269b --- /dev/null +++ b/third_party/xxhash/tests/collisions/threading.h @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2016 Tino Reichardt + * All rights reserved. + * + * This source code is licensed under both the BSD-style license (found in the + * LICENSE file in the root directory of this source tree) and the GPLv2 (found + * in the COPYING file in the root directory of this source tree). + * + * You can contact the author at: + * - zstdmt source repository: https://github.com/mcmilk/zstdmt + */ + +#ifndef THREADING_H_938743 +#define THREADING_H_938743 + +#if defined (__cplusplus) +extern "C" { +#endif + +/* === Build Macro === */ + +#ifndef POOL_MT // can be defined on command line +# define POOL_MT 1 +#endif + + +/* === Implementation === */ + +#if POOL_MT && defined(_WIN32) + +/** + * Define windows version before include + */ +#undef WINVER +#define WINVER 0x0600 + +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0600 + +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#include +#include + +/* mutex */ +#define ZSTD_pthread_mutex_t CRITICAL_SECTION +#define ZSTD_pthread_mutex_init(a, b) ((void)(b), InitializeCriticalSection((a)), 0) +#define ZSTD_pthread_mutex_destroy(a) DeleteCriticalSection((a)) +#define ZSTD_pthread_mutex_lock(a) EnterCriticalSection((a)) +#define ZSTD_pthread_mutex_unlock(a) LeaveCriticalSection((a)) + +/* condition variable */ +#define ZSTD_pthread_cond_t CONDITION_VARIABLE +#define ZSTD_pthread_cond_init(a, b) ((void)(b), InitializeConditionVariable((a)), 0) +#define ZSTD_pthread_cond_destroy(a) ((void)(a)) +#define ZSTD_pthread_cond_wait(a, b) SleepConditionVariableCS((a), (b), INFINITE) +#define ZSTD_pthread_cond_signal(a) WakeConditionVariable((a)) +#define ZSTD_pthread_cond_broadcast(a) WakeAllConditionVariable((a)) + +/* ZSTD_pthread_create() and ZSTD_pthread_join() */ +typedef struct { + HANDLE handle; + void* (*start_routine)(void*); + void* arg; +} ZSTD_pthread_t; + +int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused, + void* (*start_routine) (void*), void* arg); + +int ZSTD_pthread_join(ZSTD_pthread_t thread, void** value_ptr); + +/** + * add here more wrappers as required + */ + + +#elif POOL_MT /* posix assumed ; need a better detection method */ +/* === POSIX Systems === */ +# include + +#define ZSTD_pthread_mutex_t pthread_mutex_t +#define ZSTD_pthread_mutex_init(a, b) pthread_mutex_init((a), (b)) +#define ZSTD_pthread_mutex_destroy(a) pthread_mutex_destroy((a)) +#define ZSTD_pthread_mutex_lock(a) pthread_mutex_lock((a)) +#define ZSTD_pthread_mutex_unlock(a) pthread_mutex_unlock((a)) + +#define ZSTD_pthread_cond_t pthread_cond_t +#define ZSTD_pthread_cond_init(a, b) pthread_cond_init((a), (b)) +#define ZSTD_pthread_cond_destroy(a) pthread_cond_destroy((a)) +#define ZSTD_pthread_cond_wait(a, b) pthread_cond_wait((a), (b)) +#define ZSTD_pthread_cond_signal(a) pthread_cond_signal((a)) +#define ZSTD_pthread_cond_broadcast(a) pthread_cond_broadcast((a)) + +#define ZSTD_pthread_t pthread_t +#define ZSTD_pthread_create(a, b, c, d) pthread_create((a), (b), (c), (d)) +#define ZSTD_pthread_join(a, b) pthread_join((a),(b)) + +#else /* POOL_MT == 0 */ +/* No multithreading support */ + +typedef int ZSTD_pthread_mutex_t; +#define ZSTD_pthread_mutex_init(a, b) ((void)(a), (void)(b), 0) +#define ZSTD_pthread_mutex_destroy(a) ((void)(a)) +#define ZSTD_pthread_mutex_lock(a) ((void)(a)) +#define ZSTD_pthread_mutex_unlock(a) ((void)(a)) + +typedef int ZSTD_pthread_cond_t; +#define ZSTD_pthread_cond_init(a, b) ((void)(a), (void)(b), 0) +#define ZSTD_pthread_cond_destroy(a) ((void)(a)) +#define ZSTD_pthread_cond_wait(a, b) ((void)(a), (void)(b)) +#define ZSTD_pthread_cond_signal(a) ((void)(a)) +#define ZSTD_pthread_cond_broadcast(a) ((void)(a)) + +/* do not use ZSTD_pthread_t */ + +#endif /* POOL_MT */ + +#if defined (__cplusplus) +} +#endif + +#endif /* THREADING_H_938743 */ diff --git a/third_party/xxhash/tests/generate_unicode_test.c b/third_party/xxhash/tests/generate_unicode_test.c new file mode 100644 index 00000000000..eed6ac01a51 --- /dev/null +++ b/third_party/xxhash/tests/generate_unicode_test.c @@ -0,0 +1,154 @@ +/* + * Generates a Unicode test for xxhsum without using Unicode in the source files. + * + * Copyright (C) 2020 Devin Hussey (easyaspi314) + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Certain terminals don't properly handle UTF-8 (i.e. rxvt and command prompt + * in the default codepage), and that can cause issues when editing text. + * + * We use this C file to generate a file with a Unicode filename, a file with + * a checksum of said file, and both a Windows batch script and a Unix shell + * script to test the file. + */ + +#define _CRT_SECURE_NO_WARNINGS /* Silence warnings on MSVC */ +#include + +/* Use a Japanese filename, something that can't be cheated with ANSI. + * yuniko-do.unicode (literally unicode.unicode) */ + +/* Use raw hex values to ensure that the output is well-formed UTF-8. It is also more C90 compliant. */ +static const char FILENAME[] = { + (char)0xe3, (char)0x83, (char)0xa6, /* U+30e6: Katakana letter yu */ + (char)0xe3, (char)0x83, (char)0x8b, /* U+30cb: Katakana letter ni */ + (char)0xe3, (char)0x82, (char)0xb3, /* U+30b3: Katakana letter ko */ + (char)0xe3, (char)0x83, (char)0xbc, /* U+30fc: Katakana-Hiragana prolonged sound mark (dash) */ + (char)0xe3, (char)0x83, (char)0x89, /* U+30c9: Katakana letter do */ + '.','u','n','i','c','o','d','e','\0' /* ".unicode" (so we can glob in make clean and .gitignore) */ +}; + +#ifdef _WIN32 +/* The same text as above, but encoded in Windows UTF-16. */ +static const wchar_t WFILENAME[] = { 0x30e6, 0x30cb, 0x30b3, 0x30fc, 0x30c9, L'.', L'u', L'n', L'i', L'c', L'o', L'd', L'e', L'\0' }; +#endif + +int main(void) +{ + FILE *f, *script, *checksum; + + /* Create our Unicode file. Use _wfopen on Windows as fopen doesn't support Unicode filenames. */ +#ifdef _WIN32 + if (!(f = _wfopen(WFILENAME, L"wb"))) return 1; +#else + if (!(f = fopen(FILENAME, "wb"))) return 1; +#endif + fprintf(f, "test\n"); + fclose(f); + + /* XXH64 checksum file with the precalculated checksum for said file. */ + if (!(checksum = fopen("unicode_test.xxh64", "wb"))) + return 1; + fprintf(checksum, "2d7f1808da1fa63c %s\n", FILENAME); + fclose(checksum); + + + /* Create two scripts for both Windows and Unix. */ + + /* Generate a Windows batch script. Always insert CRLF manually. */ + if (!(script = fopen("unicode_test.bat", "wb"))) + return 1; + + /* Disable echoing the commands. We do that ourselves the naive way. */ + fprintf(script, "@echo off\r\n"); + + /* Change to codepage 65001 to enable UTF-8 support. */ + fprintf(script, "chcp 65001 >NUL 2>&1\r\n"); + + /* First test a Unicode filename */ + fprintf(script, "echo Testing filename provided on command line...\r\n"); + fprintf(script, "echo xxhsum.exe \"%s\"\r\n", FILENAME); + fprintf(script, "xxhsum.exe \"%s\"\r\n", FILENAME); + + /* Bail on error */ + fprintf(script, "if %%ERRORLEVEL%% neq 0 (\r\n"); + fprintf(script, " exit /B %%ERRORLEVEL%%\r\n"); + fprintf(script, ")\r\n"); + + /* Then test a checksum file. */ + fprintf(script, "echo Testing a checksum file...\r\n"); + fprintf(script, "echo xxhsum.exe -c unicode_test.xxh64\r\n"); + fprintf(script, "xxhsum.exe -c unicode_test.xxh64\r\n"); + + fprintf(script, "exit /B %%ERRORLEVEL%%\r\n"); + + fclose(script); + + /* Generate a Unix shell script */ + if (!(script = fopen("unicode_test.sh", "wb"))) + return 1; + + fprintf(script, "#!/bin/sh\n"); + /* + * Some versions of MSYS, MinGW and Cygwin do not support UTF-8, and the ones that + * don't may error with something like this: + * + * Error: Could not open '.unicode': No such file or directory. + * + * which is an internal error that happens when it tries to convert MinGW/Cygwin + * paths to Windows paths. + * + * In that case, we bail to cmd.exe and the batch script, which supports UTF-8 + * on Windows 7 and later. + */ + fprintf(script, "case $(uname) in\n"); + /* MinGW/MSYS converts /c to C:\ unless you have a double slash, + * Cygwin does not. */ + fprintf(script, " *CYGWIN*)\n"); + fprintf(script, " exec cmd.exe /c unicode_test.bat\n"); + fprintf(script, " ;;\n"); + fprintf(script, " *MINGW*|*MSYS*)\n"); + fprintf(script, " exec cmd.exe //c unicode_test.bat\n"); + fprintf(script, " ;;\n"); + fprintf(script, "esac\n"); + + /* First test a Unicode filename */ + fprintf(script, "echo Testing filename provided on command line...\n"); + fprintf(script, "echo './xxhsum \"%s\" || exit $?'\n", FILENAME); + fprintf(script, "./xxhsum \"%s\" || exit $?\n", FILENAME); + + /* Then test a checksum file. */ + fprintf(script, "echo Testing a checksum file...\n"); + fprintf(script, "echo './xxhsum -c unicode_test.xxh64 || exit $?'\n"); + fprintf(script, "./xxhsum -c unicode_test.xxh64 || exit $?\n"); + + fclose(script); + + return 0; +} diff --git a/third_party/xxhash/tests/multiInclude.c b/third_party/xxhash/tests/multiInclude.c new file mode 100644 index 00000000000..7d2bc8a9fd3 --- /dev/null +++ b/third_party/xxhash/tests/multiInclude.c @@ -0,0 +1,66 @@ +/* + * Multi-include test program + * Validates that xxhash.h can be included multiple times and in any order + * + * Copyright (C) 2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#include /* printf */ + +/* Normal include, gives access to public symbols */ +#include "../xxhash.h" + +/* + * Advanced include, gives access to experimental symbols + * This test ensure that xxhash.h can be included multiple times and in any + * order. This order is more difficult: Without care, the declaration of + * experimental symbols could be skipped. + */ +#define XXH_STATIC_LINKING_ONLY +#include "../xxhash.h" + +/* + * Inlining: Re-define all identifiers, keep them private to the unit. + * Note: Without specific efforts, the identifier names would collide. + * + * To be linked with and without xxhash.o to test the symbol's presence and + * naming collisions. + */ +#define XXH_INLINE_ALL +#include "../xxhash.h" + + +int main(void) +{ + XXH3_state_t state; /* part of experimental API */ + + XXH3_64bits_reset(&state); + const char input[] = "Hello World !"; + + XXH3_64bits_update(&state, input, sizeof(input)); + + XXH64_hash_t const h = XXH3_64bits_digest(&state); + printf("hash '%s': %08x%08x \n", input, (unsigned)(h >> 32), (unsigned)h); + + return 0; +} diff --git a/third_party/xxhash/tests/ppc_define.c b/third_party/xxhash/tests/ppc_define.c new file mode 100644 index 00000000000..d94c2c7240b --- /dev/null +++ b/third_party/xxhash/tests/ppc_define.c @@ -0,0 +1,62 @@ +/* + * Multi-include test program + * ensure that pixel, bool and vector are not redefined + * + * Copyright (C) 2020 Yann Collet + * + * GPL v2 License + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* gcc's altivec.h, included for the VSX code path, + * may, in some circumstances, redefine + * bool, vector and pixel keywords. + * + * This unit checks if it happens. + * It's a compile test. + * The test is mostly meaningful for PPC target using altivec.h + * hence XXH_VECTOR == XXH_VSX + */ + +#define BOOL_VALUE 32123456 +#define bool BOOL_VALUE + +#define VECTOR_VALUE 374464784 +#define vector VECTOR_VALUE + +#define PIXEL_VALUE 5846841 +#define pixel PIXEL_VALUE + +#define XXH_INLINE_ALL +#include "../xxhash.h" + +#if (bool != BOOL_VALUE) +# error "bool macro was redefined !" +#endif + +#if (vector != VECTOR_VALUE) +# error "vector macro was redefined !" +#endif + +#if (pixel != PIXEL_VALUE) +# error "pixel macro was redefined !" +#endif + +int g_nonEmptyUnit = 0; diff --git a/third_party/xxhash/xxh3.h b/third_party/xxhash/xxh3.h new file mode 100644 index 00000000000..7e83e6418af --- /dev/null +++ b/third_party/xxhash/xxh3.h @@ -0,0 +1,55 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Development source file for `xxh3` + * Copyright (C) 2019-2020 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +/* + * Note: This file used to host the source code of XXH3_* variants. + * during the development period. + * The source code is now properly integrated within xxhash.h. + * + * xxh3.h is no longer useful, + * but it is still provided for compatibility with source code + * which used to include it directly. + * + * Programs are now highly discourage to include xxh3.h. + * Include `xxhash.h` instead, which is the officially supported interface. + * + * In the future, xxh3.h will start to generate warnings, then errors, + * then it will be removed from source package and from include directory. + */ + +/* Simulate the same impact as including the old xxh3.h source file */ + +#define XXH_INLINE_ALL +#include "xxhash.h" diff --git a/third_party/xxhash/xxh_x86dispatch.c b/third_party/xxhash/xxh_x86dispatch.c new file mode 100644 index 00000000000..ab338329d17 --- /dev/null +++ b/third_party/xxhash/xxh_x86dispatch.c @@ -0,0 +1,770 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2020 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + + +/*! + * @file xxh_x86dispatch.c + * + * Automatic dispatcher code for the @ref xxh3_family on x86-based targets. + * + * Optional add-on. + * + * **Compile this file with the default flags for your target.** Do not compile + * with flags like `-mavx*`, `-march=native`, or `/arch:AVX*`, there will be + * an error. See @ref XXH_X86DISPATCH_ALLOW_AVX for details. + * + * @defgroup dispatch x86 Dispatcher + * @{ + */ + +#if defined (__cplusplus) +extern "C" { +#endif + +#if !(defined(__x86_64__) || defined(__i386__) || defined(_M_IX86) || defined(_M_X64)) +# error "Dispatching is currently only supported on x86 and x86_64." +#endif + +/*! + * @def XXH_X86DISPATCH_ALLOW_AVX + * @brief Disables the AVX sanity check. + * + * Don't compile xxh_x86dispatch.c with options like `-mavx*`, `-march=native`, + * or `/arch:AVX*`. It is intended to be compiled for the minimum target, and + * it selectively enables SSE2, AVX2, and AVX512 when it is needed. + * + * Using this option _globally_ allows this feature, and therefore makes it + * undefined behavior to execute on any CPU without said feature. + * + * Even if the source code isn't directly using AVX intrinsics in a function, + * the compiler can still generate AVX code from autovectorization and by + * "upgrading" SSE2 intrinsics to use the VEX prefixes (a.k.a. AVX128). + * + * Use the same flags that you use to compile the rest of the program; this + * file will safely generate SSE2, AVX2, and AVX512 without these flags. + * + * Define XXH_X86DISPATCH_ALLOW_AVX to ignore this check, and feel free to open + * an issue if there is a target in the future where AVX is a default feature. + */ +#ifdef XXH_DOXYGEN +# define XXH_X86DISPATCH_ALLOW_AVX +#endif + +#if defined(__AVX__) && !defined(XXH_X86DISPATCH_ALLOW_AVX) +# error "Do not compile xxh_x86dispatch.c with AVX enabled! See the comment above." +#endif + +#ifdef __has_include +# define XXH_HAS_INCLUDE(header) __has_include(header) +#else +# define XXH_HAS_INCLUDE(header) 0 +#endif + +/*! + * @def XXH_DISPATCH_SCALAR + * @brief Enables/dispatching the scalar code path. + * + * If this is defined to 0, SSE2 support is assumed. This reduces code size + * when the scalar path is not needed. + * + * This is automatically defined to 0 when... + * - SSE2 support is enabled in the compiler + * - Targeting x86_64 + * - Targeting Android x86 + * - Targeting macOS + */ +#ifndef XXH_DISPATCH_SCALAR +# if defined(__SSE2__) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2) /* SSE2 on by default */ \ + || defined(__x86_64__) || defined(_M_X64) /* x86_64 */ \ + || defined(__ANDROID__) || defined(__APPLEv__) /* Android or macOS */ +# define XXH_DISPATCH_SCALAR 0 /* disable */ +# else +# define XXH_DISPATCH_SCALAR 1 +# endif +#endif +/*! + * @def XXH_DISPATCH_AVX2 + * @brief Enables/disables dispatching for AVX2. + * + * This is automatically detected if it is not defined. + * - GCC 4.7 and later are known to support AVX2, but >4.9 is required for + * to get the AVX2 intrinsics and typedefs without -mavx -mavx2. + * - Visual Studio 2013 Update 2 and later are known to support AVX2. + * - The GCC/Clang internal header `` is detected. While this is + * not allowed to be included directly, it still appears in the builtin + * include path and is detectable with `__has_include`. + * + * @see XXH_AVX2 + */ +#ifndef XXH_DISPATCH_AVX2 +# if (defined(__GNUC__) && (__GNUC__ > 4)) /* GCC 5.0+ */ \ + || (defined(_MSC_VER) && _MSC_VER >= 1900) /* VS 2015+ */ \ + || (defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 180030501) /* VS 2013 Update 2 */ \ + || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ +# define XXH_DISPATCH_AVX2 1 /* enable dispatch towards AVX2 */ +# else +# define XXH_DISPATCH_AVX2 0 +# endif +#endif /* XXH_DISPATCH_AVX2 */ + +/*! + * @def XXH_DISPATCH_AVX512 + * @brief Enables/disables dispatching for AVX512. + * + * Automatically detected if one of the following conditions is met: + * - GCC 4.9 and later are known to support AVX512. + * - Visual Studio 2017 and later are known to support AVX2. + * - The GCC/Clang internal header `` is detected. While this + * is not allowed to be included directly, it still appears in the builtin + * include path and is detectable with `__has_include`. + * + * @see XXH_AVX512 + */ +#ifndef XXH_DISPATCH_AVX512 +# if (defined(__GNUC__) \ + && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) /* GCC 4.9+ */ \ + || (defined(_MSC_VER) && _MSC_VER >= 1910) /* VS 2017+ */ \ + || XXH_HAS_INCLUDE() /* GCC/Clang internal header */ +# define XXH_DISPATCH_AVX512 1 /* enable dispatch towards AVX512 */ +# else +# define XXH_DISPATCH_AVX512 0 +# endif +#endif /* XXH_DISPATCH_AVX512 */ + +/*! + * @def XXH_TARGET_SSE2 + * @brief Allows a function to be compiled with SSE2 intrinsics. + * + * Uses `__attribute__((__target__("sse2")))` on GCC to allow SSE2 to be used + * even with `-mno-sse2`. + * + * @def XXH_TARGET_AVX2 + * @brief Like @ref XXH_TARGET_SSE2, but for AVX2. + * + * @def XXH_TARGET_AVX512 + * @brief Like @ref XXH_TARGET_SSE2, but for AVX512. + */ +#if defined(__GNUC__) +# include /* SSE2 */ +# if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +# include /* AVX2, AVX512F */ +# endif +# define XXH_TARGET_SSE2 __attribute__((__target__("sse2"))) +# define XXH_TARGET_AVX2 __attribute__((__target__("avx2"))) +# define XXH_TARGET_AVX512 __attribute__((__target__("avx512f"))) +#elif defined(_MSC_VER) +# include +# define XXH_TARGET_SSE2 +# define XXH_TARGET_AVX2 +# define XXH_TARGET_AVX512 +#else +# error "Dispatching is currently not supported for your compiler." +#endif + +#ifdef XXH_DISPATCH_DEBUG +/* debug logging */ +# include +# define XXH_debugPrint(str) { fprintf(stderr, "DEBUG: xxHash dispatch: %s \n", str); fflush(NULL); } +#else +# define XXH_debugPrint(str) ((void)0) +# undef NDEBUG /* avoid redefinition */ +# define NDEBUG +#endif +#include + +#define XXH_INLINE_ALL +#define XXH_X86DISPATCH +#include "xxhash.h" + +/* + * Support both AT&T and Intel dialects + * + * GCC doesn't convert AT&T syntax to Intel syntax, and will error out if + * compiled with -masm=intel. Instead, it supports dialect switching with + * curly braces: { AT&T syntax | Intel syntax } + * + * Clang's integrated assembler automatically converts AT&T syntax to Intel if + * needed, making the dialect switching useless (it isn't even supported). + * + * Note: Comments are written in the inline assembly itself. + */ +#ifdef __clang__ +# define XXH_I_ATT(intel, att) att "\n\t" +#else +# define XXH_I_ATT(intel, att) "{" att "|" intel "}\n\t" +#endif + +/*! + * @internal + * @brief Runs CPUID. + * + * @param eax, ecx The parameters to pass to CPUID, %eax and %ecx respectively. + * @param abcd The array to store the result in, `{ eax, ebx, ecx, edx }` + */ +static void XXH_cpuid(xxh_u32 eax, xxh_u32 ecx, xxh_u32* abcd) +{ +#if defined(_MSC_VER) + __cpuidex(abcd, eax, ecx); +#else + xxh_u32 ebx, edx; +# if defined(__i386__) && defined(__PIC__) + __asm__( + "# Call CPUID\n\t" + "#\n\t" + "# On 32-bit x86 with PIC enabled, we are not allowed to overwrite\n\t" + "# EBX, so we use EDI instead.\n\t" + XXH_I_ATT("mov edi, ebx", "movl %%ebx, %%edi") + XXH_I_ATT("cpuid", "cpuid" ) + XXH_I_ATT("xchg edi, ebx", "xchgl %%ebx, %%edi") + : "=D" (ebx), +# else + __asm__( + "# Call CPUID\n\t" + XXH_I_ATT("cpuid", "cpuid") + : "=b" (ebx), +# endif + "+a" (eax), "+c" (ecx), "=d" (edx)); + abcd[0] = eax; + abcd[1] = ebx; + abcd[2] = ecx; + abcd[3] = edx; +#endif +} + +/* + * Modified version of Intel's guide + * https://software.intel.com/en-us/articles/how-to-detect-new-instruction-support-in-the-4th-generation-intel-core-processor-family + */ + +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 +/*! + * @internal + * @brief Runs `XGETBV`. + * + * While the CPU may support AVX2, the operating system might not properly save + * the full YMM/ZMM registers. + * + * xgetbv is used for detecting this: Any compliant operating system will define + * a set of flags in the xcr0 register indicating how it saves the AVX registers. + * + * You can manually disable this flag on Windows by running, as admin: + * + * bcdedit.exe /set xsavedisable 1 + * + * and rebooting. Run the same command with 0 to re-enable it. + */ +static xxh_u64 XXH_xgetbv(void) +{ +#if defined(_MSC_VER) + return _xgetbv(0); /* min VS2010 SP1 compiler is required */ +#else + xxh_u32 xcr0_lo, xcr0_hi; + __asm__( + "# Call XGETBV\n\t" + "#\n\t" + "# Older assemblers (e.g. macOS's ancient GAS version) don't support\n\t" + "# the XGETBV opcode, so we encode it by hand instead.\n\t" + "# See for details.\n\t" + ".byte 0x0f, 0x01, 0xd0\n\t" + : "=a" (xcr0_lo), "=d" (xcr0_hi) : "c" (0)); + return xcr0_lo | ((xxh_u64)xcr0_hi << 32); +#endif +} +#endif + +#define XXH_SSE2_CPUID_MASK (1 << 26) +#define XXH_OSXSAVE_CPUID_MASK ((1 << 26) | (1 << 27)) +#define XXH_AVX2_CPUID_MASK (1 << 5) +#define XXH_AVX2_XGETBV_MASK ((1 << 2) | (1 << 1)) +#define XXH_AVX512F_CPUID_MASK (1 << 16) +#define XXH_AVX512F_XGETBV_MASK ((7 << 5) | (1 << 2) | (1 << 1)) + +/*! + * @internal + * @brief Returns the best XXH3 implementation. + * + * Runs various CPUID/XGETBV tests to try and determine the best implementation. + * + * @ret The best @ref XXH_VECTOR implementation. + * @see XXH_VECTOR_TYPES + */ +static int XXH_featureTest(void) +{ + xxh_u32 abcd[4]; + xxh_u32 max_leaves; + int best = XXH_SCALAR; +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 + xxh_u64 xgetbv_val; +#endif +#if defined(__GNUC__) && defined(__i386__) + xxh_u32 cpuid_supported; + __asm__( + "# For the sake of ruthless backwards compatibility, check if CPUID\n\t" + "# is supported in the EFLAGS on i386.\n\t" + "# This is not necessary on x86_64 - CPUID is mandatory.\n\t" + "# The ID flag (bit 21) in the EFLAGS register indicates support\n\t" + "# for the CPUID instruction. If a software procedure can set and\n\t" + "# clear this flag, the processor executing the procedure supports\n\t" + "# the CPUID instruction.\n\t" + "# \n\t" + "#\n\t" + "# Routine is from .\n\t" + + "# Save EFLAGS\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# Store EFLAGS\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# Invert the ID bit in stored EFLAGS\n\t" + XXH_I_ATT("xor dword ptr[esp], 0x200000", "xorl $0x200000, (%%esp)") + "# Load stored EFLAGS (with ID bit inverted)\n\t" + XXH_I_ATT("popfd", "popfl" ) + "# Store EFLAGS again (ID bit may or not be inverted)\n\t" + XXH_I_ATT("pushfd", "pushfl" ) + "# eax = modified EFLAGS (ID bit may or may not be inverted)\n\t" + XXH_I_ATT("pop eax", "popl %%eax" ) + "# eax = whichever bits were changed\n\t" + XXH_I_ATT("xor eax, dword ptr[esp]", "xorl (%%esp), %%eax" ) + "# Restore original EFLAGS\n\t" + XXH_I_ATT("popfd", "popfl" ) + "# eax = zero if ID bit can't be changed, else non-zero\n\t" + XXH_I_ATT("and eax, 0x200000", "andl $0x200000, %%eax" ) + : "=a" (cpuid_supported) :: "cc"); + + if (XXH_unlikely(!cpuid_supported)) { + XXH_debugPrint("CPUID support is not detected!"); + return best; + } + +#endif + /* Check how many CPUID pages we have */ + XXH_cpuid(0, 0, abcd); + max_leaves = abcd[0]; + + /* Shouldn't happen on hardware, but happens on some QEMU configs. */ + if (XXH_unlikely(max_leaves == 0)) { + XXH_debugPrint("Max CPUID leaves == 0!"); + return best; + } + + /* Check for SSE2, OSXSAVE and xgetbv */ + XXH_cpuid(1, 0, abcd); + + /* + * Test for SSE2. The check is redundant on x86_64, but it doesn't hurt. + */ + if (XXH_unlikely((abcd[3] & XXH_SSE2_CPUID_MASK) != XXH_SSE2_CPUID_MASK)) + return best; + + XXH_debugPrint("SSE2 support detected."); + + best = XXH_SSE2; +#if XXH_DISPATCH_AVX2 || XXH_DISPATCH_AVX512 + /* Make sure we have enough leaves */ + if (XXH_unlikely(max_leaves < 7)) + return best; + + /* Test for OSXSAVE and XGETBV */ + if ((abcd[2] & XXH_OSXSAVE_CPUID_MASK) != XXH_OSXSAVE_CPUID_MASK) + return best; + + /* CPUID check for AVX features */ + XXH_cpuid(7, 0, abcd); + + xgetbv_val = XXH_xgetbv(); +#if XXH_DISPATCH_AVX2 + /* Validate that AVX2 is supported by the CPU */ + if ((abcd[1] & XXH_AVX2_CPUID_MASK) != XXH_AVX2_CPUID_MASK) + return best; + + /* Validate that the OS supports YMM registers */ + if ((xgetbv_val & XXH_AVX2_XGETBV_MASK) != XXH_AVX2_XGETBV_MASK) { + XXH_debugPrint("AVX2 supported by the CPU, but not the OS."); + return best; + } + + /* AVX2 supported */ + XXH_debugPrint("AVX2 support detected."); + best = XXH_AVX2; +#endif +#if XXH_DISPATCH_AVX512 + /* Check if AVX512F is supported by the CPU */ + if ((abcd[1] & XXH_AVX512F_CPUID_MASK) != XXH_AVX512F_CPUID_MASK) { + XXH_debugPrint("AVX512F not supported by CPU"); + return best; + } + + /* Validate that the OS supports ZMM registers */ + if ((xgetbv_val & XXH_AVX512F_XGETBV_MASK) != XXH_AVX512F_XGETBV_MASK) { + XXH_debugPrint("AVX512F supported by the CPU, but not the OS."); + return best; + } + + /* AVX512F supported */ + XXH_debugPrint("AVX512F support detected."); + best = XXH_AVX512; +#endif +#endif + return best; +} + + +/* === Vector implementations === */ + +/*! + * @internal + * @brief Defines the various dispatch functions. + * + * TODO: Consolidate? + * + * @param suffix The suffix for the functions, e.g. sse2 or scalar + * @param target XXH_TARGET_* or empty. + */ +#define XXH_DEFINE_DISPATCH_FUNCS(suffix, target) \ + \ +/* === XXH3, default variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_default_##suffix(const void* XXH_RESTRICT input, size_t len) \ +{ \ + return XXH3_hashLong_64b_internal( \ + input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ + XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH3, Seeded variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_seed_##suffix(const void* XXH_RESTRICT input, size_t len, \ + XXH64_hash_t seed) \ +{ \ + return XXH3_hashLong_64b_withSeed_internal( \ + input, len, seed, XXH3_accumulate_512_##suffix, \ + XXH3_scrambleAcc_##suffix, XXH3_initCustomSecret_##suffix \ + ); \ +} \ + \ +/* === XXH3, Secret variants === */ \ + \ +XXH_NO_INLINE target XXH64_hash_t \ +XXHL64_secret_##suffix(const void* XXH_RESTRICT input, size_t len, \ + const void* secret, size_t secretLen) \ +{ \ + return XXH3_hashLong_64b_internal( \ + input, len, secret, secretLen, \ + XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH3 update variants === */ \ + \ +XXH_NO_INLINE target XXH_errorcode \ +XXH3_update_##suffix(XXH3_state_t* state, const void* input, size_t len) \ +{ \ + return XXH3_update(state, (const xxh_u8*)input, len, \ + XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix); \ +} \ + \ +/* === XXH128 default variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_default_##suffix(const void* XXH_RESTRICT input, size_t len) \ +{ \ + return XXH3_hashLong_128b_internal( \ + input, len, XXH3_kSecret, sizeof(XXH3_kSecret), \ + XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix \ + ); \ +} \ + \ +/* === XXH128 Secret variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_secret_##suffix(const void* XXH_RESTRICT input, size_t len, \ + const void* XXH_RESTRICT secret, size_t secretLen) \ +{ \ + return XXH3_hashLong_128b_internal( \ + input, len, (const xxh_u8*)secret, secretLen, \ + XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix); \ +} \ + \ +/* === XXH128 Seeded variants === */ \ + \ +XXH_NO_INLINE target XXH128_hash_t \ +XXHL128_seed_##suffix(const void* XXH_RESTRICT input, size_t len, \ + XXH64_hash_t seed) \ +{ \ + return XXH3_hashLong_128b_withSeed_internal(input, len, seed, \ + XXH3_accumulate_512_##suffix, XXH3_scrambleAcc_##suffix, \ + XXH3_initCustomSecret_##suffix); \ +} + +/* End XXH_DEFINE_DISPATCH_FUNCS */ + +#if XXH_DISPATCH_SCALAR +XXH_DEFINE_DISPATCH_FUNCS(scalar, /* nothing */) +#endif +XXH_DEFINE_DISPATCH_FUNCS(sse2, XXH_TARGET_SSE2) +#if XXH_DISPATCH_AVX2 +XXH_DEFINE_DISPATCH_FUNCS(avx2, XXH_TARGET_AVX2) +#endif +#if XXH_DISPATCH_AVX512 +XXH_DEFINE_DISPATCH_FUNCS(avx512, XXH_TARGET_AVX512) +#endif +#undef XXH_DEFINE_DISPATCH_FUNCS + +/* ==== Dispatchers ==== */ + +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_default)(const void* XXH_RESTRICT, size_t); + +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSeed)(const void* XXH_RESTRICT, size_t, XXH64_hash_t); + +typedef XXH64_hash_t (*XXH3_dispatchx86_hashLong64_withSecret)(const void* XXH_RESTRICT, size_t, const void* XXH_RESTRICT, size_t); + +typedef XXH_errorcode (*XXH3_dispatchx86_update)(XXH3_state_t*, const void*, size_t); + +typedef struct { + XXH3_dispatchx86_hashLong64_default hashLong64_default; + XXH3_dispatchx86_hashLong64_withSeed hashLong64_seed; + XXH3_dispatchx86_hashLong64_withSecret hashLong64_secret; + XXH3_dispatchx86_update update; +} XXH_dispatchFunctions_s; + +#define XXH_NB_DISPATCHES 4 + +/*! + * @internal + * @brief Table of dispatchers for @ref XXH3_64bits(). + * + * @pre The indices must match @ref XXH_VECTOR_TYPE. + */ +static const XXH_dispatchFunctions_s XXH_kDispatch[XXH_NB_DISPATCHES] = { +#if XXH_DISPATCH_SCALAR + /* Scalar */ { XXHL64_default_scalar, XXHL64_seed_scalar, XXHL64_secret_scalar, XXH3_update_scalar }, +#else + /* Scalar */ { NULL, NULL, NULL, NULL }, +#endif + /* SSE2 */ { XXHL64_default_sse2, XXHL64_seed_sse2, XXHL64_secret_sse2, XXH3_update_sse2 }, +#if XXH_DISPATCH_AVX2 + /* AVX2 */ { XXHL64_default_avx2, XXHL64_seed_avx2, XXHL64_secret_avx2, XXH3_update_avx2 }, +#else + /* AVX2 */ { NULL, NULL, NULL, NULL }, +#endif +#if XXH_DISPATCH_AVX512 + /* AVX512 */ { XXHL64_default_avx512, XXHL64_seed_avx512, XXHL64_secret_avx512, XXH3_update_avx512 } +#else + /* AVX512 */ { NULL, NULL, NULL, NULL } +#endif +}; +/*! + * @internal + * @brief The selected dispatch table for @ref XXH3_64bits(). + */ +static XXH_dispatchFunctions_s XXH_g_dispatch = { NULL, NULL, NULL, NULL }; + + +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_default)(const void* XXH_RESTRICT, size_t); + +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSeed)(const void* XXH_RESTRICT, size_t, XXH64_hash_t); + +typedef XXH128_hash_t (*XXH3_dispatchx86_hashLong128_withSecret)(const void* XXH_RESTRICT, size_t, const void* XXH_RESTRICT, size_t); + +typedef struct { + XXH3_dispatchx86_hashLong128_default hashLong128_default; + XXH3_dispatchx86_hashLong128_withSeed hashLong128_seed; + XXH3_dispatchx86_hashLong128_withSecret hashLong128_secret; + XXH3_dispatchx86_update update; +} XXH_dispatch128Functions_s; + + +/*! + * @internal + * @brief Table of dispatchers for @ref XXH3_128bits(). + * + * @pre The indices must match @ref XXH_VECTOR_TYPE. + */ +static const XXH_dispatch128Functions_s XXH_kDispatch128[XXH_NB_DISPATCHES] = { +#if XXH_DISPATCH_SCALAR + /* Scalar */ { XXHL128_default_scalar, XXHL128_seed_scalar, XXHL128_secret_scalar, XXH3_update_scalar }, +#else + /* Scalar */ { NULL, NULL, NULL, NULL }, +#endif + /* SSE2 */ { XXHL128_default_sse2, XXHL128_seed_sse2, XXHL128_secret_sse2, XXH3_update_sse2 }, +#if XXH_DISPATCH_AVX2 + /* AVX2 */ { XXHL128_default_avx2, XXHL128_seed_avx2, XXHL128_secret_avx2, XXH3_update_avx2 }, +#else + /* AVX2 */ { NULL, NULL, NULL, NULL }, +#endif +#if XXH_DISPATCH_AVX512 + /* AVX512 */ { XXHL128_default_avx512, XXHL128_seed_avx512, XXHL128_secret_avx512, XXH3_update_avx512 } +#else + /* AVX512 */ { NULL, NULL, NULL, NULL } +#endif +}; + +/*! + * @internal + * @brief The selected dispatch table for @ref XXH3_64bits(). + */ +static XXH_dispatch128Functions_s XXH_g_dispatch128 = { NULL, NULL, NULL, NULL }; + +/*! + * @internal + * @brief Runs a CPUID check and sets the correct dispatch tables. + */ +static void XXH_setDispatch(void) +{ + int vecID = XXH_featureTest(); + XXH_STATIC_ASSERT(XXH_AVX512 == XXH_NB_DISPATCHES-1); + assert(XXH_SCALAR <= vecID && vecID <= XXH_AVX512); +#if !XXH_DISPATCH_SCALAR + assert(vecID != XXH_SCALAR); +#endif +#if !XXH_DISPATCH_AVX512 + assert(vecID != XXH_AVX512); +#endif +#if !XXH_DISPATCH_AVX2 + assert(vecID != XXH_AVX2); +#endif + XXH_g_dispatch = XXH_kDispatch[vecID]; + XXH_g_dispatch128 = XXH_kDispatch128[vecID]; +} + + +/* ==== XXH3 public functions ==== */ + +static XXH64_hash_t +XXH3_hashLong_64b_defaultSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + if (XXH_g_dispatch.hashLong64_default == NULL) XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_default(input, len); +} + +XXH64_hash_t XXH3_64bits_dispatch(const void* input, size_t len) +{ + return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_defaultSecret_selection); +} + +static XXH64_hash_t +XXH3_hashLong_64b_withSeed_selection(const void* input, size_t len, + XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + if (XXH_g_dispatch.hashLong64_seed == NULL) XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_seed(input, len, seed64); +} + +XXH64_hash_t XXH3_64bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed_selection); +} + +static XXH64_hash_t +XXH3_hashLong_64b_withSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const xxh_u8* secret, size_t secretLen) +{ + (void)seed64; + if (XXH_g_dispatch.hashLong64_secret == NULL) XXH_setDispatch(); + return XXH_g_dispatch.hashLong64_secret(input, len, secret, secretLen); +} + +XXH64_hash_t XXH3_64bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen) +{ + return XXH3_64bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_64b_withSecret_selection); +} + +XXH_errorcode +XXH3_64bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len) +{ + if (XXH_g_dispatch.update == NULL) XXH_setDispatch(); + return XXH_g_dispatch.update(state, (const xxh_u8*)input, len); +} + + +/* ==== XXH128 public functions ==== */ + +static XXH128_hash_t +XXH3_hashLong_128b_defaultSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + if (XXH_g_dispatch128.hashLong128_default == NULL) XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_default(input, len); +} + +XXH128_hash_t XXH3_128bits_dispatch(const void* input, size_t len) +{ + return XXH3_128bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_defaultSecret_selection); +} + +static XXH128_hash_t +XXH3_hashLong_128b_withSeed_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + if (XXH_g_dispatch128.hashLong128_seed == NULL) XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_seed(input, len, seed64); +} + +XXH128_hash_t XXH3_128bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_128b_withSeed_selection); +} + +static XXH128_hash_t +XXH3_hashLong_128b_withSecret_selection(const void* input, size_t len, + XXH64_hash_t seed64, const void* secret, size_t secretLen) +{ + (void)seed64; + if (XXH_g_dispatch128.hashLong128_secret == NULL) XXH_setDispatch(); + return XXH_g_dispatch128.hashLong128_secret(input, len, secret, secretLen); +} + +XXH128_hash_t XXH3_128bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen) +{ + return XXH3_128bits_internal(input, len, 0, secret, secretLen, XXH3_hashLong_128b_withSecret_selection); +} + +XXH_errorcode +XXH3_128bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len) +{ + if (XXH_g_dispatch128.update == NULL) XXH_setDispatch(); + return XXH_g_dispatch128.update(state, (const xxh_u8*)input, len); +} + +#if defined (__cplusplus) +} +#endif +/*! @} */ diff --git a/third_party/xxhash/xxh_x86dispatch.h b/third_party/xxhash/xxh_x86dispatch.h new file mode 100644 index 00000000000..6bc17bcbbe4 --- /dev/null +++ b/third_party/xxhash/xxh_x86dispatch.h @@ -0,0 +1,86 @@ +/* + * xxHash - XXH3 Dispatcher for x86-based targets + * Copyright (C) 2020 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + +#ifndef XXH_X86DISPATCH_H_13563687684 +#define XXH_X86DISPATCH_H_13563687684 + +#include "xxhash.h" /* XXH64_hash_t, XXH3_state_t */ + +#if defined (__cplusplus) +extern "C" { +#endif + +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_dispatch(const void* input, size_t len); +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen); +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len); + +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_dispatch(const void* input, size_t len); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed_dispatch(const void* input, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret_dispatch(const void* input, size_t len, const void* secret, size_t secretLen); +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update_dispatch(XXH3_state_t* state, const void* input, size_t len); + +#if defined (__cplusplus) +} +#endif + + +/* automatic replacement of XXH3 functions. + * can be disabled by setting XXH_DISPATCH_DISABLE_REPLACE */ +#ifndef XXH_DISPATCH_DISABLE_REPLACE + +# undef XXH3_64bits +# define XXH3_64bits XXH3_64bits_dispatch +# undef XXH3_64bits_withSeed +# define XXH3_64bits_withSeed XXH3_64bits_withSeed_dispatch +# undef XXH3_64bits_withSecret +# define XXH3_64bits_withSecret XXH3_64bits_withSecret_dispatch +# undef XXH3_64bits_update +# define XXH3_64bits_update XXH3_64bits_update_dispatch + +# undef XXH128 +# define XXH128 XXH3_128bits_withSeed_dispatch +# define XXH3_128bits XXH3_128bits_dispatch +# undef XXH3_128bits +# define XXH3_128bits XXH3_128bits_dispatch +# undef XXH3_128bits_withSeed +# define XXH3_128bits_withSeed XXH3_128bits_withSeed_dispatch +# undef XXH3_128bits_withSecret +# define XXH3_128bits_withSecret XXH3_128bits_withSecret_dispatch +# undef XXH3_128bits_update +# define XXH3_128bits_update XXH3_128bits_update_dispatch + +#endif /* XXH_DISPATCH_DISABLE_REPLACE */ + +#endif /* XXH_X86DISPATCH_H_13563687684 */ diff --git a/third_party/xxhash/xxhash.c b/third_party/xxhash/xxhash.c new file mode 100644 index 00000000000..0fae88c5d67 --- /dev/null +++ b/third_party/xxhash/xxhash.c @@ -0,0 +1,43 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Copyright (C) 2012-2020 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ + + +/* + * xxhash.c instantiates functions defined in xxhash.h + */ + +#define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ +#define XXH_IMPLEMENTATION /* access definitions */ + +#include "xxhash.h" diff --git a/third_party/xxhash/xxhash.h b/third_party/xxhash/xxhash.h new file mode 100644 index 00000000000..29c44e45d96 --- /dev/null +++ b/third_party/xxhash/xxhash.h @@ -0,0 +1,5443 @@ +/* + * xxHash - Extremely Fast Hash algorithm + * Header File + * Copyright (C) 2012-2020 Yann Collet + * + * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at: + * - xxHash homepage: https://www.xxhash.com + * - xxHash source repository: https://github.com/Cyan4973/xxHash + */ +/*! + * @mainpage xxHash + * + * @file xxhash.h + * xxHash prototypes and implementation + */ +/* TODO: update */ +/* Notice extracted from xxHash homepage: + +xxHash is an extremely fast hash algorithm, running at RAM speed limits. +It also successfully passes all tests from the SMHasher suite. + +Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) + +Name Speed Q.Score Author +xxHash 5.4 GB/s 10 +CrapWow 3.2 GB/s 2 Andrew +MurmurHash 3a 2.7 GB/s 10 Austin Appleby +SpookyHash 2.0 GB/s 10 Bob Jenkins +SBox 1.4 GB/s 9 Bret Mulvey +Lookup3 1.2 GB/s 9 Bob Jenkins +SuperFastHash 1.2 GB/s 1 Paul Hsieh +CityHash64 1.05 GB/s 10 Pike & Alakuijala +FNV 0.55 GB/s 5 Fowler, Noll, Vo +CRC32 0.43 GB/s 9 +MD5-32 0.33 GB/s 10 Ronald L. Rivest +SHA1-32 0.28 GB/s 10 + +Q.Score is a measure of quality of the hash function. +It depends on successfully passing SMHasher test set. +10 is a perfect score. + +Note: SMHasher's CRC32 implementation is not the fastest one. +Other speed-oriented implementations can be faster, +especially in combination with PCLMUL instruction: +https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html?showComment=1552696407071#c3490092340461170735 + +A 64-bit version, named XXH64, is available since r35. +It offers much better speed, but for 64-bit applications only. +Name Speed on 64 bits Speed on 32 bits +XXH64 13.8 GB/s 1.9 GB/s +XXH32 6.8 GB/s 6.0 GB/s +*/ + +#if defined (__cplusplus) +extern "C" { +#endif + +/* **************************** + * INLINE mode + ******************************/ +/*! + * XXH_INLINE_ALL (and XXH_PRIVATE_API) + * Use these build macros to inline xxhash into the target unit. + * Inlining improves performance on small inputs, especially when the length is + * expressed as a compile-time constant: + * + * https://fastcompression.blogspot.com/2018/03/xxhash-for-small-keys-impressive-power.html + * + * It also keeps xxHash symbols private to the unit, so they are not exported. + * + * Usage: + * #define XXH_INLINE_ALL + * #include "xxhash.h" + * + * Do not compile and link xxhash.o as a separate object, as it is not useful. + */ +#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \ + && !defined(XXH_INLINE_ALL_31684351384) + /* this section should be traversed only once */ +# define XXH_INLINE_ALL_31684351384 + /* give access to the advanced API, required to compile implementations */ +# undef XXH_STATIC_LINKING_ONLY /* avoid macro redef */ +# define XXH_STATIC_LINKING_ONLY + /* make all functions private */ +# undef XXH_PUBLIC_API +# if defined(__GNUC__) +# define XXH_PUBLIC_API static __inline __attribute__((unused)) +# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define XXH_PUBLIC_API static inline +# elif defined(_MSC_VER) +# define XXH_PUBLIC_API static __inline +# else + /* note: this version may generate warnings for unused static functions */ +# define XXH_PUBLIC_API static +# endif + + /* + * This part deals with the special case where a unit wants to inline xxHash, + * but "xxhash.h" has previously been included without XXH_INLINE_ALL, such + * as part of some previously included *.h header file. + * Without further action, the new include would just be ignored, + * and functions would effectively _not_ be inlined (silent failure). + * The following macros solve this situation by prefixing all inlined names, + * avoiding naming collision with previous inclusions. + */ +# ifdef XXH_NAMESPACE +# error "XXH_INLINE_ALL with XXH_NAMESPACE is not supported" + /* + * Note: Alternative: #undef all symbols (it's a pretty large list). + * Without #error: it compiles, but functions are actually not inlined. + */ +# endif +# define XXH_NAMESPACE XXH_INLINE_ + /* + * Some identifiers (enums, type names) are not symbols, but they must + * still be renamed to avoid redeclaration. + * Alternative solution: do not redeclare them. + * However, this requires some #ifdefs, and is a more dispersed action. + * Meanwhile, renaming can be achieved in a single block + */ +# define XXH_IPREF(Id) XXH_INLINE_ ## Id +# define XXH_OK XXH_IPREF(XXH_OK) +# define XXH_ERROR XXH_IPREF(XXH_ERROR) +# define XXH_errorcode XXH_IPREF(XXH_errorcode) +# define XXH32_canonical_t XXH_IPREF(XXH32_canonical_t) +# define XXH64_canonical_t XXH_IPREF(XXH64_canonical_t) +# define XXH128_canonical_t XXH_IPREF(XXH128_canonical_t) +# define XXH32_state_s XXH_IPREF(XXH32_state_s) +# define XXH32_state_t XXH_IPREF(XXH32_state_t) +# define XXH64_state_s XXH_IPREF(XXH64_state_s) +# define XXH64_state_t XXH_IPREF(XXH64_state_t) +# define XXH3_state_s XXH_IPREF(XXH3_state_s) +# define XXH3_state_t XXH_IPREF(XXH3_state_t) +# define XXH128_hash_t XXH_IPREF(XXH128_hash_t) + /* Ensure the header is parsed again, even if it was previously included */ +# undef XXHASH_H_5627135585666179 +# undef XXHASH_H_STATIC_13879238742 +#endif /* XXH_INLINE_ALL || XXH_PRIVATE_API */ + + + +/* **************************************************************** + * Stable API + *****************************************************************/ +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 + + +/*! + * @defgroup public Public API + * Contains details on the public xxHash functions. + * @{ + */ +/* specific declaration modes for Windows */ +#if !defined(XXH_INLINE_ALL) && !defined(XXH_PRIVATE_API) +# if defined(WIN32) && defined(_MSC_VER) && (defined(XXH_IMPORT) || defined(XXH_EXPORT)) +# ifdef XXH_EXPORT +# define XXH_PUBLIC_API __declspec(dllexport) +# elif XXH_IMPORT +# define XXH_PUBLIC_API __declspec(dllimport) +# endif +# else +# define XXH_PUBLIC_API /* do nothing */ +# endif +#endif + +#ifdef XXH_DOXYGEN +/*! + * @brief Emulate a namespace by transparently prefixing all symbols. + * + * If you want to include _and expose_ xxHash functions from within your own + * library, but also want to avoid symbol collisions with other libraries which + * may also include xxHash, you can use XXH_NAMESPACE to automatically prefix + * any public symbol from xxhash library with the value of XXH_NAMESPACE + * (therefore, avoid empty or numeric values). + * + * Note that no change is required within the calling program as long as it + * includes `xxhash.h`: Regular symbol names will be automatically translated + * by this header. + */ +# define XXH_NAMESPACE /* YOUR NAME HERE */ +# undef XXH_NAMESPACE +#endif + +#ifdef XXH_NAMESPACE +# define XXH_CAT(A,B) A##B +# define XXH_NAME2(A,B) XXH_CAT(A,B) +# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +/* XXH32 */ +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) +# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) +# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) +# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) +# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) +# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) +# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) +# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) +# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +/* XXH64 */ +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) +# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +/* XXH3_64bits */ +# define XXH3_64bits XXH_NAME2(XXH_NAMESPACE, XXH3_64bits) +# define XXH3_64bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSecret) +# define XXH3_64bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_withSeed) +# define XXH3_createState XXH_NAME2(XXH_NAMESPACE, XXH3_createState) +# define XXH3_freeState XXH_NAME2(XXH_NAMESPACE, XXH3_freeState) +# define XXH3_copyState XXH_NAME2(XXH_NAMESPACE, XXH3_copyState) +# define XXH3_64bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset) +# define XXH3_64bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSeed) +# define XXH3_64bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_reset_withSecret) +# define XXH3_64bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_update) +# define XXH3_64bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_64bits_digest) +# define XXH3_generateSecret XXH_NAME2(XXH_NAMESPACE, XXH3_generateSecret) +/* XXH3_128bits */ +# define XXH128 XXH_NAME2(XXH_NAMESPACE, XXH128) +# define XXH3_128bits XXH_NAME2(XXH_NAMESPACE, XXH3_128bits) +# define XXH3_128bits_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSeed) +# define XXH3_128bits_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_withSecret) +# define XXH3_128bits_reset XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset) +# define XXH3_128bits_reset_withSeed XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSeed) +# define XXH3_128bits_reset_withSecret XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_reset_withSecret) +# define XXH3_128bits_update XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_update) +# define XXH3_128bits_digest XXH_NAME2(XXH_NAMESPACE, XXH3_128bits_digest) +# define XXH128_isEqual XXH_NAME2(XXH_NAMESPACE, XXH128_isEqual) +# define XXH128_cmp XXH_NAME2(XXH_NAMESPACE, XXH128_cmp) +# define XXH128_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH128_canonicalFromHash) +# define XXH128_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH128_hashFromCanonical) +#endif + + +/* ************************************* +* Version +***************************************/ +#define XXH_VERSION_MAJOR 0 +#define XXH_VERSION_MINOR 8 +#define XXH_VERSION_RELEASE 0 +#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) + +/*! + * @brief Obtains the xxHash version. + * + * This is only useful when xxHash is compiled as a shared library, as it is + * independent of the version defined in the header. + * + * @return `XXH_VERSION_NUMBER` as of when the function was compiled. + */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void); + + +/* **************************** +* Definitions +******************************/ +#include /* size_t */ +typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; + + +/*-********************************************************************** +* 32-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* Don't show include */ +/*! + * @brief An unsigned 32-bit integer. + * + * Not necessarily defined to `uint32_t` but functionally equivalent. + */ +typedef uint32_t XXH32_hash_t; +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint32_t XXH32_hash_t; +#else +# include +# if UINT_MAX == 0xFFFFFFFFUL + typedef unsigned int XXH32_hash_t; +# else +# if ULONG_MAX == 0xFFFFFFFFUL + typedef unsigned long XXH32_hash_t; +# else +# error "unsupported platform: need a 32-bit type" +# endif +# endif +#endif + +/*! + * @} + * + * @defgroup xxh32_family XXH32 family + * @ingroup public + * Contains functions used in the classic 32-bit xxHash algorithm. + * + * @note + * XXH32 is considered rather weak by today's standards. + * The @ref xxh3_family provides competitive speed for both 32-bit and 64-bit + * systems, and offers true 64/128 bit hash results. It provides a superior + * level of dispersion, and greatly reduces the risks of collisions. + * + * @see @ref xxh64_family, @ref xxh3_family : Other xxHash families + * @see @ref xxh32_impl for implementation details + * @{ + */ + +/*! + * @brief Calculates the 32-bit hash of @p input using xxHash32. + * + * Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark): 5.4 GB/s + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 32-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 32-bit hash value. + * + * @see + * XXH64(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): + * Direct equivalents for the other variants of xxHash. + * @see + * XXH32_createState(), XXH32_update(), XXH32_digest(): Streaming version. + */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, XXH32_hash_t seed); + +/*! + * Streaming functions generate the xxHash value from an incremental input. + * This method is slower than single-call functions, due to state management. + * For small inputs, prefer `XXH32()` and `XXH64()`, which are better optimized. + * + * An XXH state must first be allocated using `XXH*_createState()`. + * + * Start a new hash by initializing the state with a seed using `XXH*_reset()`. + * + * Then, feed the hash state by calling `XXH*_update()` as many times as necessary. + * + * The function returns an error code, with 0 meaning OK, and any other value + * meaning there is an error. + * + * Finally, a hash value can be produced anytime, by using `XXH*_digest()`. + * This function returns the nn-bits hash as an int or long long. + * + * It's still possible to continue inserting input into the hash state after a + * digest, and generate new hash values later on by invoking `XXH*_digest()`. + * + * When done, release the state using `XXH*_freeState()`. + * + * Example code for incrementally hashing a file: + * @code{.c} + * #include + * #include + * #define BUFFER_SIZE 256 + * + * // Note: XXH64 and XXH3 use the same interface. + * XXH32_hash_t + * hashFile(FILE* stream) + * { + * XXH32_state_t* state; + * unsigned char buf[BUFFER_SIZE]; + * size_t amt; + * XXH32_hash_t hash; + * + * state = XXH32_createState(); // Create a state + * assert(state != NULL); // Error check here + * XXH32_reset(state, 0xbaad5eed); // Reset state with our seed + * while ((amt = fread(buf, 1, sizeof(buf), stream)) != 0) { + * XXH32_update(state, buf, amt); // Hash the file in chunks + * } + * hash = XXH32_digest(state); // Finalize the hash + * XXH32_freeState(state); // Clean up + * return hash; + * } + * @endcode + */ + +/*! + * @typedef struct XXH32_state_s XXH32_state_t + * @brief The opaque state struct for the XXH32 streaming API. + * + * @see XXH32_state_s for details. + */ +typedef struct XXH32_state_s XXH32_state_t; + +/*! + * @brief Allocates an @ref XXH32_state_t. + * + * Must be freed with XXH32_freeState(). + * @return An allocated XXH32_state_t on success, `NULL` on failure. + */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); +/*! + * @brief Frees an @ref XXH32_state_t. + * + * Must be allocated with XXH32_createState(). + * @param statePtr A pointer to an @ref XXH32_state_t allocated with @ref XXH32_createState(). + * @return XXH_OK. + */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +/*! + * @brief Copies one @ref XXH32_state_t to another. + * + * @param dst_state The state to copy to. + * @param src_state The state to copy from. + * @pre + * @p dst_state and @p src_state must not be `NULL` and must not overlap. + */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); + +/*! + * @brief Resets an @ref XXH32_state_t to begin a new hash. + * + * This function resets and seeds a state. Call it before @ref XXH32_update(). + * + * @param statePtr The state struct to reset. + * @param seed The 32-bit seed to alter the hash result predictably. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, XXH32_hash_t seed); + +/*! + * @brief Consumes a block of @p input to an @ref XXH32_state_t. + * + * Call this to incrementally consume blocks of data. + * + * @param statePtr The state struct to update. + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * + * @pre + * @p statePtr must not be `NULL`. + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return @ref XXH_OK on success, @ref XXH_ERROR on failure. + */ +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); + +/*! + * @brief Returns the calculated hash value from an @ref XXH32_state_t. + * + * @note + * Calling XXH32_digest() will not affect @p statePtr, so you can update, + * digest, and update again. + * + * @param statePtr The state struct to calculate the hash from. + * + * @pre + * @p statePtr must not be `NULL`. + * + * @return The calculated xxHash32 value from that state. + */ +XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); + +/******* Canonical representation *******/ + +/* + * The default return values from XXH functions are unsigned 32 and 64 bit + * integers. + * This the simplest and fastest format for further post-processing. + * + * However, this leaves open the question of what is the order on the byte level, + * since little and big endian conventions will store the same number differently. + * + * The canonical representation settles this issue by mandating big-endian + * convention, the same convention as human-readable numbers (large digits first). + * + * When writing hash values to storage, sending them over a network, or printing + * them, it's highly recommended to use the canonical representation to ensure + * portability across a wider range of systems, present and future. + * + * The following functions allow transformation of hash values to and from + * canonical format. + */ + +/*! + * @brief Canonical (big endian) representation of @ref XXH32_hash_t. + */ +typedef struct { + unsigned char digest[4]; /*!< Hash bytes, big endian */ +} XXH32_canonical_t; + +/*! + * @brief Converts an @ref XXH32_hash_t to a big endian @ref XXH32_canonical_t. + * + * @param dst The @ref XXH32_canonical_t pointer to be stored to. + * @param hash The @ref XXH32_hash_t to be converted. + * + * @pre + * @p dst must not be `NULL`. + */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); + +/*! + * @brief Converts an @ref XXH32_canonical_t to a native @ref XXH32_hash_t. + * + * @param src The @ref XXH32_canonical_t to convert. + * + * @pre + * @p src must not be `NULL`. + * + * @return The converted hash. + */ +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); + + +/*! + * @} + * @ingroup public + * @{ + */ + +#ifndef XXH_NO_LONG_LONG +/*-********************************************************************** +* 64-bit hash +************************************************************************/ +#if defined(XXH_DOXYGEN) /* don't include */ +/*! + * @brief An unsigned 64-bit integer. + * + * Not necessarily defined to `uint64_t` but functionally equivalent. + */ +typedef uint64_t XXH64_hash_t; +#elif !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint64_t XXH64_hash_t; +#else +# include +# if defined(__LP64__) && ULONG_MAX == 0xFFFFFFFFFFFFFFFFULL + /* LP64 ABI says uint64_t is unsigned long */ + typedef unsigned long XXH64_hash_t; +# else + /* the following type must have a width of 64-bit */ + typedef unsigned long long XXH64_hash_t; +# endif +#endif + +/*! + * @} + * + * @defgroup xxh64_family XXH64 family + * @ingroup public + * @{ + * Contains functions used in the classic 64-bit xxHash algorithm. + * + * @note + * XXH3 provides competitive speed for both 32-bit and 64-bit systems, + * and offers true 64/128 bit hash results. It provides a superior level of + * dispersion, and greatly reduces the risks of collisions. + */ + + +/*! + * @brief Calculates the 64-bit hash of @p input using xxHash64. + * + * This function usually runs faster on 64-bit systems, but slower on 32-bit + * systems (see benchmark). + * + * @param input The block of data to be hashed, at least @p length bytes in size. + * @param length The length of @p input, in bytes. + * @param seed The 64-bit seed to alter the hash's output predictably. + * + * @pre + * The memory between @p input and @p input + @p length must be valid, + * readable, contiguous memory. However, if @p length is `0`, @p input may be + * `NULL`. In C++, this also must be *TriviallyCopyable*. + * + * @return The calculated 64-bit hash. + * + * @see + * XXH32(), XXH3_64bits_withSeed(), XXH3_128bits_withSeed(), XXH128(): + * Direct equivalents for the other variants of xxHash. + * @see + * XXH64_createState(), XXH64_update(), XXH64_digest(): Streaming version. + */ +XXH_PUBLIC_API XXH64_hash_t XXH64(const void* input, size_t length, XXH64_hash_t seed); + +/******* Streaming *******/ +/*! + * @brief The opaque state struct for the XXH64 streaming API. + * + * @see XXH64_state_s for details. + */ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); + +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, XXH64_hash_t seed); +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); + +/******* Canonical representation *******/ +typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t; +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); + +/*! + * @} + * ************************************************************************ + * @defgroup xxh3_family XXH3 family + * @ingroup public + * @{ + * + * XXH3 is a more recent hash algorithm featuring: + * - Improved speed for both small and large inputs + * - True 64-bit and 128-bit outputs + * - SIMD acceleration + * - Improved 32-bit viability + * + * Speed analysis methodology is explained here: + * + * https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html + * + * Compared to XXH64, expect XXH3 to run approximately + * ~2x faster on large inputs and >3x faster on small ones, + * exact differences vary depending on platform. + * + * XXH3's speed benefits greatly from SIMD and 64-bit arithmetic, + * but does not require it. + * Any 32-bit and 64-bit targets that can run XXH32 smoothly + * can run XXH3 at competitive speeds, even without vector support. + * Further details are explained in the implementation. + * + * Optimized implementations are provided for AVX512, AVX2, SSE2, NEON, POWER8, + * ZVector and scalar targets. This can be controlled via the XXH_VECTOR macro. + * + * XXH3 implementation is portable: + * it has a generic C90 formulation that can be compiled on any platform, + * all implementations generage exactly the same hash value on all platforms. + * Starting from v0.8.0, it's also labelled "stable", meaning that + * any future version will also generate the same hash value. + * + * XXH3 offers 2 variants, _64bits and _128bits. + * + * When only 64 bits are needed, prefer invoking the _64bits variant, as it + * reduces the amount of mixing, resulting in faster speed on small inputs. + * It's also generally simpler to manipulate a scalar return type than a struct. + * + * The API supports one-shot hashing, streaming mode, and custom secrets. + */ + +/*-********************************************************************** +* XXH3 64-bit variant +************************************************************************/ + +/* XXH3_64bits(): + * default 64-bit variant, using default secret and default seed of 0. + * It's the fastest variant. */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* data, size_t len); + +/* + * XXH3_64bits_withSeed(): + * This variant generates a custom secret on the fly + * based on default secret altered using the `seed` value. + * While this operation is decently fast, note that it's not completely free. + * Note: seed==0 produces the same results as XXH3_64bits(). + */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSeed(const void* data, size_t len, XXH64_hash_t seed); + +/*! + * The bare minimum size for a custom secret. + * + * @see + * XXH3_64bits_withSecret(), XXH3_64bits_reset_withSecret(), + * XXH3_128bits_withSecret(), XXH3_128bits_reset_withSecret(). + */ +#define XXH3_SECRET_SIZE_MIN 136 + +/* + * XXH3_64bits_withSecret(): + * It's possible to provide any blob of bytes as a "secret" to generate the hash. + * This makes it more difficult for an external actor to prepare an intentional collision. + * The main condition is that secretSize *must* be large enough (>= XXH3_SECRET_SIZE_MIN). + * However, the quality of produced hash values depends on secret's entropy. + * Technically, the secret must look like a bunch of random bytes. + * Avoid "trivial" or structured data such as repeated sequences or a text document. + * Whenever unsure about the "randomness" of the blob of bytes, + * consider relabelling it as a "custom seed" instead, + * and employ "XXH3_generateSecret()" (see below) + * to generate a high entropy secret derived from the custom seed. + */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize); + + +/******* Streaming *******/ +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + */ + +/*! + * @brief The state struct for the XXH3 streaming API. + * + * @see XXH3_state_s for details. + */ +typedef struct XXH3_state_s XXH3_state_t; +XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr); +XXH_PUBLIC_API void XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state); + +/* + * XXH3_64bits_reset(): + * Initialize with default parameters. + * digest will be equivalent to `XXH3_64bits()`. + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH3_state_t* statePtr); +/* + * XXH3_64bits_reset_withSeed(): + * Generate a custom secret from `seed`, and store it into `statePtr`. + * digest will be equivalent to `XXH3_64bits_withSeed()`. + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed); +/* + * XXH3_64bits_reset_withSecret(): + * `secret` is referenced, it _must outlive_ the hash streaming session. + * Similar to one-shot API, `secretSize` must be >= `XXH3_SECRET_SIZE_MIN`, + * and the quality of produced hash values depends on secret's entropy + * (secret's content should look like a bunch of random bytes). + * When in doubt about the randomness of a candidate `secret`, + * consider employing `XXH3_generateSecret()` instead (see below). + */ +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize); + +XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH3_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* statePtr); + +/* note : canonical representation of XXH3 is the same as XXH64 + * since they both produce XXH64_hash_t values */ + + +/*-********************************************************************** +* XXH3 128-bit variant +************************************************************************/ + +/*! + * @brief The return value from 128-bit hashes. + * + * Stored in little endian order, although the fields themselves are in native + * endianness. + */ +typedef struct { + XXH64_hash_t low64; /*!< `value & 0xFFFFFFFFFFFFFFFF` */ + XXH64_hash_t high64; /*!< `value >> 64` */ +} XXH128_hash_t; + +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* data, size_t len); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSeed(const void* data, size_t len, XXH64_hash_t seed); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_withSecret(const void* data, size_t len, const void* secret, size_t secretSize); + +/******* Streaming *******/ +/* + * Streaming requires state maintenance. + * This operation costs memory and CPU. + * As a consequence, streaming is slower than one-shot hashing. + * For better performance, prefer one-shot functions whenever applicable. + * + * XXH3_128bits uses the same XXH3_state_t as XXH3_64bits(). + * Use already declared XXH3_createState() and XXH3_freeState(). + * + * All reset and streaming functions have same meaning as their 64-bit counterpart. + */ + +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH3_state_t* statePtr); +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed); +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize); + +XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH3_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* statePtr); + +/* Following helper functions make it possible to compare XXH128_hast_t values. + * Since XXH128_hash_t is a structure, this capability is not offered by the language. + * Note: For better performance, these functions can be inlined using XXH_INLINE_ALL */ + +/*! + * XXH128_isEqual(): + * Return: 1 if `h1` and `h2` are equal, 0 if they are not. + */ +XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2); + +/*! + * XXH128_cmp(): + * + * This comparator is compatible with stdlib's `qsort()`/`bsearch()`. + * + * return: >0 if *h128_1 > *h128_2 + * =0 if *h128_1 == *h128_2 + * <0 if *h128_1 < *h128_2 + */ +XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2); + + +/******* Canonical representation *******/ +typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t; +XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash); +XXH_PUBLIC_API XXH128_hash_t XXH128_hashFromCanonical(const XXH128_canonical_t* src); + + +#endif /* XXH_NO_LONG_LONG */ + +/*! + * @} + */ +#endif /* XXHASH_H_5627135585666179 */ + + + +#if defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) +#define XXHASH_H_STATIC_13879238742 +/* **************************************************************************** + * This section contains declarations which are not guaranteed to remain stable. + * They may change in future versions, becoming incompatible with a different + * version of the library. + * These declarations should only be used with static linking. + * Never use them in association with dynamic linking! + ***************************************************************************** */ + +/* + * These definitions are only present to allow static allocation + * of XXH states, on stack or in a struct, for example. + * Never **ever** access their members directly. + */ + +/*! + * @internal + * @brief Structure for XXH32 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH32_state_t. + * Do not access the members of this struct directly. + * @see XXH64_state_s, XXH3_state_s + */ +struct XXH32_state_s { + XXH32_hash_t total_len_32; /*!< Total length hashed, modulo 2^32 */ + XXH32_hash_t large_len; /*!< Whether the hash is >= 16 (handles @ref total_len_32 overflow) */ + XXH32_hash_t v1; /*!< First accumulator lane */ + XXH32_hash_t v2; /*!< Second accumulator lane */ + XXH32_hash_t v3; /*!< Third accumulator lane */ + XXH32_hash_t v4; /*!< Fourth accumulator lane */ + XXH32_hash_t mem32[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[16]. */ + XXH32_hash_t memsize; /*!< Amount of data in @ref mem32 */ + XXH32_hash_t reserved; /*!< Reserved field. Do not read or write to it, it may be removed. */ +}; /* typedef'd to XXH32_state_t */ + + +#ifndef XXH_NO_LONG_LONG /* defined when there is no 64-bit support */ + +/*! + * @internal + * @brief Structure for XXH64 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * Typedef'd to @ref XXH64_state_t. + * Do not access the members of this struct directly. + * @see XXH32_state_s, XXH3_state_s + */ +struct XXH64_state_s { + XXH64_hash_t total_len; /*!< Total length hashed. This is always 64-bit. */ + XXH64_hash_t v1; /*!< First accumulator lane */ + XXH64_hash_t v2; /*!< Second accumulator lane */ + XXH64_hash_t v3; /*!< Third accumulator lane */ + XXH64_hash_t v4; /*!< Fourth accumulator lane */ + XXH64_hash_t mem64[4]; /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */ + XXH32_hash_t memsize; /*!< Amount of data in @ref mem64 */ + XXH32_hash_t reserved32; /*!< Reserved field, needed for padding anyways*/ + XXH64_hash_t reserved64; /*!< Reserved field. Do not read or write to it, it may be removed. */ +}; /* typedef'd to XXH64_state_t */ + +#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11+ */ +# include +# define XXH_ALIGN(n) alignas(n) +#elif defined(__GNUC__) +# define XXH_ALIGN(n) __attribute__ ((aligned(n))) +#elif defined(_MSC_VER) +# define XXH_ALIGN(n) __declspec(align(n)) +#else +# define XXH_ALIGN(n) /* disabled */ +#endif + +/* Old GCC versions only accept the attribute after the type in structures. */ +#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) /* C11+ */ \ + && defined(__GNUC__) +# define XXH_ALIGN_MEMBER(align, type) type XXH_ALIGN(align) +#else +# define XXH_ALIGN_MEMBER(align, type) XXH_ALIGN(align) type +#endif + +/*! + * @brief The size of the internal XXH3 buffer. + * + * This is the optimal update size for incremental hashing. + * + * @see XXH3_64b_update(), XXH3_128b_update(). + */ +#define XXH3_INTERNALBUFFER_SIZE 256 + +/*! + * @brief Default size of the secret buffer (and @ref XXH3_kSecret). + * + * This is the size used in @ref XXH3_kSecret and the seeded functions. + * + * Not to be confused with @ref XXH3_SECRET_SIZE_MIN. + */ +#define XXH3_SECRET_DEFAULT_SIZE 192 + +/*! + * @internal + * @brief Structure for XXH3 streaming API. + * + * @note This is only defined when @ref XXH_STATIC_LINKING_ONLY, + * @ref XXH_INLINE_ALL, or @ref XXH_IMPLEMENTATION is defined. Otherwise it is + * an opaque type. This allows fields to safely be changed. + * + * @note **This structure has a strict alignment requirement of 64 bytes.** Do + * not allocate this with `malloc()` or `new`, it will not be sufficiently + * aligned. Use @ref XXH3_createState() and @ref XXH3_freeState(), or stack + * allocation. + * + * Typedef'd to @ref XXH3_state_t. + * Do not access the members of this struct directly. + * + * @see XXH3_INITSTATE() for stack initialization. + * @see XXH3_createState(), XXH3_freeState(). + * @see XXH32_state_s, XXH64_state_s + */ +struct XXH3_state_s { + XXH_ALIGN_MEMBER(64, XXH64_hash_t acc[8]); + /*!< The 8 accumulators. Similar to `vN` in @ref XXH32_state_s::v1 and @ref XXH64_state_s */ + XXH_ALIGN_MEMBER(64, unsigned char customSecret[XXH3_SECRET_DEFAULT_SIZE]); + /*!< Used to store a custom secret generated from a seed. */ + XXH_ALIGN_MEMBER(64, unsigned char buffer[XXH3_INTERNALBUFFER_SIZE]); + /*!< The internal buffer. @see XXH32_state_s::mem32 */ + XXH32_hash_t bufferedSize; + /*!< The amount of memory in @ref buffer, @see XXH32_state_s::memsize */ + XXH32_hash_t reserved32; + /*!< Reserved field. Needed for padding on 64-bit. */ + size_t nbStripesSoFar; + /*!< Number or stripes processed. */ + XXH64_hash_t totalLen; + /*!< Total length hashed. 64-bit even on 32-bit targets. */ + size_t nbStripesPerBlock; + /*!< Number of stripes per block. */ + size_t secretLimit; + /*!< Size of @ref customSecret or @ref extSecret */ + XXH64_hash_t seed; + /*!< Seed for _withSeed variants. Must be zero otherwise, @see XXH3_INITSTATE() */ + XXH64_hash_t reserved64; + /*!< Reserved field. */ + const unsigned char* extSecret; + /*!< Reference to an external secret for the _withSecret variants, NULL + * for other variants. */ + /* note: there may be some padding at the end due to alignment on 64 bytes */ +}; /* typedef'd to XXH3_state_t */ + +#undef XXH_ALIGN_MEMBER + +/*! + * @brief Initializes a stack-allocated `XXH3_state_s`. + * + * When the @ref XXH3_state_t structure is merely emplaced on stack, + * it should be initialized with XXH3_INITSTATE() or a memset() + * in case its first reset uses XXH3_NNbits_reset_withSeed(). + * This init can be omitted if the first reset uses default or _withSecret mode. + * This operation isn't necessary when the state is created with XXH3_createState(). + * Note that this doesn't prepare the state for a streaming operation, + * it's still necessary to use XXH3_NNbits_reset*() afterwards. + */ +#define XXH3_INITSTATE(XXH3_state_ptr) { (XXH3_state_ptr)->seed = 0; } + + +/* === Experimental API === */ +/* Symbols defined below must be considered tied to a specific library version. */ + +/* + * XXH3_generateSecret(): + * + * Derive a high-entropy secret from any user-defined content, named customSeed. + * The generated secret can be used in combination with `*_withSecret()` functions. + * The `_withSecret()` variants are useful to provide a higher level of protection than 64-bit seed, + * as it becomes much more difficult for an external actor to guess how to impact the calculation logic. + * + * The function accepts as input a custom seed of any length and any content, + * and derives from it a high-entropy secret of length XXH3_SECRET_DEFAULT_SIZE + * into an already allocated buffer secretBuffer. + * The generated secret is _always_ XXH_SECRET_DEFAULT_SIZE bytes long. + * + * The generated secret can then be used with any `*_withSecret()` variant. + * Functions `XXH3_128bits_withSecret()`, `XXH3_64bits_withSecret()`, + * `XXH3_128bits_reset_withSecret()` and `XXH3_64bits_reset_withSecret()` + * are part of this list. They all accept a `secret` parameter + * which must be very long for implementation reasons (>= XXH3_SECRET_SIZE_MIN) + * _and_ feature very high entropy (consist of random-looking bytes). + * These conditions can be a high bar to meet, so + * this function can be used to generate a secret of proper quality. + * + * customSeed can be anything. It can have any size, even small ones, + * and its content can be anything, even stupidly "low entropy" source such as a bunch of zeroes. + * The resulting `secret` will nonetheless provide all expected qualities. + * + * Supplying NULL as the customSeed copies the default secret into `secretBuffer`. + * When customSeedSize > 0, supplying NULL as customSeed is undefined behavior. + */ +XXH_PUBLIC_API void XXH3_generateSecret(void* secretBuffer, const void* customSeed, size_t customSeedSize); + + +/* simple short-cut to pre-selected XXH3_128bits variant */ +XXH_PUBLIC_API XXH128_hash_t XXH128(const void* data, size_t len, XXH64_hash_t seed); + + +#endif /* XXH_NO_LONG_LONG */ +#if defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) +# define XXH_IMPLEMENTATION +#endif + +#endif /* defined(XXH_STATIC_LINKING_ONLY) && !defined(XXHASH_H_STATIC_13879238742) */ + + +/* ======================================================================== */ +/* ======================================================================== */ +/* ======================================================================== */ + + +/*-********************************************************************** + * xxHash implementation + *-********************************************************************** + * xxHash's implementation used to be hosted inside xxhash.c. + * + * However, inlining requires implementation to be visible to the compiler, + * hence be included alongside the header. + * Previously, implementation was hosted inside xxhash.c, + * which was then #included when inlining was activated. + * This construction created issues with a few build and install systems, + * as it required xxhash.c to be stored in /include directory. + * + * xxHash implementation is now directly integrated within xxhash.h. + * As a consequence, xxhash.c is no longer needed in /include. + * + * xxhash.c is still available and is still useful. + * In a "normal" setup, when xxhash is not inlined, + * xxhash.h only exposes the prototypes and public symbols, + * while xxhash.c can be built into an object file xxhash.o + * which can then be linked into the final binary. + ************************************************************************/ + +#if ( defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API) \ + || defined(XXH_IMPLEMENTATION) ) && !defined(XXH_IMPLEM_13a8737387) +# define XXH_IMPLEM_13a8737387 + +/* ************************************* +* Tuning parameters +***************************************/ + +/*! + * @defgroup tuning Tuning parameters + * @{ + * + * Various macros to control xxHash's behavior. + */ +#ifdef XXH_DOXYGEN +/*! + * @brief Define this to disable 64-bit code. + * + * Useful if only using the @ref xxh32_family and you have a strict C90 compiler. + */ +# define XXH_NO_LONG_LONG +# undef XXH_NO_LONG_LONG /* don't actually */ +/*! + * @brief Controls how unaligned memory is accessed. + * + * By default, access to unaligned memory is controlled by `memcpy()`, which is + * safe and portable. + * + * Unfortunately, on some target/compiler combinations, the generated assembly + * is sub-optimal. + * + * The below switch allow selection of a different access method + * in the search for improved performance. + * + * @par Possible options: + * + * - `XXH_FORCE_MEMORY_ACCESS=0` (default): `memcpy` + * @par + * Use `memcpy()`. Safe and portable. Note that most modern compilers will + * eliminate the function call and treat it as an unaligned access. + * + * - `XXH_FORCE_MEMORY_ACCESS=1`: `__attribute__((packed))` + * @par + * Depends on compiler extensions and is therefore not portable. + * This method is safe _if_ your compiler supports it, + * and *generally* as fast or faster than `memcpy`. + * + * - `XXH_FORCE_MEMORY_ACCESS=2`: Direct cast + * @par + * Casts directly and dereferences. This method doesn't depend on the + * compiler, but it violates the C standard as it directly dereferences an + * unaligned pointer. It can generate buggy code on targets which do not + * support unaligned memory accesses, but in some circumstances, it's the + * only known way to get the most performance. + * + * - `XXH_FORCE_MEMORY_ACCESS=3`: Byteshift + * @par + * Also portable. This can generate the best code on old compilers which don't + * inline small `memcpy()` calls, and it might also be faster on big-endian + * systems which lack a native byteswap instruction. However, some compilers + * will emit literal byteshifts even if the target supports unaligned access. + * . + * + * @warning + * Methods 1 and 2 rely on implementation-defined behavior. Use these with + * care, as what works on one compiler/platform/optimization level may cause + * another to read garbage data or even crash. + * + * See https://stackoverflow.com/a/32095106/646947 for details. + * + * Prefer these methods in priority order (0 > 3 > 1 > 2) + */ +# define XXH_FORCE_MEMORY_ACCESS 0 +/*! + * @def XXH_ACCEPT_NULL_INPUT_POINTER + * @brief Whether to add explicit `NULL` checks. + * + * If the input pointer is `NULL` and the length is non-zero, xxHash's default + * behavior is to dereference it, triggering a segfault. + * + * When this macro is enabled, xxHash actively checks the input for a null pointer. + * If it is, the result for null input pointers is the same as a zero-length input. + */ +# define XXH_ACCEPT_NULL_INPUT_POINTER 0 +/*! + * @def XXH_FORCE_ALIGN_CHECK + * @brief If defined to non-zero, adds a special path for aligned inputs (XXH32() + * and XXH64() only). + * + * This is an important performance trick for architectures without decent + * unaligned memory access performance. + * + * It checks for input alignment, and when conditions are met, uses a "fast + * path" employing direct 32-bit/64-bit reads, resulting in _dramatically + * faster_ read speed. + * + * The check costs one initial branch per hash, which is generally negligible, + * but not zero. + * + * Moreover, it's not useful to generate an additional code path if memory + * access uses the same instruction for both aligned and unaligned + * addresses (e.g. x86 and aarch64). + * + * In these cases, the alignment check can be removed by setting this macro to 0. + * Then the code will always use unaligned memory access. + * Align check is automatically disabled on x86, x64 & arm64, + * which are platforms known to offer good unaligned memory accesses performance. + * + * This option does not affect XXH3 (only XXH32 and XXH64). + */ +# define XXH_FORCE_ALIGN_CHECK 0 + +/*! + * @def XXH_NO_INLINE_HINTS + * @brief When non-zero, sets all functions to `static`. + * + * By default, xxHash tries to force the compiler to inline almost all internal + * functions. + * + * This can usually improve performance due to reduced jumping and improved + * constant folding, but significantly increases the size of the binary which + * might not be favorable. + * + * Additionally, sometimes the forced inlining can be detrimental to performance, + * depending on the architecture. + * + * XXH_NO_INLINE_HINTS marks all internal functions as static, giving the + * compiler full control on whether to inline or not. + * + * When not optimizing (-O0), optimizing for size (-Os, -Oz), or using + * -fno-inline with GCC or Clang, this will automatically be defined. + */ +# define XXH_NO_INLINE_HINTS 0 + +/*! + * @def XXH_REROLL + * @brief Whether to reroll `XXH32_finalize` and `XXH64_finalize`. + * + * For performance, `XXH32_finalize` and `XXH64_finalize` use an unrolled loop + * in the form of a switch statement. + * + * This is not always desirable, as it generates larger code, and depending on + * the architecture, may even be slower + * + * This is automatically defined with `-Os`/`-Oz` on GCC and Clang. + */ +# define XXH_REROLL 0 + +/*! + * @internal + * @brief Redefines old internal names. + * + * For compatibility with code that uses xxHash's internals before the names + * were changed to improve namespacing. There is no other reason to use this. + */ +# define XXH_OLD_NAMES +# undef XXH_OLD_NAMES /* don't actually use, it is ugly. */ +#endif /* XXH_DOXYGEN */ +/*! + * @} + */ + +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ + /* prefer __packed__ structures (method 1) for gcc on armv7 and armv8 */ +# if !defined(__clang__) && ( \ + (defined(__INTEL_COMPILER) && !defined(_WIN32)) || \ + (defined(__GNUC__) && (defined(__ARM_ARCH) && __ARM_ARCH >= 7)) ) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */ +# define XXH_ACCEPT_NULL_INPUT_POINTER 0 +#endif + +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ +# if defined(__i386) || defined(__x86_64__) || defined(__aarch64__) \ + || defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64) /* visual */ +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + +#ifndef XXH_NO_INLINE_HINTS +# if defined(__OPTIMIZE_SIZE__) /* -Os, -Oz */ \ + || defined(__NO_INLINE__) /* -O0, -fno-inline */ +# define XXH_NO_INLINE_HINTS 1 +# else +# define XXH_NO_INLINE_HINTS 0 +# endif +#endif + +#ifndef XXH_REROLL +# if defined(__OPTIMIZE_SIZE__) +# define XXH_REROLL 1 +# else +# define XXH_REROLL 0 +# endif +#endif + +/*! + * @defgroup impl Implementation + * @{ + */ + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +/* + * Modify the local functions below should you wish to use + * different memory routines for malloc() and free() + */ +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than malloc(). + */ +static void* XXH_malloc(size_t s) { return malloc(s); } + +/*! + * @internal + * @brief Modify this function to use a different routine than free(). + */ +static void XXH_free(void* p) { free(p); } + +#include + +/*! + * @internal + * @brief Modify this function to use a different routine than memcpy(). + */ +static void* XXH_memcpy(void* dest, const void* src, size_t size) +{ + return memcpy(dest,src,size); +} + +#include /* ULLONG_MAX */ + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#ifdef _MSC_VER /* Visual Studio warning fix */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#endif + +#if XXH_NO_INLINE_HINTS /* disable inlining hints */ +# if defined(__GNUC__) +# define XXH_FORCE_INLINE static __attribute__((unused)) +# else +# define XXH_FORCE_INLINE static +# endif +# define XXH_NO_INLINE static +/* enable inlining hints */ +#elif defined(_MSC_VER) /* Visual Studio */ +# define XXH_FORCE_INLINE static __forceinline +# define XXH_NO_INLINE static __declspec(noinline) +#elif defined(__GNUC__) +# define XXH_FORCE_INLINE static __inline__ __attribute__((always_inline, unused)) +# define XXH_NO_INLINE static __attribute__((noinline)) +#elif defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) /* C99 */ +# define XXH_FORCE_INLINE static inline +# define XXH_NO_INLINE static +#else +# define XXH_FORCE_INLINE static +# define XXH_NO_INLINE static +#endif + + + +/* ************************************* +* Debug +***************************************/ +/*! + * @ingroup tuning + * @def XXH_DEBUGLEVEL + * @brief Sets the debugging level. + * + * XXH_DEBUGLEVEL is expected to be defined externally, typically via the + * compiler's command line options. The value must be a number. + */ +#ifndef XXH_DEBUGLEVEL +# ifdef DEBUGLEVEL /* backwards compat */ +# define XXH_DEBUGLEVEL DEBUGLEVEL +# else +# define XXH_DEBUGLEVEL 0 +# endif +#endif + +#if (XXH_DEBUGLEVEL>=1) +# include /* note: can still be disabled with NDEBUG */ +# define XXH_ASSERT(c) assert(c) +#else +# define XXH_ASSERT(c) ((void)0) +#endif + +/* note: use after variable declarations */ +#define XXH_STATIC_ASSERT(c) do { enum { XXH_sa = 1/(int)(!!(c)) }; } while (0) + + +/* ************************************* +* Basic Types +***************************************/ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint8_t xxh_u8; +#else + typedef unsigned char xxh_u8; +#endif +typedef XXH32_hash_t xxh_u32; + +#ifdef XXH_OLD_NAMES +# define BYTE xxh_u8 +# define U8 xxh_u8 +# define U32 xxh_u32 +#endif + +/* *** Memory access *** */ + +/*! + * @internal + * @fn xxh_u32 XXH_read32(const void* ptr) + * @brief Reads an unaligned 32-bit integer from @p ptr in native endianness. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit native endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32(const void* ptr) + * @brief Reads an unaligned 32-bit little endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readBE32(const void* ptr) + * @brief Reads an unaligned 32-bit big endian integer from @p ptr. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * + * @param ptr The pointer to read from. + * @return The 32-bit big endian integer from the bytes at @p ptr. + */ + +/*! + * @internal + * @fn xxh_u32 XXH_readLE32_align(const void* ptr, XXH_alignment align) + * @brief Like @ref XXH_readLE32(), but has an option for aligned reads. + * + * Affected by @ref XXH_FORCE_MEMORY_ACCESS. + * Note that when @ref XXH_FORCE_ALIGN_CHECK == 0, the @p align parameter is + * always @ref XXH_alignment::XXH_unaligned. + * + * @param ptr The pointer to read from. + * @param align Whether @p ptr is aligned. + * @pre + * If @p align == @ref XXH_alignment::XXH_aligned, @p ptr must be 4 byte + * aligned. + * @return The 32-bit little endian integer from the bytes at @p ptr. + */ + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE32 and XXH_readBE32. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* + * Force direct memory access. Only works on CPU which support unaligned memory + * access in hardware. + */ +static xxh_u32 XXH_read32(const void* memPtr) { return *(const xxh_u32*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __pack instructions are safer but compiler specific, hence potentially + * problematic for some compilers. + * + * Currently only defined for GCC and ICC. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; } __attribute__((packed)) unalign; +#endif +static xxh_u32 XXH_read32(const void* ptr) +{ + typedef union { xxh_u32 u32; } __attribute__((packed)) xxh_unalign; + return ((const xxh_unalign*)ptr)->u32; +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://stackoverflow.com/a/32095106/646947 + */ +static xxh_u32 XXH_read32(const void* memPtr) +{ + xxh_u32 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* *** Endianness *** */ +typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; + +/*! + * @ingroup tuning + * @def XXH_CPU_LITTLE_ENDIAN + * @brief Whether the target is little endian. + * + * Defined to 1 if the target is little endian, or 0 if it is big endian. + * It can be defined externally, for example on the compiler command line. + * + * If it is not defined, a runtime check (which is usually constant folded) + * is used instead. + * + * @note + * This is not necessarily defined to an integer constant. + * + * @see XXH_isLittleEndian() for the runtime check. + */ +#ifndef XXH_CPU_LITTLE_ENDIAN +/* + * Try to detect endianness automatically, to avoid the nonstandard behavior + * in `XXH_isLittleEndian()` + */ +# if defined(_WIN32) /* Windows is always little endian */ \ + || defined(__LITTLE_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 1 +# elif defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_CPU_LITTLE_ENDIAN 0 +# else +/*! + * @internal + * @brief Runtime check for @ref XXH_CPU_LITTLE_ENDIAN. + * + * Most compilers will constant fold this. + */ +static int XXH_isLittleEndian(void) +{ + /* + * Portable and well-defined behavior. + * Don't use static: it is detrimental to performance. + */ + const union { xxh_u32 u; xxh_u8 c[4]; } one = { 1 }; + return one.c[0]; +} +# define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian() +# endif +#endif + + + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#ifdef __has_builtin +# define XXH_HAS_BUILTIN(x) __has_builtin(x) +#else +# define XXH_HAS_BUILTIN(x) 0 +#endif + +/*! + * @internal + * @def XXH_rotl32(x,r) + * @brief 32-bit rotate left. + * + * @param x The 32-bit integer to be rotated. + * @param r The number of bits to rotate. + * @pre + * @p r > 0 && @p r < 32 + * @note + * @p x and @p r may be evaluated multiple times. + * @return The rotated result. + */ +#if !defined(NO_CLANG_BUILTIN) && XXH_HAS_BUILTIN(__builtin_rotateleft32) \ + && XXH_HAS_BUILTIN(__builtin_rotateleft64) +# define XXH_rotl32 __builtin_rotateleft32 +# define XXH_rotl64 __builtin_rotateleft64 +/* Note: although _rotl exists for minGW (GCC under windows), performance seems poor */ +#elif defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) +# define XXH_rotl64(x,r) (((x) << (r)) | ((x) >> (64 - (r)))) +#endif + +/*! + * @internal + * @fn xxh_u32 XXH_swap32(xxh_u32 x) + * @brief A 32-bit byteswap. + * + * @param x The 32-bit integer to byteswap. + * @return @p x, byteswapped. + */ +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static xxh_u32 XXH_swap32 (xxh_u32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +#endif + + +/* *************************** +* Memory reads +*****************************/ + +/*! + * @internal + * @brief Enum to indicate whether a pointer is aligned. + */ +typedef enum { + XXH_aligned, /*!< Aligned */ + XXH_unaligned /*!< Possibly unaligned */ +} XXH_alignment; + +/* + * XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. + * + * This is ideal for older compilers which don't inline memcpy. + */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u32)bytePtr[1] << 8) + | ((xxh_u32)bytePtr[2] << 16) + | ((xxh_u32)bytePtr[3] << 24); +} + +XXH_FORCE_INLINE xxh_u32 XXH_readBE32(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[3] + | ((xxh_u32)bytePtr[2] << 8) + | ((xxh_u32)bytePtr[1] << 16) + | ((xxh_u32)bytePtr[0] << 24); +} + +#else +XXH_FORCE_INLINE xxh_u32 XXH_readLE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); +} + +static xxh_u32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u32 +XXH_readLE32_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) { + return XXH_readLE32(ptr); + } else { + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u32*)ptr : XXH_swap32(*(const xxh_u32*)ptr); + } +} + + +/* ************************************* +* Misc +***************************************/ +/*! @ingroup public */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ******************************************************************* +* 32-bit hash functions +*********************************************************************/ +/*! + * @} + * @defgroup xxh32_impl XXH32 implementation + * @ingroup impl + * @{ + */ +static const xxh_u32 XXH_PRIME32_1 = 0x9E3779B1U; /*!< 0b10011110001101110111100110110001 */ +static const xxh_u32 XXH_PRIME32_2 = 0x85EBCA77U; /*!< 0b10000101111010111100101001110111 */ +static const xxh_u32 XXH_PRIME32_3 = 0xC2B2AE3DU; /*!< 0b11000010101100101010111000111101 */ +static const xxh_u32 XXH_PRIME32_4 = 0x27D4EB2FU; /*!< 0b00100111110101001110101100101111 */ +static const xxh_u32 XXH_PRIME32_5 = 0x165667B1U; /*!< 0b00010110010101100110011110110001 */ + +#ifdef XXH_OLD_NAMES +# define PRIME32_1 XXH_PRIME32_1 +# define PRIME32_2 XXH_PRIME32_2 +# define PRIME32_3 XXH_PRIME32_3 +# define PRIME32_4 XXH_PRIME32_4 +# define PRIME32_5 XXH_PRIME32_5 +#endif + +/*! + * @internal + * @brief Normal stripe processing routine. + * + * This shuffles the bits so that any bit from @p input impacts several bits in + * @p acc. + * + * @param acc The accumulator lane. + * @param input The stripe of input to mix. + * @return The mixed accumulator lane. + */ +static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input) +{ + acc += input * XXH_PRIME32_2; + acc = XXH_rotl32(acc, 13); + acc *= XXH_PRIME32_1; +#if defined(__GNUC__) && defined(__SSE4_1__) && !defined(XXH_ENABLE_AUTOVECTORIZE) + /* + * UGLY HACK: + * This inline assembly hack forces acc into a normal register. This is the + * only thing that prevents GCC and Clang from autovectorizing the XXH32 + * loop (pragmas and attributes don't work for some reason) without globally + * disabling SSE4.1. + * + * The reason we want to avoid vectorization is because despite working on + * 4 integers at a time, there are multiple factors slowing XXH32 down on + * SSE4: + * - There's a ridiculous amount of lag from pmulld (10 cycles of latency on + * newer chips!) making it slightly slower to multiply four integers at + * once compared to four integers independently. Even when pmulld was + * fastest, Sandy/Ivy Bridge, it is still not worth it to go into SSE + * just to multiply unless doing a long operation. + * + * - Four instructions are required to rotate, + * movqda tmp, v // not required with VEX encoding + * pslld tmp, 13 // tmp <<= 13 + * psrld v, 19 // x >>= 19 + * por v, tmp // x |= tmp + * compared to one for scalar: + * roll v, 13 // reliably fast across the board + * shldl v, v, 13 // Sandy Bridge and later prefer this for some reason + * + * - Instruction level parallelism is actually more beneficial here because + * the SIMD actually serializes this operation: While v1 is rotating, v2 + * can load data, while v3 can multiply. SSE forces them to operate + * together. + * + * How this hack works: + * __asm__("" // Declare an assembly block but don't declare any instructions + * : // However, as an Input/Output Operand, + * "+r" // constrain a read/write operand (+) as a general purpose register (r). + * (acc) // and set acc as the operand + * ); + * + * Because of the 'r', the compiler has promised that seed will be in a + * general purpose register and the '+' says that it will be 'read/write', + * so it has to assume it has changed. It is like volatile without all the + * loads and stores. + * + * Since the argument has to be in a normal register (not an SSE register), + * each time XXH32_round is called, it is impossible to vectorize. + */ + __asm__("" : "+r" (acc)); +#endif + return acc; +} + +/*! + * @internal + * @brief Mixes all bits to finalize the hash. + * + * The final mix ensures that all input bits have a chance to impact any bit in + * the output digest, resulting in an unbiased distribution. + * + * @param h32 The hash to avalanche. + * @return The avalanched hash. + */ +static xxh_u32 XXH32_avalanche(xxh_u32 h32) +{ + h32 ^= h32 >> 15; + h32 *= XXH_PRIME32_2; + h32 ^= h32 >> 13; + h32 *= XXH_PRIME32_3; + h32 ^= h32 >> 16; + return(h32); +} + +#define XXH_get32bits(p) XXH_readLE32_align(p, align) + +/*! + * @internal + * @brief Processes the last 0-15 bytes of @p ptr. + * + * There may be up to 15 bytes remaining to consume from the input. + * This final stage will digest them to ensure that all input bytes are present + * in the final mix. + * + * @param h32 The hash to finalize. + * @param ptr The pointer to the remaining input. + * @param len The remaining length, modulo 16. + * @param align Whether @p ptr is aligned. + * @return The finalized hash. + */ +static xxh_u32 +XXH32_finalize(xxh_u32 h32, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ +#define XXH_PROCESS1 do { \ + h32 += (*ptr++) * XXH_PRIME32_5; \ + h32 = XXH_rotl32(h32, 11) * XXH_PRIME32_1; \ +} while (0) + +#define XXH_PROCESS4 do { \ + h32 += XXH_get32bits(ptr) * XXH_PRIME32_3; \ + ptr += 4; \ + h32 = XXH_rotl32(h32, 17) * XXH_PRIME32_4; \ +} while (0) + + /* Compact rerolled version */ + if (XXH_REROLL) { + len &= 15; + while (len >= 4) { + XXH_PROCESS4; + len -= 4; + } + while (len > 0) { + XXH_PROCESS1; + --len; + } + return XXH32_avalanche(h32); + } else { + switch(len&15) /* or switch(bEnd - p) */ { + case 12: XXH_PROCESS4; + /* fallthrough */ + case 8: XXH_PROCESS4; + /* fallthrough */ + case 4: XXH_PROCESS4; + return XXH32_avalanche(h32); + + case 13: XXH_PROCESS4; + /* fallthrough */ + case 9: XXH_PROCESS4; + /* fallthrough */ + case 5: XXH_PROCESS4; + XXH_PROCESS1; + return XXH32_avalanche(h32); + + case 14: XXH_PROCESS4; + /* fallthrough */ + case 10: XXH_PROCESS4; + /* fallthrough */ + case 6: XXH_PROCESS4; + XXH_PROCESS1; + XXH_PROCESS1; + return XXH32_avalanche(h32); + + case 15: XXH_PROCESS4; + /* fallthrough */ + case 11: XXH_PROCESS4; + /* fallthrough */ + case 7: XXH_PROCESS4; + /* fallthrough */ + case 3: XXH_PROCESS1; + /* fallthrough */ + case 2: XXH_PROCESS1; + /* fallthrough */ + case 1: XXH_PROCESS1; + /* fallthrough */ + case 0: return XXH32_avalanche(h32); + } + XXH_ASSERT(0); + return h32; /* reaching this point is deemed impossible */ + } +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1 XXH_PROCESS1 +# define PROCESS4 XXH_PROCESS4 +#else +# undef XXH_PROCESS1 +# undef XXH_PROCESS4 +#endif + +/*! + * @internal + * @brief The implementation for @ref XXH32(). + * + * @param input, len, seed Directly passed from @ref XXH32(). + * @param align Whether @p input is aligned. + * @return The calculated hash. + */ +XXH_FORCE_INLINE xxh_u32 +XXH32_endian_align(const xxh_u8* input, size_t len, xxh_u32 seed, XXH_alignment align) +{ + const xxh_u8* bEnd = input + len; + xxh_u32 h32; + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (input==NULL) { + len=0; + bEnd=input=(const xxh_u8*)(size_t)16; + } +#endif + + if (len>=16) { + const xxh_u8* const limit = bEnd - 15; + xxh_u32 v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + xxh_u32 v2 = seed + XXH_PRIME32_2; + xxh_u32 v3 = seed + 0; + xxh_u32 v4 = seed - XXH_PRIME32_1; + + do { + v1 = XXH32_round(v1, XXH_get32bits(input)); input += 4; + v2 = XXH32_round(v2, XXH_get32bits(input)); input += 4; + v3 = XXH32_round(v3, XXH_get32bits(input)); input += 4; + v4 = XXH32_round(v4, XXH_get32bits(input)); input += 4; + } while (input < limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } else { + h32 = seed + XXH_PRIME32_5; + } + + h32 += (xxh_u32)len; + + return XXH32_finalize(h32, input, len&15, align); +} + +/*! @ingroup xxh32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t len, XXH32_hash_t seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_state_t state; + XXH32_reset(&state, seed); + XXH32_update(&state, (const xxh_u8*)input, len); + return XXH32_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH32_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); +#endif +} + + + +/******* Hash streaming *******/ +/*! + * @ingroup xxh32_family + */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +/*! @ingroup xxh32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup xxh32_family */ +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup xxh32_family */ +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, XXH32_hash_t seed) +{ + XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + XXH_PRIME32_1 + XXH_PRIME32_2; + state.v2 = seed + XXH_PRIME32_2; + state.v3 = seed + 0; + state.v4 = seed - XXH_PRIME32_1; + /* do not write into reserved, planned to be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + return XXH_OK; +} + + +/*! @ingroup xxh32_family */ +XXH_PUBLIC_API XXH_errorcode +XXH32_update(XXH32_state_t* state, const void* input, size_t len) +{ + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + { const xxh_u8* p = (const xxh_u8*)input; + const xxh_u8* const bEnd = p + len; + + state->total_len_32 += (XXH32_hash_t)len; + state->large_len |= (XXH32_hash_t)((len>=16) | (state->total_len_32>=16)); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, len); + state->memsize += (XXH32_hash_t)len; + return XXH_OK; + } + + if (state->memsize) { /* some data left from previous update */ + XXH_memcpy((xxh_u8*)(state->mem32) + state->memsize, input, 16-state->memsize); + { const xxh_u32* p32 = state->mem32; + state->v1 = XXH32_round(state->v1, XXH_readLE32(p32)); p32++; + state->v2 = XXH32_round(state->v2, XXH_readLE32(p32)); p32++; + state->v3 = XXH32_round(state->v3, XXH_readLE32(p32)); p32++; + state->v4 = XXH32_round(state->v4, XXH_readLE32(p32)); + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) { + const xxh_u8* const limit = bEnd - 16; + xxh_u32 v1 = state->v1; + xxh_u32 v2 = state->v2; + xxh_u32 v3 = state->v3; + xxh_u32 v4 = state->v4; + + do { + v1 = XXH32_round(v1, XXH_readLE32(p)); p+=4; + v2 = XXH32_round(v2, XXH_readLE32(p)); p+=4; + v3 = XXH32_round(v3, XXH_readLE32(p)); p+=4; + v4 = XXH32_round(v4, XXH_readLE32(p)); p+=4; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + } + + return XXH_OK; +} + + +/*! @ingroup xxh32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_digest(const XXH32_state_t* state) +{ + xxh_u32 h32; + + if (state->large_len) { + h32 = XXH_rotl32(state->v1, 1) + + XXH_rotl32(state->v2, 7) + + XXH_rotl32(state->v3, 12) + + XXH_rotl32(state->v4, 18); + } else { + h32 = state->v3 /* == seed */ + XXH_PRIME32_5; + } + + h32 += state->total_len_32; + + return XXH32_finalize(h32, (const xxh_u8*)state->mem32, state->memsize, XXH_aligned); +} + + +/******* Canonical representation *******/ + +/*! + * @ingroup xxh32_family + * The default return values from XXH functions are unsigned 32 and 64 bit + * integers. + * + * The canonical representation uses big endian convention, the same convention + * as human-readable numbers (large digits first). + * + * This way, hash values can be written into a file or buffer, remaining + * comparable across different systems. + * + * The following functions allow transformation of hash values to and from their + * canonical format. + */ +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + memcpy(dst, &hash, sizeof(*dst)); +} +/*! @ingroup xxh32_family */ +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + + +#ifndef XXH_NO_LONG_LONG + +/* ******************************************************************* +* 64-bit hash functions +*********************************************************************/ +/*! + * @} + * @ingroup impl + * @{ + */ +/******* Memory access *******/ + +typedef XXH64_hash_t xxh_u64; + +#ifdef XXH_OLD_NAMES +# define U64 xxh_u64 +#endif + +/*! + * XXH_REROLL_XXH64: + * Whether to reroll the XXH64_finalize() loop. + * + * Just like XXH32, we can unroll the XXH64_finalize() loop. This can be a + * performance gain on 64-bit hosts, as only one jump is required. + * + * However, on 32-bit hosts, because arithmetic needs to be done with two 32-bit + * registers, and 64-bit arithmetic needs to be simulated, it isn't beneficial + * to unroll. The code becomes ridiculously large (the largest function in the + * binary on i386!), and rerolling it saves anywhere from 3kB to 20kB. It is + * also slightly faster because it fits into cache better and is more likely + * to be inlined by the compiler. + * + * If XXH_REROLL is defined, this is ignored and the loop is always rerolled. + */ +#ifndef XXH_REROLL_XXH64 +# if (defined(__ILP32__) || defined(_ILP32)) /* ILP32 is often defined on 32-bit GCC family */ \ + || !(defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) /* x86-64 */ \ + || defined(_M_ARM64) || defined(__aarch64__) || defined(__arm64__) /* aarch64 */ \ + || defined(__PPC64__) || defined(__PPC64LE__) || defined(__ppc64__) || defined(__powerpc64__) /* ppc64 */ \ + || defined(__mips64__) || defined(__mips64)) /* mips64 */ \ + || (!defined(SIZE_MAX) || SIZE_MAX < ULLONG_MAX) /* check limits */ +# define XXH_REROLL_XXH64 1 +# else +# define XXH_REROLL_XXH64 0 +# endif +#endif /* !defined(XXH_REROLL_XXH64) */ + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) +/* + * Manual byteshift. Best for old compilers which don't inline memcpy. + * We actually directly use XXH_readLE64 and XXH_readBE64. + */ +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + return *(const xxh_u64*) memPtr; +} + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* + * __pack instructions are safer, but compiler specific, hence potentially + * problematic for some compilers. + * + * Currently only defined for GCC and ICC. + */ +#ifdef XXH_OLD_NAMES +typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) unalign64; +#endif +static xxh_u64 XXH_read64(const void* ptr) +{ + typedef union { xxh_u32 u32; xxh_u64 u64; } __attribute__((packed)) xxh_unalign64; + return ((const xxh_unalign64*)ptr)->u64; +} + +#else + +/* + * Portable and safe solution. Generally efficient. + * see: https://stackoverflow.com/a/32095106/646947 + */ +static xxh_u64 XXH_read64(const void* memPtr) +{ + xxh_u64 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap64 _byteswap_uint64 +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap64 __builtin_bswap64 +#else +static xxh_u64 XXH_swap64(xxh_u64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + + +/* XXH_FORCE_MEMORY_ACCESS==3 is an endian-independent byteshift load. */ +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==3)) + +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[0] + | ((xxh_u64)bytePtr[1] << 8) + | ((xxh_u64)bytePtr[2] << 16) + | ((xxh_u64)bytePtr[3] << 24) + | ((xxh_u64)bytePtr[4] << 32) + | ((xxh_u64)bytePtr[5] << 40) + | ((xxh_u64)bytePtr[6] << 48) + | ((xxh_u64)bytePtr[7] << 56); +} + +XXH_FORCE_INLINE xxh_u64 XXH_readBE64(const void* memPtr) +{ + const xxh_u8* bytePtr = (const xxh_u8 *)memPtr; + return bytePtr[7] + | ((xxh_u64)bytePtr[6] << 8) + | ((xxh_u64)bytePtr[5] << 16) + | ((xxh_u64)bytePtr[4] << 24) + | ((xxh_u64)bytePtr[3] << 32) + | ((xxh_u64)bytePtr[2] << 40) + | ((xxh_u64)bytePtr[1] << 48) + | ((xxh_u64)bytePtr[0] << 56); +} + +#else +XXH_FORCE_INLINE xxh_u64 XXH_readLE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); +} + +static xxh_u64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} +#endif + +XXH_FORCE_INLINE xxh_u64 +XXH_readLE64_align(const void* ptr, XXH_alignment align) +{ + if (align==XXH_unaligned) + return XXH_readLE64(ptr); + else + return XXH_CPU_LITTLE_ENDIAN ? *(const xxh_u64*)ptr : XXH_swap64(*(const xxh_u64*)ptr); +} + + +/******* xxh64 *******/ +/*! + * @} + * @defgroup xxh64_impl XXH64 implementation + * @ingroup impl + * @{ + */ +static const xxh_u64 XXH_PRIME64_1 = 0x9E3779B185EBCA87ULL; /*!< 0b1001111000110111011110011011000110000101111010111100101010000111 */ +static const xxh_u64 XXH_PRIME64_2 = 0xC2B2AE3D27D4EB4FULL; /*!< 0b1100001010110010101011100011110100100111110101001110101101001111 */ +static const xxh_u64 XXH_PRIME64_3 = 0x165667B19E3779F9ULL; /*!< 0b0001011001010110011001111011000110011110001101110111100111111001 */ +static const xxh_u64 XXH_PRIME64_4 = 0x85EBCA77C2B2AE63ULL; /*!< 0b1000010111101011110010100111011111000010101100101010111001100011 */ +static const xxh_u64 XXH_PRIME64_5 = 0x27D4EB2F165667C5ULL; /*!< 0b0010011111010100111010110010111100010110010101100110011111000101 */ + +#ifdef XXH_OLD_NAMES +# define PRIME64_1 XXH_PRIME64_1 +# define PRIME64_2 XXH_PRIME64_2 +# define PRIME64_3 XXH_PRIME64_3 +# define PRIME64_4 XXH_PRIME64_4 +# define PRIME64_5 XXH_PRIME64_5 +#endif + +static xxh_u64 XXH64_round(xxh_u64 acc, xxh_u64 input) +{ + acc += input * XXH_PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= XXH_PRIME64_1; + return acc; +} + +static xxh_u64 XXH64_mergeRound(xxh_u64 acc, xxh_u64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * XXH_PRIME64_1 + XXH_PRIME64_4; + return acc; +} + +static xxh_u64 XXH64_avalanche(xxh_u64 h64) +{ + h64 ^= h64 >> 33; + h64 *= XXH_PRIME64_2; + h64 ^= h64 >> 29; + h64 *= XXH_PRIME64_3; + h64 ^= h64 >> 32; + return h64; +} + + +#define XXH_get64bits(p) XXH_readLE64_align(p, align) + +static xxh_u64 +XXH64_finalize(xxh_u64 h64, const xxh_u8* ptr, size_t len, XXH_alignment align) +{ +#define XXH_PROCESS1_64 do { \ + h64 ^= (*ptr++) * XXH_PRIME64_5; \ + h64 = XXH_rotl64(h64, 11) * XXH_PRIME64_1; \ +} while (0) + +#define XXH_PROCESS4_64 do { \ + h64 ^= (xxh_u64)(XXH_get32bits(ptr)) * XXH_PRIME64_1; \ + ptr += 4; \ + h64 = XXH_rotl64(h64, 23) * XXH_PRIME64_2 + XXH_PRIME64_3; \ +} while (0) + +#define XXH_PROCESS8_64 do { \ + xxh_u64 const k1 = XXH64_round(0, XXH_get64bits(ptr)); \ + ptr += 8; \ + h64 ^= k1; \ + h64 = XXH_rotl64(h64,27) * XXH_PRIME64_1 + XXH_PRIME64_4; \ +} while (0) + + /* Rerolled version for 32-bit targets is faster and much smaller. */ + if (XXH_REROLL || XXH_REROLL_XXH64) { + len &= 31; + while (len >= 8) { + XXH_PROCESS8_64; + len -= 8; + } + if (len >= 4) { + XXH_PROCESS4_64; + len -= 4; + } + while (len > 0) { + XXH_PROCESS1_64; + --len; + } + return XXH64_avalanche(h64); + } else { + switch(len & 31) { + case 24: XXH_PROCESS8_64; + /* fallthrough */ + case 16: XXH_PROCESS8_64; + /* fallthrough */ + case 8: XXH_PROCESS8_64; + return XXH64_avalanche(h64); + + case 28: XXH_PROCESS8_64; + /* fallthrough */ + case 20: XXH_PROCESS8_64; + /* fallthrough */ + case 12: XXH_PROCESS8_64; + /* fallthrough */ + case 4: XXH_PROCESS4_64; + return XXH64_avalanche(h64); + + case 25: XXH_PROCESS8_64; + /* fallthrough */ + case 17: XXH_PROCESS8_64; + /* fallthrough */ + case 9: XXH_PROCESS8_64; + XXH_PROCESS1_64; + return XXH64_avalanche(h64); + + case 29: XXH_PROCESS8_64; + /* fallthrough */ + case 21: XXH_PROCESS8_64; + /* fallthrough */ + case 13: XXH_PROCESS8_64; + /* fallthrough */ + case 5: XXH_PROCESS4_64; + XXH_PROCESS1_64; + return XXH64_avalanche(h64); + + case 26: XXH_PROCESS8_64; + /* fallthrough */ + case 18: XXH_PROCESS8_64; + /* fallthrough */ + case 10: XXH_PROCESS8_64; + XXH_PROCESS1_64; + XXH_PROCESS1_64; + return XXH64_avalanche(h64); + + case 30: XXH_PROCESS8_64; + /* fallthrough */ + case 22: XXH_PROCESS8_64; + /* fallthrough */ + case 14: XXH_PROCESS8_64; + /* fallthrough */ + case 6: XXH_PROCESS4_64; + XXH_PROCESS1_64; + XXH_PROCESS1_64; + return XXH64_avalanche(h64); + + case 27: XXH_PROCESS8_64; + /* fallthrough */ + case 19: XXH_PROCESS8_64; + /* fallthrough */ + case 11: XXH_PROCESS8_64; + XXH_PROCESS1_64; + XXH_PROCESS1_64; + XXH_PROCESS1_64; + return XXH64_avalanche(h64); + + case 31: XXH_PROCESS8_64; + /* fallthrough */ + case 23: XXH_PROCESS8_64; + /* fallthrough */ + case 15: XXH_PROCESS8_64; + /* fallthrough */ + case 7: XXH_PROCESS4_64; + /* fallthrough */ + case 3: XXH_PROCESS1_64; + /* fallthrough */ + case 2: XXH_PROCESS1_64; + /* fallthrough */ + case 1: XXH_PROCESS1_64; + /* fallthrough */ + case 0: return XXH64_avalanche(h64); + } + } + /* impossible to reach */ + XXH_ASSERT(0); + return 0; /* unreachable, but some compilers complain without it */ +} + +#ifdef XXH_OLD_NAMES +# define PROCESS1_64 XXH_PROCESS1_64 +# define PROCESS4_64 XXH_PROCESS4_64 +# define PROCESS8_64 XXH_PROCESS8_64 +#else +# undef XXH_PROCESS1_64 +# undef XXH_PROCESS4_64 +# undef XXH_PROCESS8_64 +#endif + +XXH_FORCE_INLINE xxh_u64 +XXH64_endian_align(const xxh_u8* input, size_t len, xxh_u64 seed, XXH_alignment align) +{ + const xxh_u8* bEnd = input + len; + xxh_u64 h64; + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (input==NULL) { + len=0; + bEnd=input=(const xxh_u8*)(size_t)32; + } +#endif + + if (len>=32) { + const xxh_u8* const limit = bEnd - 32; + xxh_u64 v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + xxh_u64 v2 = seed + XXH_PRIME64_2; + xxh_u64 v3 = seed + 0; + xxh_u64 v4 = seed - XXH_PRIME64_1; + + do { + v1 = XXH64_round(v1, XXH_get64bits(input)); input+=8; + v2 = XXH64_round(v2, XXH_get64bits(input)); input+=8; + v3 = XXH64_round(v3, XXH_get64bits(input)); input+=8; + v4 = XXH64_round(v4, XXH_get64bits(input)); input+=8; + } while (input<=limit); + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + + } else { + h64 = seed + XXH_PRIME64_5; + } + + h64 += (xxh_u64) len; + + return XXH64_finalize(h64, input, len, align); +} + + +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t len, XXH64_hash_t seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_state_t state; + XXH64_reset(&state, seed); + XXH64_update(&state, (const xxh_u8*)input, len); + return XXH64_digest(&state); +#else + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_aligned); + } } + + return XXH64_endian_align((const xxh_u8*)input, len, seed, XXH_unaligned); + +#endif +} + +/******* Hash Streaming *******/ + +/*! @ingroup xxh64_family*/ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, XXH64_hash_t seed) +{ + XXH64_state_t state; /* use a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + XXH_PRIME64_1 + XXH_PRIME64_2; + state.v2 = seed + XXH_PRIME64_2; + state.v3 = seed + 0; + state.v4 = seed - XXH_PRIME64_1; + /* do not write into reserved64, might be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved64)); + return XXH_OK; +} + +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API XXH_errorcode +XXH64_update (XXH64_state_t* state, const void* input, size_t len) +{ + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + { const xxh_u8* p = (const xxh_u8*)input; + const xxh_u8* const bEnd = p + len; + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, len); + state->memsize += (xxh_u32)len; + return XXH_OK; + } + + if (state->memsize) { /* tmp buffer is full */ + XXH_memcpy(((xxh_u8*)state->mem64) + state->memsize, input, 32-state->memsize); + state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0)); + state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1)); + state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2)); + state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3)); + p += 32 - state->memsize; + state->memsize = 0; + } + + if (p+32 <= bEnd) { + const xxh_u8* const limit = bEnd - 32; + xxh_u64 v1 = state->v1; + xxh_u64 v2 = state->v2; + xxh_u64 v3 = state->v3; + xxh_u64 v4 = state->v4; + + do { + v1 = XXH64_round(v1, XXH_readLE64(p)); p+=8; + v2 = XXH64_round(v2, XXH_readLE64(p)); p+=8; + v3 = XXH64_round(v3, XXH_readLE64(p)); p+=8; + v4 = XXH64_round(v4, XXH_readLE64(p)); p+=8; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + } + + return XXH_OK; +} + + +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_digest(const XXH64_state_t* state) +{ + xxh_u64 h64; + + if (state->total_len >= 32) { + xxh_u64 const v1 = state->v1; + xxh_u64 const v2 = state->v2; + xxh_u64 const v3 = state->v3; + xxh_u64 const v4 = state->v4; + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + } else { + h64 = state->v3 /*seed*/ + XXH_PRIME64_5; + } + + h64 += (xxh_u64) state->total_len; + + return XXH64_finalize(h64, (const xxh_u8*)state->mem64, (size_t)state->total_len, XXH_aligned); +} + + +/******* Canonical representation *******/ + +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +/*! @ingroup xxh64_family */ +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} + + + +/* ********************************************************************* +* XXH3 +* New generation hash designed for speed on small keys and vectorization +************************************************************************ */ +/*! + * @} + * @defgroup xxh3_impl XXH3 implementation + * @ingroup impl + * @{ + */ + +/* === Compiler specifics === */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* >= C99 */ +# define XXH_RESTRICT restrict +#else +/* Note: it might be useful to define __restrict or __restrict__ for some C++ compilers */ +# define XXH_RESTRICT /* disable */ +#endif + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) \ + || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) \ + || defined(__clang__) +# define XXH_likely(x) __builtin_expect(x, 1) +# define XXH_unlikely(x) __builtin_expect(x, 0) +#else +# define XXH_likely(x) (x) +# define XXH_unlikely(x) (x) +#endif + +#if defined(__GNUC__) +# if defined(__AVX2__) +# include +# elif defined(__SSE2__) +# include +# elif defined(__ARM_NEON__) || defined(__ARM_NEON) +# define inline __inline__ /* circumvent a clang bug */ +# include +# undef inline +# endif +#elif defined(_MSC_VER) +# include +#endif + +/* + * One goal of XXH3 is to make it fast on both 32-bit and 64-bit, while + * remaining a true 64-bit/128-bit hash function. + * + * This is done by prioritizing a subset of 64-bit operations that can be + * emulated without too many steps on the average 32-bit machine. + * + * For example, these two lines seem similar, and run equally fast on 64-bit: + * + * xxh_u64 x; + * x ^= (x >> 47); // good + * x ^= (x >> 13); // bad + * + * However, to a 32-bit machine, there is a major difference. + * + * x ^= (x >> 47) looks like this: + * + * x.lo ^= (x.hi >> (47 - 32)); + * + * while x ^= (x >> 13) looks like this: + * + * // note: funnel shifts are not usually cheap. + * x.lo ^= (x.lo >> 13) | (x.hi << (32 - 13)); + * x.hi ^= (x.hi >> 13); + * + * The first one is significantly faster than the second, simply because the + * shift is larger than 32. This means: + * - All the bits we need are in the upper 32 bits, so we can ignore the lower + * 32 bits in the shift. + * - The shift result will always fit in the lower 32 bits, and therefore, + * we can ignore the upper 32 bits in the xor. + * + * Thanks to this optimization, XXH3 only requires these features to be efficient: + * + * - Usable unaligned access + * - A 32-bit or 64-bit ALU + * - If 32-bit, a decent ADC instruction + * - A 32 or 64-bit multiply with a 64-bit result + * - For the 128-bit variant, a decent byteswap helps short inputs. + * + * The first two are already required by XXH32, and almost all 32-bit and 64-bit + * platforms which can run XXH32 can run XXH3 efficiently. + * + * Thumb-1, the classic 16-bit only subset of ARM's instruction set, is one + * notable exception. + * + * First of all, Thumb-1 lacks support for the UMULL instruction which + * performs the important long multiply. This means numerous __aeabi_lmul + * calls. + * + * Second of all, the 8 functional registers are just not enough. + * Setup for __aeabi_lmul, byteshift loads, pointers, and all arithmetic need + * Lo registers, and this shuffling results in thousands more MOVs than A32. + * + * A32 and T32 don't have this limitation. They can access all 14 registers, + * do a 32->64 multiply with UMULL, and the flexible operand allowing free + * shifts is helpful, too. + * + * Therefore, we do a quick sanity check. + * + * If compiling Thumb-1 for a target which supports ARM instructions, we will + * emit a warning, as it is not a "sane" platform to compile for. + * + * Usually, if this happens, it is because of an accident and you probably need + * to specify -march, as you likely meant to compile for a newer architecture. + * + * Credit: large sections of the vectorial and asm source code paths + * have been contributed by @easyaspi314 + */ +#if defined(__thumb__) && !defined(__thumb2__) && defined(__ARM_ARCH_ISA_ARM) +# warning "XXH3 is highly inefficient without ARM or Thumb-2." +#endif + +/* ========================================== + * Vectorization detection + * ========================================== */ + +#ifdef XXH_DOXYGEN +/*! + * @ingroup tuning + * @brief Overrides the vectorization implementation chosen for XXH3. + * + * Can be defined to 0 to disable SIMD or any of the values mentioned in + * @ref XXH_VECTOR_TYPE. + * + * If this is not defined, it uses predefined macros to determine the best + * implementation. + */ +# define XXH_VECTOR XXH_SCALAR +/*! + * @ingroup tuning + * @brief Possible values for @ref XXH_VECTOR. + * + * Note that these are actually implemented as macros. + * + * If this is not defined, it is detected automatically. + * @ref XXH_X86DISPATCH overrides this. + */ +enum XXH_VECTOR_TYPE /* fake enum */ { + XXH_SCALAR = 0, /*!< Portable scalar version */ + XXH_SSE2 = 1, /*!< + * SSE2 for Pentium 4, Opteron, all x86_64. + * + * @note SSE2 is also guaranteed on Windows 10, macOS, and + * Android x86. + */ + XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */ + XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */ + XXH_NEON = 4, /*!< NEON for most ARMv7-A and all AArch64 */ + XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */ +}; +/*! + * @ingroup tuning + * @brief Selects the minimum alignment for XXH3's accumulators. + * + * When using SIMD, this should match the alignment reqired for said vector + * type, so, for example, 32 for AVX2. + * + * Default: Auto detected. + */ +# define XXH_ACC_ALIGN 8 +#endif + +/* Actual definition */ +#ifndef XXH_DOXYGEN +# define XXH_SCALAR 0 +# define XXH_SSE2 1 +# define XXH_AVX2 2 +# define XXH_AVX512 3 +# define XXH_NEON 4 +# define XXH_VSX 5 +#endif + +#ifndef XXH_VECTOR /* can be defined on command line */ +# if defined(__AVX512F__) +# define XXH_VECTOR XXH_AVX512 +# elif defined(__AVX2__) +# define XXH_VECTOR XXH_AVX2 +# elif defined(__SSE2__) || defined(_M_AMD64) || defined(_M_X64) || (defined(_M_IX86_FP) && (_M_IX86_FP == 2)) +# define XXH_VECTOR XXH_SSE2 +# elif defined(__GNUC__) /* msvc support maybe later */ \ + && (defined(__ARM_NEON__) || defined(__ARM_NEON)) \ + && (defined(__LITTLE_ENDIAN__) /* We only support little endian NEON */ \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +# define XXH_VECTOR XXH_NEON +# elif (defined(__PPC64__) && defined(__POWER8_VECTOR__)) \ + || (defined(__s390x__) && defined(__VEC__)) \ + && defined(__GNUC__) /* TODO: IBM XL */ +# define XXH_VECTOR XXH_VSX +# else +# define XXH_VECTOR XXH_SCALAR +# endif +#endif + +/* + * Controls the alignment of the accumulator, + * for compatibility with aligned vector loads, which are usually faster. + */ +#ifndef XXH_ACC_ALIGN +# if defined(XXH_X86DISPATCH) +# define XXH_ACC_ALIGN 64 /* for compatibility with avx512 */ +# elif XXH_VECTOR == XXH_SCALAR /* scalar */ +# define XXH_ACC_ALIGN 8 +# elif XXH_VECTOR == XXH_SSE2 /* sse2 */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX2 /* avx2 */ +# define XXH_ACC_ALIGN 32 +# elif XXH_VECTOR == XXH_NEON /* neon */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_VSX /* vsx */ +# define XXH_ACC_ALIGN 16 +# elif XXH_VECTOR == XXH_AVX512 /* avx512 */ +# define XXH_ACC_ALIGN 64 +# endif +#endif + +#if defined(XXH_X86DISPATCH) || XXH_VECTOR == XXH_SSE2 \ + || XXH_VECTOR == XXH_AVX2 || XXH_VECTOR == XXH_AVX512 +# define XXH_SEC_ALIGN XXH_ACC_ALIGN +#else +# define XXH_SEC_ALIGN 8 +#endif + +/* + * UGLY HACK: + * GCC usually generates the best code with -O3 for xxHash. + * + * However, when targeting AVX2, it is overzealous in its unrolling resulting + * in code roughly 3/4 the speed of Clang. + * + * There are other issues, such as GCC splitting _mm256_loadu_si256 into + * _mm_loadu_si128 + _mm256_inserti128_si256. This is an optimization which + * only applies to Sandy and Ivy Bridge... which don't even support AVX2. + * + * That is why when compiling the AVX2 version, it is recommended to use either + * -O2 -mavx2 -march=haswell + * or + * -O2 -mavx2 -mno-avx256-split-unaligned-load + * for decent performance, or to use Clang instead. + * + * Fortunately, we can control the first one with a pragma that forces GCC into + * -O2, but the other one we can't control without "failed to inline always + * inline function due to target mismatch" warnings. + */ +#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ + && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__) /* respect -O0 and -Os */ +# pragma GCC push_options +# pragma GCC optimize("-O2") +#endif + + +#if XXH_VECTOR == XXH_NEON +/* + * NEON's setup for vmlal_u32 is a little more complicated than it is on + * SSE2, AVX2, and VSX. + * + * While PMULUDQ and VMULEUW both perform a mask, VMLAL.U32 performs an upcast. + * + * To do the same operation, the 128-bit 'Q' register needs to be split into + * two 64-bit 'D' registers, performing this operation:: + * + * [ a | b ] + * | '---------. .--------' | + * | x | + * | .---------' '--------. | + * [ a & 0xFFFFFFFF | b & 0xFFFFFFFF ],[ a >> 32 | b >> 32 ] + * + * Due to significant changes in aarch64, the fastest method for aarch64 is + * completely different than the fastest method for ARMv7-A. + * + * ARMv7-A treats D registers as unions overlaying Q registers, so modifying + * D11 will modify the high half of Q5. This is similar to how modifying AH + * will only affect bits 8-15 of AX on x86. + * + * VZIP takes two registers, and puts even lanes in one register and odd lanes + * in the other. + * + * On ARMv7-A, this strangely modifies both parameters in place instead of + * taking the usual 3-operand form. + * + * Therefore, if we want to do this, we can simply use a D-form VZIP.32 on the + * lower and upper halves of the Q register to end up with the high and low + * halves where we want - all in one instruction. + * + * vzip.32 d10, d11 @ d10 = { d10[0], d11[0] }; d11 = { d10[1], d11[1] } + * + * Unfortunately we need inline assembly for this: Instructions modifying two + * registers at once is not possible in GCC or Clang's IR, and they have to + * create a copy. + * + * aarch64 requires a different approach. + * + * In order to make it easier to write a decent compiler for aarch64, many + * quirks were removed, such as conditional execution. + * + * NEON was also affected by this. + * + * aarch64 cannot access the high bits of a Q-form register, and writes to a + * D-form register zero the high bits, similar to how writes to W-form scalar + * registers (or DWORD registers on x86_64) work. + * + * The formerly free vget_high intrinsics now require a vext (with a few + * exceptions) + * + * Additionally, VZIP was replaced by ZIP1 and ZIP2, which are the equivalent + * of PUNPCKL* and PUNPCKH* in SSE, respectively, in order to only modify one + * operand. + * + * The equivalent of the VZIP.32 on the lower and upper halves would be this + * mess: + * + * ext v2.4s, v0.4s, v0.4s, #2 // v2 = { v0[2], v0[3], v0[0], v0[1] } + * zip1 v1.2s, v0.2s, v2.2s // v1 = { v0[0], v2[0] } + * zip2 v0.2s, v0.2s, v1.2s // v0 = { v0[1], v2[1] } + * + * Instead, we use a literal downcast, vmovn_u64 (XTN), and vshrn_n_u64 (SHRN): + * + * shrn v1.2s, v0.2d, #32 // v1 = (uint32x2_t)(v0 >> 32); + * xtn v0.2s, v0.2d // v0 = (uint32x2_t)(v0 & 0xFFFFFFFF); + * + * This is available on ARMv7-A, but is less efficient than a single VZIP.32. + */ + +/*! + * Function-like macro: + * void XXH_SPLIT_IN_PLACE(uint64x2_t &in, uint32x2_t &outLo, uint32x2_t &outHi) + * { + * outLo = (uint32x2_t)(in & 0xFFFFFFFF); + * outHi = (uint32x2_t)(in >> 32); + * in = UNDEFINED; + * } + */ +# if !defined(XXH_NO_VZIP_HACK) /* define to disable */ \ + && defined(__GNUC__) \ + && !defined(__aarch64__) && !defined(__arm64__) +# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \ + do { \ + /* Undocumented GCC/Clang operand modifier: %e0 = lower D half, %f0 = upper D half */ \ + /* https://github.com/gcc-mirror/gcc/blob/38cf91e5/gcc/config/arm/arm.c#L22486 */ \ + /* https://github.com/llvm-mirror/llvm/blob/2c4ca683/lib/Target/ARM/ARMAsmPrinter.cpp#L399 */ \ + __asm__("vzip.32 %e0, %f0" : "+w" (in)); \ + (outLo) = vget_low_u32 (vreinterpretq_u32_u64(in)); \ + (outHi) = vget_high_u32(vreinterpretq_u32_u64(in)); \ + } while (0) +# else +# define XXH_SPLIT_IN_PLACE(in, outLo, outHi) \ + do { \ + (outLo) = vmovn_u64 (in); \ + (outHi) = vshrn_n_u64 ((in), 32); \ + } while (0) +# endif +#endif /* XXH_VECTOR == XXH_NEON */ + +/* + * VSX and Z Vector helpers. + * + * This is very messy, and any pull requests to clean this up are welcome. + * + * There are a lot of problems with supporting VSX and s390x, due to + * inconsistent intrinsics, spotty coverage, and multiple endiannesses. + */ +#if XXH_VECTOR == XXH_VSX +# if defined(__s390x__) +# include +# else +/* gcc's altivec.h can have the unwanted consequence to unconditionally + * #define bool, vector, and pixel keywords, + * with bad consequences for programs already using these keywords for other purposes. + * The paragraph defining these macros is skipped when __APPLE_ALTIVEC__ is defined. + * __APPLE_ALTIVEC__ is _generally_ defined automatically by the compiler, + * but it seems that, in some cases, it isn't. + * Force the build macro to be defined, so that keywords are not altered. + */ +# if defined(__GNUC__) && !defined(__APPLE_ALTIVEC__) +# define __APPLE_ALTIVEC__ +# endif +# include +# endif + +typedef __vector unsigned long long xxh_u64x2; +typedef __vector unsigned char xxh_u8x16; +typedef __vector unsigned xxh_u32x4; + +# ifndef XXH_VSX_BE +# if defined(__BIG_ENDIAN__) \ + || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +# define XXH_VSX_BE 1 +# elif defined(__VEC_ELEMENT_REG_ORDER__) && __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__ +# warning "-maltivec=be is not recommended. Please use native endianness." +# define XXH_VSX_BE 1 +# else +# define XXH_VSX_BE 0 +# endif +# endif /* !defined(XXH_VSX_BE) */ + +# if XXH_VSX_BE +# if defined(__POWER9_VECTOR__) || (defined(__clang__) && defined(__s390x__)) +# define XXH_vec_revb vec_revb +# else +/*! + * A polyfill for POWER9's vec_revb(). + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_revb(xxh_u64x2 val) +{ + xxh_u8x16 const vByteSwap = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + return vec_perm(val, val, vByteSwap); +} +# endif +# endif /* XXH_VSX_BE */ + +/*! + * Performs an unaligned vector load and byte swaps it on big endian. + */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_loadu(const void *ptr) +{ + xxh_u64x2 ret; + memcpy(&ret, ptr, sizeof(xxh_u64x2)); +# if XXH_VSX_BE + ret = XXH_vec_revb(ret); +# endif + return ret; +} + +/* + * vec_mulo and vec_mule are very problematic intrinsics on PowerPC + * + * These intrinsics weren't added until GCC 8, despite existing for a while, + * and they are endian dependent. Also, their meaning swap depending on version. + * */ +# if defined(__s390x__) + /* s390x is always big endian, no issue on this platform */ +# define XXH_vec_mulo vec_mulo +# define XXH_vec_mule vec_mule +# elif defined(__clang__) && XXH_HAS_BUILTIN(__builtin_altivec_vmuleuw) +/* Clang has a better way to control this, we can just use the builtin which doesn't swap. */ +# define XXH_vec_mulo __builtin_altivec_vmulouw +# define XXH_vec_mule __builtin_altivec_vmuleuw +# else +/* gcc needs inline assembly */ +/* Adapted from https://github.com/google/highwayhash/blob/master/highwayhash/hh_vsx.h. */ +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mulo(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmulouw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) +{ + xxh_u64x2 result; + __asm__("vmuleuw %0, %1, %2" : "=v" (result) : "v" (a), "v" (b)); + return result; +} +# endif /* XXH_vec_mulo, XXH_vec_mule */ +#endif /* XXH_VECTOR == XXH_VSX */ + + +/* prefetch + * can be disabled, by declaring XXH_NO_PREFETCH build macro */ +#if defined(XXH_NO_PREFETCH) +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +#else +# if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86)) /* _mm_prefetch() not defined outside of x86/x64 */ +# include /* https://msdn.microsoft.com/fr-fr/library/84szxsww(v=vs.90).aspx */ +# define XXH_PREFETCH(ptr) _mm_prefetch((const char*)(ptr), _MM_HINT_T0) +# elif defined(__GNUC__) && ( (__GNUC__ >= 4) || ( (__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) ) ) +# define XXH_PREFETCH(ptr) __builtin_prefetch((ptr), 0 /* rw==read */, 3 /* locality */) +# else +# define XXH_PREFETCH(ptr) (void)(ptr) /* disabled */ +# endif +#endif /* XXH_NO_PREFETCH */ + + +/* ========================================== + * XXH3 default settings + * ========================================== */ + +#define XXH_SECRET_DEFAULT_SIZE 192 /* minimum XXH3_SECRET_SIZE_MIN */ + +#if (XXH_SECRET_DEFAULT_SIZE < XXH3_SECRET_SIZE_MIN) +# error "default keyset is not large enough" +#endif + +/*! Pseudorandom secret taken directly from FARSH. */ +XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = { + 0xb8, 0xfe, 0x6c, 0x39, 0x23, 0xa4, 0x4b, 0xbe, 0x7c, 0x01, 0x81, 0x2c, 0xf7, 0x21, 0xad, 0x1c, + 0xde, 0xd4, 0x6d, 0xe9, 0x83, 0x90, 0x97, 0xdb, 0x72, 0x40, 0xa4, 0xa4, 0xb7, 0xb3, 0x67, 0x1f, + 0xcb, 0x79, 0xe6, 0x4e, 0xcc, 0xc0, 0xe5, 0x78, 0x82, 0x5a, 0xd0, 0x7d, 0xcc, 0xff, 0x72, 0x21, + 0xb8, 0x08, 0x46, 0x74, 0xf7, 0x43, 0x24, 0x8e, 0xe0, 0x35, 0x90, 0xe6, 0x81, 0x3a, 0x26, 0x4c, + 0x3c, 0x28, 0x52, 0xbb, 0x91, 0xc3, 0x00, 0xcb, 0x88, 0xd0, 0x65, 0x8b, 0x1b, 0x53, 0x2e, 0xa3, + 0x71, 0x64, 0x48, 0x97, 0xa2, 0x0d, 0xf9, 0x4e, 0x38, 0x19, 0xef, 0x46, 0xa9, 0xde, 0xac, 0xd8, + 0xa8, 0xfa, 0x76, 0x3f, 0xe3, 0x9c, 0x34, 0x3f, 0xf9, 0xdc, 0xbb, 0xc7, 0xc7, 0x0b, 0x4f, 0x1d, + 0x8a, 0x51, 0xe0, 0x4b, 0xcd, 0xb4, 0x59, 0x31, 0xc8, 0x9f, 0x7e, 0xc9, 0xd9, 0x78, 0x73, 0x64, + 0xea, 0xc5, 0xac, 0x83, 0x34, 0xd3, 0xeb, 0xc3, 0xc5, 0x81, 0xa0, 0xff, 0xfa, 0x13, 0x63, 0xeb, + 0x17, 0x0d, 0xdd, 0x51, 0xb7, 0xf0, 0xda, 0x49, 0xd3, 0x16, 0x55, 0x26, 0x29, 0xd4, 0x68, 0x9e, + 0x2b, 0x16, 0xbe, 0x58, 0x7d, 0x47, 0xa1, 0xfc, 0x8f, 0xf8, 0xb8, 0xd1, 0x7a, 0xd0, 0x31, 0xce, + 0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e, +}; + + +#ifdef XXH_OLD_NAMES +# define kSecret XXH3_kSecret +#endif + +#ifdef XXH_DOXYGEN +/*! + * @brief Calculates a 32-bit to 64-bit long multiply. + * + * Implemented as a macro. + * + * Wraps `__emulu` on MSVC x86 because it tends to call `__allmul` when it doesn't + * need to (but it shouldn't need to anyways, it is about 7 instructions to do + * a 64x64 multiply...). Since we know that this will _always_ emit `MULL`, we + * use that instead of the normal method. + * + * If you are compiling for platforms like Thumb-1 and don't have a better option, + * you may also want to write your own long multiply routine here. + * + * @param x, y Numbers to be multiplied + * @return 64-bit product of the low 32 bits of @p x and @p y. + */ +XXH_FORCE_INLINE xxh_u64 +XXH_mult32to64(xxh_u64 x, xxh_u64 y) +{ + return (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF); +} +#elif defined(_MSC_VER) && defined(_M_IX86) +# include +# define XXH_mult32to64(x, y) __emulu((unsigned)(x), (unsigned)(y)) +#else +/* + * Downcast + upcast is usually better than masking on older compilers like + * GCC 4.2 (especially 32-bit ones), all without affecting newer compilers. + * + * The other method, (x & 0xFFFFFFFF) * (y & 0xFFFFFFFF), will AND both operands + * and perform a full 64x64 multiply -- entirely redundant on 32-bit. + */ +# define XXH_mult32to64(x, y) ((xxh_u64)(xxh_u32)(x) * (xxh_u64)(xxh_u32)(y)) +#endif + +/*! + * @brief Calculates a 64->128-bit long multiply. + * + * Uses `__uint128_t` and `_umul128` if available, otherwise uses a scalar + * version. + * + * @param lhs, rhs The 64-bit integers to be multiplied + * @return The 128-bit result represented in an @ref XXH128_hash_t. + */ +static XXH128_hash_t +XXH_mult64to128(xxh_u64 lhs, xxh_u64 rhs) +{ + /* + * GCC/Clang __uint128_t method. + * + * On most 64-bit targets, GCC and Clang define a __uint128_t type. + * This is usually the best way as it usually uses a native long 64-bit + * multiply, such as MULQ on x86_64 or MUL + UMULH on aarch64. + * + * Usually. + * + * Despite being a 32-bit platform, Clang (and emscripten) define this type + * despite not having the arithmetic for it. This results in a laggy + * compiler builtin call which calculates a full 128-bit multiply. + * In that case it is best to use the portable one. + * https://github.com/Cyan4973/xxHash/issues/211#issuecomment-515575677 + */ +#if defined(__GNUC__) && !defined(__wasm__) \ + && defined(__SIZEOF_INT128__) \ + || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) + + __uint128_t const product = (__uint128_t)lhs * (__uint128_t)rhs; + XXH128_hash_t r128; + r128.low64 = (xxh_u64)(product); + r128.high64 = (xxh_u64)(product >> 64); + return r128; + + /* + * MSVC for x64's _umul128 method. + * + * xxh_u64 _umul128(xxh_u64 Multiplier, xxh_u64 Multiplicand, xxh_u64 *HighProduct); + * + * This compiles to single operand MUL on x64. + */ +#elif defined(_M_X64) || defined(_M_IA64) + +#ifndef _MSC_VER +# pragma intrinsic(_umul128) +#endif + xxh_u64 product_high; + xxh_u64 const product_low = _umul128(lhs, rhs, &product_high); + XXH128_hash_t r128; + r128.low64 = product_low; + r128.high64 = product_high; + return r128; + +#else + /* + * Portable scalar method. Optimized for 32-bit and 64-bit ALUs. + * + * This is a fast and simple grade school multiply, which is shown below + * with base 10 arithmetic instead of base 0x100000000. + * + * 9 3 // D2 lhs = 93 + * x 7 5 // D2 rhs = 75 + * ---------- + * 1 5 // D2 lo_lo = (93 % 10) * (75 % 10) = 15 + * 4 5 | // D2 hi_lo = (93 / 10) * (75 % 10) = 45 + * 2 1 | // D2 lo_hi = (93 % 10) * (75 / 10) = 21 + * + 6 3 | | // D2 hi_hi = (93 / 10) * (75 / 10) = 63 + * --------- + * 2 7 | // D2 cross = (15 / 10) + (45 % 10) + 21 = 27 + * + 6 7 | | // D2 upper = (27 / 10) + (45 / 10) + 63 = 67 + * --------- + * 6 9 7 5 // D4 res = (27 * 10) + (15 % 10) + (67 * 100) = 6975 + * + * The reasons for adding the products like this are: + * 1. It avoids manual carry tracking. Just like how + * (9 * 9) + 9 + 9 = 99, the same applies with this for UINT64_MAX. + * This avoids a lot of complexity. + * + * 2. It hints for, and on Clang, compiles to, the powerful UMAAL + * instruction available in ARM's Digital Signal Processing extension + * in 32-bit ARMv6 and later, which is shown below: + * + * void UMAAL(xxh_u32 *RdLo, xxh_u32 *RdHi, xxh_u32 Rn, xxh_u32 Rm) + * { + * xxh_u64 product = (xxh_u64)*RdLo * (xxh_u64)*RdHi + Rn + Rm; + * *RdLo = (xxh_u32)(product & 0xFFFFFFFF); + * *RdHi = (xxh_u32)(product >> 32); + * } + * + * This instruction was designed for efficient long multiplication, and + * allows this to be calculated in only 4 instructions at speeds + * comparable to some 64-bit ALUs. + * + * 3. It isn't terrible on other platforms. Usually this will be a couple + * of 32-bit ADD/ADCs. + */ + + /* First calculate all of the cross products. */ + xxh_u64 const lo_lo = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs & 0xFFFFFFFF); + xxh_u64 const hi_lo = XXH_mult32to64(lhs >> 32, rhs & 0xFFFFFFFF); + xxh_u64 const lo_hi = XXH_mult32to64(lhs & 0xFFFFFFFF, rhs >> 32); + xxh_u64 const hi_hi = XXH_mult32to64(lhs >> 32, rhs >> 32); + + /* Now add the products together. These will never overflow. */ + xxh_u64 const cross = (lo_lo >> 32) + (hi_lo & 0xFFFFFFFF) + lo_hi; + xxh_u64 const upper = (hi_lo >> 32) + (cross >> 32) + hi_hi; + xxh_u64 const lower = (cross << 32) | (lo_lo & 0xFFFFFFFF); + + XXH128_hash_t r128; + r128.low64 = lower; + r128.high64 = upper; + return r128; +#endif +} + +/*! + * @brief Calculates a 64-bit to 128-bit multiply, then XOR folds it. + * + * The reason for the separate function is to prevent passing too many structs + * around by value. This will hopefully inline the multiply, but we don't force it. + * + * @param lhs, rhs The 64-bit integers to multiply + * @return The low 64 bits of the product XOR'd by the high 64 bits. + * @see XXH_mult64to128() + */ +static xxh_u64 +XXH3_mul128_fold64(xxh_u64 lhs, xxh_u64 rhs) +{ + XXH128_hash_t product = XXH_mult64to128(lhs, rhs); + return product.low64 ^ product.high64; +} + +/*! Seems to produce slightly better code on GCC for some reason. */ +XXH_FORCE_INLINE xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift) +{ + XXH_ASSERT(0 <= shift && shift < 64); + return v64 ^ (v64 >> shift); +} + +/* + * This is a fast avalanche stage, + * suitable when input bits are already partially mixed + */ +static XXH64_hash_t XXH3_avalanche(xxh_u64 h64) +{ + h64 = XXH_xorshift64(h64, 37); + h64 *= 0x165667919E3779F9ULL; + h64 = XXH_xorshift64(h64, 32); + return h64; +} + +/* + * This is a stronger avalanche, + * inspired by Pelle Evensen's rrmxmx + * preferable when input has not been previously mixed + */ +static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len) +{ + /* this mix is inspired by Pelle Evensen's rrmxmx */ + h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24); + h64 *= 0x9FB21C651E98DF25ULL; + h64 ^= (h64 >> 35) + len ; + h64 *= 0x9FB21C651E98DF25ULL; + return XXH_xorshift64(h64, 28); +} + + +/* ========================================== + * Short keys + * ========================================== + * One of the shortcomings of XXH32 and XXH64 was that their performance was + * sub-optimal on short lengths. It used an iterative algorithm which strongly + * favored lengths that were a multiple of 4 or 8. + * + * Instead of iterating over individual inputs, we use a set of single shot + * functions which piece together a range of lengths and operate in constant time. + * + * Additionally, the number of multiplies has been significantly reduced. This + * reduces latency, especially when emulating 64-bit multiplies on 32-bit. + * + * Depending on the platform, this may or may not be faster than XXH32, but it + * is almost guaranteed to be faster than XXH64. + */ + +/* + * At very short lengths, there isn't enough input to fully hide secrets, or use + * the entire secret. + * + * There is also only a limited amount of mixing we can do before significantly + * impacting performance. + * + * Therefore, we use different sections of the secret and always mix two secret + * samples with an XOR. This should have no effect on performance on the + * seedless or withSeed variants because everything _should_ be constant folded + * by modern compilers. + * + * The XOR mixing hides individual parts of the secret and increases entropy. + * + * This adds an extra layer of strength for custom secrets. + */ +XXH_FORCE_INLINE XXH64_hash_t +XXH3_len_1to3_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combined = { input[0], 0x01, input[0], input[0] } + * len = 2: combined = { input[1], 0x02, input[0], input[1] } + * len = 3: combined = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combined = ((xxh_u32)c1 << 16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u64 const bitflip = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const keyed = (xxh_u64)combined ^ bitflip; + return XXH64_avalanche(keyed); + } +} + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_len_4to8_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len < 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input1 = XXH_readLE32(input); + xxh_u32 const input2 = XXH_readLE32(input + len - 4); + xxh_u64 const bitflip = (XXH_readLE64(secret+8) ^ XXH_readLE64(secret+16)) - seed; + xxh_u64 const input64 = input2 + (((xxh_u64)input1) << 32); + xxh_u64 const keyed = input64 ^ bitflip; + return XXH3_rrmxmx(keyed, len); + } +} + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_len_9to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(8 <= len && len <= 16); + { xxh_u64 const bitflip1 = (XXH_readLE64(secret+24) ^ XXH_readLE64(secret+32)) + seed; + xxh_u64 const bitflip2 = (XXH_readLE64(secret+40) ^ XXH_readLE64(secret+48)) - seed; + xxh_u64 const input_lo = XXH_readLE64(input) ^ bitflip1; + xxh_u64 const input_hi = XXH_readLE64(input + len - 8) ^ bitflip2; + xxh_u64 const acc = len + + XXH_swap64(input_lo) + input_hi + + XXH3_mul128_fold64(input_lo, input_hi); + return XXH3_avalanche(acc); + } +} + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_len_0to16_64b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (XXH_likely(len > 8)) return XXH3_len_9to16_64b(input, len, secret, seed); + if (XXH_likely(len >= 4)) return XXH3_len_4to8_64b(input, len, secret, seed); + if (len) return XXH3_len_1to3_64b(input, len, secret, seed); + return XXH64_avalanche(seed ^ (XXH_readLE64(secret+56) ^ XXH_readLE64(secret+64))); + } +} + +/* + * DISCLAIMER: There are known *seed-dependent* multicollisions here due to + * multiplication by zero, affecting hashes of lengths 17 to 240. + * + * However, they are very unlikely. + * + * Keep this in mind when using the unseeded XXH3_64bits() variant: As with all + * unseeded non-cryptographic hashes, it does not attempt to defend itself + * against specially crafted inputs, only random inputs. + * + * Compared to classic UMAC where a 1 in 2^31 chance of 4 consecutive bytes + * cancelling out the secret is taken an arbitrary number of times (addressed + * in XXH3_accumulate_512), this collision is very unlikely with random inputs + * and/or proper seeding: + * + * This only has a 1 in 2^63 chance of 8 consecutive bytes cancelling out, in a + * function that is only called up to 16 times per hash with up to 240 bytes of + * input. + * + * This is not too bad for a non-cryptographic hash function, especially with + * only 64 bit outputs. + * + * The 128-bit variant (which trades some speed for strength) is NOT affected + * by this, although it is always a good idea to use a proper seed if you care + * about strength. + */ +XXH_FORCE_INLINE xxh_u64 XXH3_mix16B(const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, xxh_u64 seed64) +{ +#if defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__i386__) && defined(__SSE2__) /* x86 + SSE2 */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable like XXH32 hack */ + /* + * UGLY HACK: + * GCC for x86 tends to autovectorize the 128-bit multiply, resulting in + * slower code. + * + * By forcing seed64 into a register, we disrupt the cost model and + * cause it to scalarize. See `XXH32_round()` + * + * FIXME: Clang's output is still _much_ faster -- On an AMD Ryzen 3600, + * XXH3_64bits @ len=240 runs at 4.6 GB/s with Clang 9, but 3.3 GB/s on + * GCC 9.2, despite both emitting scalar code. + * + * GCC generates much better scalar code than Clang for the rest of XXH3, + * which is why finding a more optimal codepath is an interest. + */ + __asm__ ("" : "+r" (seed64)); +#endif + { xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 const input_hi = XXH_readLE64(input+8); + return XXH3_mul128_fold64( + input_lo ^ (XXH_readLE64(secret) + seed64), + input_hi ^ (XXH_readLE64(secret+8) - seed64) + ); + } +} + +/* For mid range keys, XXH3 uses a Mum-hash variant. */ +XXH_FORCE_INLINE XXH64_hash_t +XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { xxh_u64 acc = len * XXH_PRIME64_1; + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc += XXH3_mix16B(input+48, secret+96, seed); + acc += XXH3_mix16B(input+len-64, secret+112, seed); + } + acc += XXH3_mix16B(input+32, secret+64, seed); + acc += XXH3_mix16B(input+len-48, secret+80, seed); + } + acc += XXH3_mix16B(input+16, secret+32, seed); + acc += XXH3_mix16B(input+len-32, secret+48, seed); + } + acc += XXH3_mix16B(input+0, secret+0, seed); + acc += XXH3_mix16B(input+len-16, secret+16, seed); + + return XXH3_avalanche(acc); + } +} + +#define XXH3_MIDSIZE_MAX 240 + +XXH_NO_INLINE XXH64_hash_t +XXH3_len_129to240_64b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + #define XXH3_MIDSIZE_STARTOFFSET 3 + #define XXH3_MIDSIZE_LASTOFFSET 17 + + { xxh_u64 acc = len * XXH_PRIME64_1; + int const nbRounds = (int)len / 16; + int i; + for (i=0; i<8; i++) { + acc += XXH3_mix16B(input+(16*i), secret+(16*i), seed); + } + acc = XXH3_avalanche(acc); + XXH_ASSERT(nbRounds >= 8); +#if defined(__clang__) /* Clang */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Clang for ARMv7-A tries to vectorize this loop, similar to GCC x86. + * In everywhere else, it uses scalar code. + * + * For 64->128-bit multiplies, even if the NEON was 100% optimal, it + * would still be slower than UMAAL (see XXH_mult64to128). + * + * Unfortunately, Clang doesn't handle the long multiplies properly and + * converts them to the nonexistent "vmulq_u64" intrinsic, which is then + * scalarized into an ugly mess of VMOV.32 instructions. + * + * This mess is difficult to avoid without turning autovectorization + * off completely, but they are usually relatively minor and/or not + * worth it to fix. + * + * This loop is the easiest to fix, as unlike XXH32, this pragma + * _actually works_ because it is a loop vectorization instead of an + * SLP vectorization. + */ + #pragma clang loop vectorize(disable) +#endif + for (i=8 ; i < nbRounds; i++) { + acc += XXH3_mix16B(input+(16*i), secret+(16*(i-8)) + XXH3_MIDSIZE_STARTOFFSET, seed); + } + /* last bytes */ + acc += XXH3_mix16B(input + len - 16, secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET, seed); + return XXH3_avalanche(acc); + } +} + + +/* ======= Long Keys ======= */ + +#define XXH_STRIPE_LEN 64 +#define XXH_SECRET_CONSUME_RATE 8 /* nb of secret bytes consumed at each accumulation */ +#define XXH_ACC_NB (XXH_STRIPE_LEN / sizeof(xxh_u64)) + +#ifdef XXH_OLD_NAMES +# define STRIPE_LEN XXH_STRIPE_LEN +# define ACC_NB XXH_ACC_NB +#endif + +XXH_FORCE_INLINE void XXH_writeLE64(void* dst, xxh_u64 v64) +{ + if (!XXH_CPU_LITTLE_ENDIAN) v64 = XXH_swap64(v64); + memcpy(dst, &v64, sizeof(v64)); +} + +/* Several intrinsic functions below are supposed to accept __int64 as argument, + * as documented in https://software.intel.com/sites/landingpage/IntrinsicsGuide/ . + * However, several environments do not define __int64 type, + * requiring a workaround. + */ +#if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) + typedef int64_t xxh_i64; +#else + /* the following type must have a width of 64-bit */ + typedef long long xxh_i64; +#endif + +/* + * XXH3_accumulate_512 is the tightest loop for long inputs, and it is the most optimized. + * + * It is a hardened version of UMAC, based off of FARSH's implementation. + * + * This was chosen because it adapts quite well to 32-bit, 64-bit, and SIMD + * implementations, and it is ridiculously fast. + * + * We harden it by mixing the original input to the accumulators as well as the product. + * + * This means that in the (relatively likely) case of a multiply by zero, the + * original input is preserved. + * + * On 128-bit inputs, we swap 64-bit pairs when we add the input to improve + * cross-pollination, as otherwise the upper and lower halves would be + * essentially independent. + * + * This doesn't matter on 64-bit hashes since they all get merged together in + * the end, so we skip the extra step. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +#if (XXH_VECTOR == XXH_AVX512) \ + || (defined(XXH_DISPATCH_AVX512) && XXH_DISPATCH_AVX512 != 0) + +#ifndef XXH_TARGET_AVX512 +# define XXH_TARGET_AVX512 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_accumulate_512_avx512(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ALIGN(64) __m512i* const xacc = (__m512i *) acc; + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + + { + /* data_vec = input[0]; */ + __m512i const data_vec = _mm512_loadu_si512 (input); + /* key_vec = secret[0]; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + /* data_key = data_vec ^ key_vec; */ + __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m512i const data_key_lo = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1)); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m512i const product = _mm512_mul_epu32 (data_key, data_key_lo); + /* xacc[0] += swap(data_vec); */ + __m512i const data_swap = _mm512_shuffle_epi32(data_vec, (_MM_PERM_ENUM)_MM_SHUFFLE(1, 0, 3, 2)); + __m512i const sum = _mm512_add_epi64(*xacc, data_swap); + /* xacc[0] += product; */ + *xacc = _mm512_add_epi64(product, sum); + } +} + +/* + * XXH3_scrambleAcc: Scrambles the accumulators to improve mixing. + * + * Multiplication isn't perfect, as explained by Google in HighwayHash: + * + * // Multiplication mixes/scrambles bytes 0-7 of the 64-bit result to + * // varying degrees. In descending order of goodness, bytes + * // 3 4 2 5 1 6 0 7 have quality 228 224 164 160 100 96 36 32. + * // As expected, the upper and lower bytes are much worse. + * + * Source: https://github.com/google/highwayhash/blob/0aaf66b/highwayhash/hh_avx2.h#L291 + * + * Since our algorithm uses a pseudorandom secret to add some variance into the + * mix, we don't need to (or want to) mix as often or as much as HighwayHash does. + * + * This isn't as tight as XXH3_accumulate, but still written in SIMD to avoid + * extraction. + * + * Both XXH3_64bits and XXH3_128bits use this subroutine. + */ + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 63) == 0); + XXH_STATIC_ASSERT(XXH_STRIPE_LEN == sizeof(__m512i)); + { XXH_ALIGN(64) __m512i* const xacc = (__m512i*) acc; + const __m512i prime32 = _mm512_set1_epi32((int)XXH_PRIME32_1); + + /* xacc[0] ^= (xacc[0] >> 47) */ + __m512i const acc_vec = *xacc; + __m512i const shifted = _mm512_srli_epi64 (acc_vec, 47); + __m512i const data_vec = _mm512_xor_si512 (acc_vec, shifted); + /* xacc[0] ^= secret; */ + __m512i const key_vec = _mm512_loadu_si512 (secret); + __m512i const data_key = _mm512_xor_si512 (data_vec, key_vec); + + /* xacc[0] *= XXH_PRIME32_1; */ + __m512i const data_key_hi = _mm512_shuffle_epi32 (data_key, (_MM_PERM_ENUM)_MM_SHUFFLE(0, 3, 0, 1)); + __m512i const prod_lo = _mm512_mul_epu32 (data_key, prime32); + __m512i const prod_hi = _mm512_mul_epu32 (data_key_hi, prime32); + *xacc = _mm512_add_epi64(prod_lo, _mm512_slli_epi64(prod_hi, 32)); + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX512 void +XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN == 64); + XXH_ASSERT(((size_t)customSecret & 63) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m512i); + __m512i const seed = _mm512_mask_set1_epi64(_mm512_set1_epi64((xxh_i64)seed64), 0xAA, -(xxh_i64)seed64); + + XXH_ALIGN(64) const __m512i* const src = (const __m512i*) XXH3_kSecret; + XXH_ALIGN(64) __m512i* const dest = ( __m512i*) customSecret; + int i; + for (i=0; i < nbRounds; ++i) { + /* GCC has a bug, _mm512_stream_load_si512 accepts 'void*', not 'void const*', + * this will warn "discards ‘const’ qualifier". */ + union { + XXH_ALIGN(64) const __m512i* cp; + XXH_ALIGN(64) void* p; + } remote_const_void; + remote_const_void.cp = src + i; + dest[i] = _mm512_add_epi64(_mm512_stream_load_si512(remote_const_void.p), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_AVX2) \ + || (defined(XXH_DISPATCH_AVX2) && XXH_DISPATCH_AVX2 != 0) + +#ifndef XXH_TARGET_AVX2 +# define XXH_TARGET_AVX2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_accumulate_512_avx2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { XXH_ALIGN(32) __m256i* const xacc = (__m256i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xinput = (const __m256i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* data_vec = xinput[i]; */ + __m256i const data_vec = _mm256_loadu_si256 (xinput+i); + /* key_vec = xsecret[i]; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m256i const data_key_lo = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m256i const product = _mm256_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m256i const data_swap = _mm256_shuffle_epi32(data_vec, _MM_SHUFFLE(1, 0, 3, 2)); + __m256i const sum = _mm256_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm256_add_epi64(product, sum); + } } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void +XXH3_scrambleAcc_avx2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 31) == 0); + { XXH_ALIGN(32) __m256i* const xacc = (__m256i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm256_loadu_si256 requires a const __m256i * pointer for some reason. */ + const __m256i* const xsecret = (const __m256i *) secret; + const __m256i prime32 = _mm256_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m256i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m256i const acc_vec = xacc[i]; + __m256i const shifted = _mm256_srli_epi64 (acc_vec, 47); + __m256i const data_vec = _mm256_xor_si256 (acc_vec, shifted); + /* xacc[i] ^= xsecret; */ + __m256i const key_vec = _mm256_loadu_si256 (xsecret+i); + __m256i const data_key = _mm256_xor_si256 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m256i const data_key_hi = _mm256_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + __m256i const prod_lo = _mm256_mul_epu32 (data_key, prime32); + __m256i const prod_hi = _mm256_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm256_add_epi64(prod_lo, _mm256_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_AVX2 void XXH3_initCustomSecret_avx2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 31) == 0); + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE / sizeof(__m256i)) == 6); + XXH_STATIC_ASSERT(XXH_SEC_ALIGN <= 64); + (void)(&XXH_writeLE64); + XXH_PREFETCH(customSecret); + { __m256i const seed = _mm256_set_epi64x(-(xxh_i64)seed64, (xxh_i64)seed64, -(xxh_i64)seed64, (xxh_i64)seed64); + + XXH_ALIGN(64) const __m256i* const src = (const __m256i*) XXH3_kSecret; + XXH_ALIGN(64) __m256i* dest = ( __m256i*) customSecret; + +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + * The asm hack causes Clang to assume that XXH3_kSecretPtr aliases with + * customSecret, and on aarch64, this prevented LDP from merging two + * loads together for free. Putting the loads together before the stores + * properly generates LDP. + */ + __asm__("" : "+r" (dest)); +# endif + + /* GCC -O2 need unroll loop manually */ + dest[0] = _mm256_add_epi64(_mm256_stream_load_si256(src+0), seed); + dest[1] = _mm256_add_epi64(_mm256_stream_load_si256(src+1), seed); + dest[2] = _mm256_add_epi64(_mm256_stream_load_si256(src+2), seed); + dest[3] = _mm256_add_epi64(_mm256_stream_load_si256(src+3), seed); + dest[4] = _mm256_add_epi64(_mm256_stream_load_si256(src+4), seed); + dest[5] = _mm256_add_epi64(_mm256_stream_load_si256(src+5), seed); + } +} + +#endif + +/* x86dispatch always generates SSE2 */ +#if (XXH_VECTOR == XXH_SSE2) || defined(XXH_X86DISPATCH) + +#ifndef XXH_TARGET_SSE2 +# define XXH_TARGET_SSE2 /* disable attribute target */ +#endif + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_accumulate_512_sse2( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + /* SSE2 is just a half-scale version of the AVX2 version. */ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { XXH_ALIGN(16) __m128i* const xacc = (__m128i *) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xinput = (const __m128i *) input; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* data_vec = xinput[i]; */ + __m128i const data_vec = _mm_loadu_si128 (xinput+i); + /* key_vec = xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + /* data_key = data_vec ^ key_vec; */ + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + /* data_key_lo = data_key >> 32; */ + __m128i const data_key_lo = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + /* product = (data_key & 0xffffffff) * (data_key_lo & 0xffffffff); */ + __m128i const product = _mm_mul_epu32 (data_key, data_key_lo); + /* xacc[i] += swap(data_vec); */ + __m128i const data_swap = _mm_shuffle_epi32(data_vec, _MM_SHUFFLE(1,0,3,2)); + __m128i const sum = _mm_add_epi64(xacc[i], data_swap); + /* xacc[i] += product; */ + xacc[i] = _mm_add_epi64(product, sum); + } } +} + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void +XXH3_scrambleAcc_sse2(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { XXH_ALIGN(16) __m128i* const xacc = (__m128i*) acc; + /* Unaligned. This is mainly for pointer arithmetic, and because + * _mm_loadu_si128 requires a const __m128i * pointer for some reason. */ + const __m128i* const xsecret = (const __m128i *) secret; + const __m128i prime32 = _mm_set1_epi32((int)XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(__m128i); i++) { + /* xacc[i] ^= (xacc[i] >> 47) */ + __m128i const acc_vec = xacc[i]; + __m128i const shifted = _mm_srli_epi64 (acc_vec, 47); + __m128i const data_vec = _mm_xor_si128 (acc_vec, shifted); + /* xacc[i] ^= xsecret[i]; */ + __m128i const key_vec = _mm_loadu_si128 (xsecret+i); + __m128i const data_key = _mm_xor_si128 (data_vec, key_vec); + + /* xacc[i] *= XXH_PRIME32_1; */ + __m128i const data_key_hi = _mm_shuffle_epi32 (data_key, _MM_SHUFFLE(0, 3, 0, 1)); + __m128i const prod_lo = _mm_mul_epu32 (data_key, prime32); + __m128i const prod_hi = _mm_mul_epu32 (data_key_hi, prime32); + xacc[i] = _mm_add_epi64(prod_lo, _mm_slli_epi64(prod_hi, 32)); + } + } +} + +XXH_FORCE_INLINE XXH_TARGET_SSE2 void XXH3_initCustomSecret_sse2(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + (void)(&XXH_writeLE64); + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / sizeof(__m128i); + +# if defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER < 1900 + // MSVC 32bit mode does not support _mm_set_epi64x before 2015 + XXH_ALIGN(16) const xxh_i64 seed64x2[2] = { (xxh_i64)seed64, -(xxh_i64)seed64 }; + __m128i const seed = _mm_load_si128((__m128i const*)seed64x2); +# else + __m128i const seed = _mm_set_epi64x(-(xxh_i64)seed64, (xxh_i64)seed64); +# endif + int i; + + XXH_ALIGN(64) const float* const src = (float const*) XXH3_kSecret; + XXH_ALIGN(XXH_SEC_ALIGN) __m128i* dest = (__m128i*) customSecret; +# if defined(__GNUC__) || defined(__clang__) + /* + * On GCC & Clang, marking 'dest' as modified will cause the compiler: + * - do not extract the secret from sse registers in the internal loop + * - use less common registers, and avoid pushing these reg into stack + */ + __asm__("" : "+r" (dest)); +# endif + + for (i=0; i < nbRounds; ++i) { + dest[i] = _mm_add_epi64(_mm_castps_si128(_mm_load_ps(src+i*4)), seed); + } } +} + +#endif + +#if (XXH_VECTOR == XXH_NEON) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_neon( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + { + XXH_ALIGN(16) uint64x2_t* const xacc = (uint64x2_t *) acc; + /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */ + uint8_t const* const xinput = (const uint8_t *) input; + uint8_t const* const xsecret = (const uint8_t *) secret; + + size_t i; + for (i=0; i < XXH_STRIPE_LEN / sizeof(uint64x2_t); i++) { + /* data_vec = xinput[i]; */ + uint8x16_t data_vec = vld1q_u8(xinput + (i * 16)); + /* key_vec = xsecret[i]; */ + uint8x16_t key_vec = vld1q_u8(xsecret + (i * 16)); + uint64x2_t data_key; + uint32x2_t data_key_lo, data_key_hi; + /* xacc[i] += swap(data_vec); */ + uint64x2_t const data64 = vreinterpretq_u64_u8(data_vec); + uint64x2_t const swapped = vextq_u64(data64, data64, 1); + xacc[i] = vaddq_u64 (xacc[i], swapped); + /* data_key = data_vec ^ key_vec; */ + data_key = vreinterpretq_u64_u8(veorq_u8(data_vec, key_vec)); + /* data_key_lo = (uint32x2_t) (data_key & 0xFFFFFFFF); + * data_key_hi = (uint32x2_t) (data_key >> 32); + * data_key = UNDEFINED; */ + XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi); + /* xacc[i] += (uint64x2_t) data_key_lo * (uint64x2_t) data_key_hi; */ + xacc[i] = vmlal_u32 (xacc[i], data_key_lo, data_key_hi); + + } + } +} + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { uint64x2_t* xacc = (uint64x2_t*) acc; + uint8_t const* xsecret = (uint8_t const*) secret; + uint32x2_t prime = vdup_n_u32 (XXH_PRIME32_1); + + size_t i; + for (i=0; i < XXH_STRIPE_LEN/sizeof(uint64x2_t); i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + uint64x2_t acc_vec = xacc[i]; + uint64x2_t shifted = vshrq_n_u64 (acc_vec, 47); + uint64x2_t data_vec = veorq_u64 (acc_vec, shifted); + + /* xacc[i] ^= xsecret[i]; */ + uint8x16_t key_vec = vld1q_u8(xsecret + (i * 16)); + uint64x2_t data_key = veorq_u64(data_vec, vreinterpretq_u64_u8(key_vec)); + + /* xacc[i] *= XXH_PRIME32_1 */ + uint32x2_t data_key_lo, data_key_hi; + /* data_key_lo = (uint32x2_t) (xacc[i] & 0xFFFFFFFF); + * data_key_hi = (uint32x2_t) (xacc[i] >> 32); + * xacc[i] = UNDEFINED; */ + XXH_SPLIT_IN_PLACE(data_key, data_key_lo, data_key_hi); + { /* + * prod_hi = (data_key >> 32) * XXH_PRIME32_1; + * + * Avoid vmul_u32 + vshll_n_u32 since Clang 6 and 7 will + * incorrectly "optimize" this: + * tmp = vmul_u32(vmovn_u64(a), vmovn_u64(b)); + * shifted = vshll_n_u32(tmp, 32); + * to this: + * tmp = "vmulq_u64"(a, b); // no such thing! + * shifted = vshlq_n_u64(tmp, 32); + * + * However, unlike SSE, Clang lacks a 64-bit multiply routine + * for NEON, and it scalarizes two 64-bit multiplies instead. + * + * vmull_u32 has the same timing as vmul_u32, and it avoids + * this bug completely. + * See https://bugs.llvm.org/show_bug.cgi?id=39967 + */ + uint64x2_t prod_hi = vmull_u32 (data_key_hi, prime); + /* xacc[i] = prod_hi << 32; */ + xacc[i] = vshlq_n_u64(prod_hi, 32); + /* xacc[i] += (prod_hi & 0xFFFFFFFF) * XXH_PRIME32_1; */ + xacc[i] = vmlal_u32(xacc[i], data_key_lo, prime); + } + } } +} + +#endif + +#if (XXH_VECTOR == XXH_VSX) + +XXH_FORCE_INLINE void +XXH3_accumulate_512_vsx( void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + xxh_u64x2* const xacc = (xxh_u64x2*) acc; /* presumed aligned */ + xxh_u64x2 const* const xinput = (xxh_u64x2 const*) input; /* no alignment restriction */ + xxh_u64x2 const* const xsecret = (xxh_u64x2 const*) secret; /* no alignment restriction */ + xxh_u64x2 const v32 = { 32, 32 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* data_vec = xinput[i]; */ + xxh_u64x2 const data_vec = XXH_vec_loadu(xinput + i); + /* key_vec = xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + /* shuffled = (data_key << 32) | (data_key >> 32); */ + xxh_u32x4 const shuffled = (xxh_u32x4)vec_rl(data_key, v32); + /* product = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)shuffled & 0xFFFFFFFF); */ + xxh_u64x2 const product = XXH_vec_mulo((xxh_u32x4)data_key, shuffled); + xacc[i] += product; + + /* swap high and low halves */ +#ifdef __s390x__ + xacc[i] += vec_permi(data_vec, data_vec, 2); +#else + xacc[i] += vec_xxpermdi(data_vec, data_vec, 2); +#endif + } +} + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_vsx(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ASSERT((((size_t)acc) & 15) == 0); + + { xxh_u64x2* const xacc = (xxh_u64x2*) acc; + const xxh_u64x2* const xsecret = (const xxh_u64x2*) secret; + /* constants */ + xxh_u64x2 const v32 = { 32, 32 }; + xxh_u64x2 const v47 = { 47, 47 }; + xxh_u32x4 const prime = { XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1, XXH_PRIME32_1 }; + size_t i; + for (i = 0; i < XXH_STRIPE_LEN / sizeof(xxh_u64x2); i++) { + /* xacc[i] ^= (xacc[i] >> 47); */ + xxh_u64x2 const acc_vec = xacc[i]; + xxh_u64x2 const data_vec = acc_vec ^ (acc_vec >> v47); + + /* xacc[i] ^= xsecret[i]; */ + xxh_u64x2 const key_vec = XXH_vec_loadu(xsecret + i); + xxh_u64x2 const data_key = data_vec ^ key_vec; + + /* xacc[i] *= XXH_PRIME32_1 */ + /* prod_lo = ((xxh_u64x2)data_key & 0xFFFFFFFF) * ((xxh_u64x2)prime & 0xFFFFFFFF); */ + xxh_u64x2 const prod_even = XXH_vec_mule((xxh_u32x4)data_key, prime); + /* prod_hi = ((xxh_u64x2)data_key >> 32) * ((xxh_u64x2)prime >> 32); */ + xxh_u64x2 const prod_odd = XXH_vec_mulo((xxh_u32x4)data_key, prime); + xacc[i] = prod_odd + (prod_even << v32); + } } +} + +#endif + +/* scalar variants - universal */ + +XXH_FORCE_INLINE void +XXH3_accumulate_512_scalar(void* XXH_RESTRICT acc, + const void* XXH_RESTRICT input, + const void* XXH_RESTRICT secret) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ + const xxh_u8* const xinput = (const xxh_u8*) input; /* no alignment restriction */ + const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ + size_t i; + XXH_ASSERT(((size_t)acc & (XXH_ACC_ALIGN-1)) == 0); + for (i=0; i < XXH_ACC_NB; i++) { + xxh_u64 const data_val = XXH_readLE64(xinput + 8*i); + xxh_u64 const data_key = data_val ^ XXH_readLE64(xsecret + i*8); + xacc[i ^ 1] += data_val; /* swap adjacent lanes */ + xacc[i] += XXH_mult32to64(data_key & 0xFFFFFFFF, data_key >> 32); + } +} + +XXH_FORCE_INLINE void +XXH3_scrambleAcc_scalar(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64* const xacc = (xxh_u64*) acc; /* presumed aligned */ + const xxh_u8* const xsecret = (const xxh_u8*) secret; /* no alignment restriction */ + size_t i; + XXH_ASSERT((((size_t)acc) & (XXH_ACC_ALIGN-1)) == 0); + for (i=0; i < XXH_ACC_NB; i++) { + xxh_u64 const key64 = XXH_readLE64(xsecret + 8*i); + xxh_u64 acc64 = xacc[i]; + acc64 = XXH_xorshift64(acc64, 47); + acc64 ^= key64; + acc64 *= XXH_PRIME32_1; + xacc[i] = acc64; + } +} + +XXH_FORCE_INLINE void +XXH3_initCustomSecret_scalar(void* XXH_RESTRICT customSecret, xxh_u64 seed64) +{ + /* + * We need a separate pointer for the hack below, + * which requires a non-const pointer. + * Any decent compiler will optimize this out otherwise. + */ + const xxh_u8* kSecretPtr = XXH3_kSecret; + XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 15) == 0); + +#if defined(__clang__) && defined(__aarch64__) + /* + * UGLY HACK: + * Clang generates a bunch of MOV/MOVK pairs for aarch64, and they are + * placed sequentially, in order, at the top of the unrolled loop. + * + * While MOVK is great for generating constants (2 cycles for a 64-bit + * constant compared to 4 cycles for LDR), long MOVK chains stall the + * integer pipelines: + * I L S + * MOVK + * MOVK + * MOVK + * MOVK + * ADD + * SUB STR + * STR + * By forcing loads from memory (as the asm line causes Clang to assume + * that XXH3_kSecretPtr has been changed), the pipelines are used more + * efficiently: + * I L S + * LDR + * ADD LDR + * SUB STR + * STR + * XXH3_64bits_withSeed, len == 256, Snapdragon 835 + * without hack: 2654.4 MB/s + * with hack: 3202.9 MB/s + */ + __asm__("" : "+r" (kSecretPtr)); +#endif + /* + * Note: in debug mode, this overrides the asm optimization + * and Clang will emit MOVK chains again. + */ + XXH_ASSERT(kSecretPtr == XXH3_kSecret); + + { int const nbRounds = XXH_SECRET_DEFAULT_SIZE / 16; + int i; + for (i=0; i < nbRounds; i++) { + /* + * The asm hack causes Clang to assume that kSecretPtr aliases with + * customSecret, and on aarch64, this prevented LDP from merging two + * loads together for free. Putting the loads together before the stores + * properly generates LDP. + */ + xxh_u64 lo = XXH_readLE64(kSecretPtr + 16*i) + seed64; + xxh_u64 hi = XXH_readLE64(kSecretPtr + 16*i + 8) - seed64; + XXH_writeLE64((xxh_u8*)customSecret + 16*i, lo); + XXH_writeLE64((xxh_u8*)customSecret + 16*i + 8, hi); + } } +} + + +typedef void (*XXH3_f_accumulate_512)(void* XXH_RESTRICT, const void*, const void*); +typedef void (*XXH3_f_scrambleAcc)(void* XXH_RESTRICT, const void*); +typedef void (*XXH3_f_initCustomSecret)(void* XXH_RESTRICT, xxh_u64); + + +#if (XXH_VECTOR == XXH_AVX512) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx512 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx512 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx512 + +#elif (XXH_VECTOR == XXH_AVX2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_avx2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_avx2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_avx2 + +#elif (XXH_VECTOR == XXH_SSE2) + +#define XXH3_accumulate_512 XXH3_accumulate_512_sse2 +#define XXH3_scrambleAcc XXH3_scrambleAcc_sse2 +#define XXH3_initCustomSecret XXH3_initCustomSecret_sse2 + +#elif (XXH_VECTOR == XXH_NEON) + +#define XXH3_accumulate_512 XXH3_accumulate_512_neon +#define XXH3_scrambleAcc XXH3_scrambleAcc_neon +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#elif (XXH_VECTOR == XXH_VSX) + +#define XXH3_accumulate_512 XXH3_accumulate_512_vsx +#define XXH3_scrambleAcc XXH3_scrambleAcc_vsx +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#else /* scalar */ + +#define XXH3_accumulate_512 XXH3_accumulate_512_scalar +#define XXH3_scrambleAcc XXH3_scrambleAcc_scalar +#define XXH3_initCustomSecret XXH3_initCustomSecret_scalar + +#endif + + + +#ifndef XXH_PREFETCH_DIST +# ifdef __clang__ +# define XXH_PREFETCH_DIST 320 +# else +# if (XXH_VECTOR == XXH_AVX512) +# define XXH_PREFETCH_DIST 512 +# else +# define XXH_PREFETCH_DIST 384 +# endif +# endif /* __clang__ */ +#endif /* XXH_PREFETCH_DIST */ + +/* + * XXH3_accumulate() + * Loops over XXH3_accumulate_512(). + * Assumption: nbStripes will not overflow the secret size + */ +XXH_FORCE_INLINE void +XXH3_accumulate( xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, + const xxh_u8* XXH_RESTRICT secret, + size_t nbStripes, + XXH3_f_accumulate_512 f_acc512) +{ + size_t n; + for (n = 0; n < nbStripes; n++ ) { + const xxh_u8* const in = input + n*XXH_STRIPE_LEN; + XXH_PREFETCH(in + XXH_PREFETCH_DIST); + f_acc512(acc, + in, + secret + n*XXH_SECRET_CONSUME_RATE); + } +} + +XXH_FORCE_INLINE void +XXH3_hashLong_internal_loop(xxh_u64* XXH_RESTRICT acc, + const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate_512 f_acc512, + XXH3_f_scrambleAcc f_scramble) +{ + size_t const nbStripesPerBlock = (secretSize - XXH_STRIPE_LEN) / XXH_SECRET_CONSUME_RATE; + size_t const block_len = XXH_STRIPE_LEN * nbStripesPerBlock; + size_t const nb_blocks = (len - 1) / block_len; + + size_t n; + + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + + for (n = 0; n < nb_blocks; n++) { + XXH3_accumulate(acc, input + n*block_len, secret, nbStripesPerBlock, f_acc512); + f_scramble(acc, secret + secretSize - XXH_STRIPE_LEN); + } + + /* last partial block */ + XXH_ASSERT(len > XXH_STRIPE_LEN); + { size_t const nbStripes = ((len - 1) - (block_len * nb_blocks)) / XXH_STRIPE_LEN; + XXH_ASSERT(nbStripes <= (secretSize / XXH_SECRET_CONSUME_RATE)); + XXH3_accumulate(acc, input + nb_blocks*block_len, secret, nbStripes, f_acc512); + + /* last stripe */ + { const xxh_u8* const p = input + len - XXH_STRIPE_LEN; +#define XXH_SECRET_LASTACC_START 7 /* not aligned on 8, last secret is different from acc & scrambler */ + f_acc512(acc, p, secret + secretSize - XXH_STRIPE_LEN - XXH_SECRET_LASTACC_START); + } } +} + +XXH_FORCE_INLINE xxh_u64 +XXH3_mix2Accs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret) +{ + return XXH3_mul128_fold64( + acc[0] ^ XXH_readLE64(secret), + acc[1] ^ XXH_readLE64(secret+8) ); +} + +static XXH64_hash_t +XXH3_mergeAccs(const xxh_u64* XXH_RESTRICT acc, const xxh_u8* XXH_RESTRICT secret, xxh_u64 start) +{ + xxh_u64 result64 = start; + size_t i = 0; + + for (i = 0; i < 4; i++) { + result64 += XXH3_mix2Accs(acc+2*i, secret + 16*i); +#if defined(__clang__) /* Clang */ \ + && (defined(__arm__) || defined(__thumb__)) /* ARMv7 */ \ + && (defined(__ARM_NEON) || defined(__ARM_NEON__)) /* NEON */ \ + && !defined(XXH_ENABLE_AUTOVECTORIZE) /* Define to disable */ + /* + * UGLY HACK: + * Prevent autovectorization on Clang ARMv7-a. Exact same problem as + * the one in XXH3_len_129to240_64b. Speeds up shorter keys > 240b. + * XXH3_64bits, len == 256, Snapdragon 835: + * without hack: 2063.7 MB/s + * with hack: 2560.7 MB/s + */ + __asm__("" : "+r" (result64)); +#endif + } + + return XXH3_avalanche(result64); +} + +#define XXH3_INIT_ACC { XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \ + XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 } + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_internal(const void* XXH_RESTRICT input, size_t len, + const void* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate_512 f_acc512, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, (const xxh_u8*)secret, secretSize, f_acc512, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + /* do not align on 8, so that the secret is different from the accumulator */ +#define XXH_SECRET_MERGEACCS_START 11 + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + return XXH3_mergeAccs(acc, (const xxh_u8*)secret + XXH_SECRET_MERGEACCS_START, (xxh_u64)len * XXH_PRIME64_1); +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_64b_internal(input, len, secret, secretLen, XXH3_accumulate_512, XXH3_scrambleAcc); +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + * Since the function is not inlined, the compiler may not be able to understand that, + * in some scenarios, its `secret` argument is actually a compile time constant. + * This variant enforces that the compiler can detect that, + * and uses this opportunity to streamline the generated code for better performance. + */ +XXH_NO_INLINE XXH64_hash_t +XXH3_hashLong_64b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const xxh_u8* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_64b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_accumulate_512, XXH3_scrambleAcc); +} + +/* + * XXH3_hashLong_64b_withSeed(): + * Generate a custom key based on alteration of default XXH3_kSecret with the seed, + * and then use this key for long mode hashing. + * + * This operation is decently fast but nonetheless costs a little bit of time. + * Try to avoid it whenever possible (typically when seed==0). + * + * It's important for performance that XXH3_hashLong is not inlined. Not sure + * why (uop cache maybe?), but the difference is large and easily measurable. + */ +XXH_FORCE_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed_internal(const void* input, size_t len, + XXH64_hash_t seed, + XXH3_f_accumulate_512 f_acc512, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ + if (seed == 0) + return XXH3_hashLong_64b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc512, f_scramble); + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed); + return XXH3_hashLong_64b_internal(input, len, secret, sizeof(secret), + f_acc512, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH64_hash_t +XXH3_hashLong_64b_withSeed(const void* input, size_t len, + XXH64_hash_t seed, const xxh_u8* secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_64b_withSeed_internal(input, len, seed, + XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + + +typedef XXH64_hash_t (*XXH3_hashLong64_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const xxh_u8* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH64_hash_t +XXH3_64bits_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong64_f f_hashLong) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secretLen` condition is not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + * Also, note that function signature doesn't offer room to return an error. + */ + if (len <= 16) + return XXH3_len_0to16_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_64b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hashLong(input, len, seed64, (const xxh_u8*)secret, secretLen); +} + + +/* === Public entry point === */ + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits(const void* input, size_t len) +{ + return XXH3_64bits_internal(input, len, 0, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_default); +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSecret(const void* input, size_t len, const void* secret, size_t secretSize) +{ + return XXH3_64bits_internal(input, len, 0, secret, secretSize, XXH3_hashLong_64b_withSecret); +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH64_hash_t +XXH3_64bits_withSeed(const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_64bits_internal(input, len, seed, XXH3_kSecret, sizeof(XXH3_kSecret), XXH3_hashLong_64b_withSeed); +} + + +/* === XXH3 streaming === */ + +/* + * Malloc's a pointer that is always aligned to align. + * + * This must be freed with `XXH_alignedFree()`. + * + * malloc typically guarantees 16 byte alignment on 64-bit systems and 8 byte + * alignment on 32-bit. This isn't enough for the 32 byte aligned loads in AVX2 + * or on 32-bit, the 16 byte aligned loads in SSE2 and NEON. + * + * This underalignment previously caused a rather obvious crash which went + * completely unnoticed due to XXH3_createState() not actually being tested. + * Credit to RedSpah for noticing this bug. + * + * The alignment is done manually: Functions like posix_memalign or _mm_malloc + * are avoided: To maintain portability, we would have to write a fallback + * like this anyways, and besides, testing for the existence of library + * functions without relying on external build tools is impossible. + * + * The method is simple: Overallocate, manually align, and store the offset + * to the original behind the returned pointer. + * + * Align must be a power of 2 and 8 <= align <= 128. + */ +static void* XXH_alignedMalloc(size_t s, size_t align) +{ + XXH_ASSERT(align <= 128 && align >= 8); /* range check */ + XXH_ASSERT((align & (align-1)) == 0); /* power of 2 */ + XXH_ASSERT(s != 0 && s < (s + align)); /* empty/overflow */ + { /* Overallocate to make room for manual realignment and an offset byte */ + xxh_u8* base = (xxh_u8*)XXH_malloc(s + align); + if (base != NULL) { + /* + * Get the offset needed to align this pointer. + * + * Even if the returned pointer is aligned, there will always be + * at least one byte to store the offset to the original pointer. + */ + size_t offset = align - ((size_t)base & (align - 1)); /* base % align */ + /* Add the offset for the now-aligned pointer */ + xxh_u8* ptr = base + offset; + + XXH_ASSERT((size_t)ptr % align == 0); + + /* Store the offset immediately before the returned pointer. */ + ptr[-1] = (xxh_u8)offset; + return ptr; + } + return NULL; + } +} +/* + * Frees an aligned pointer allocated by XXH_alignedMalloc(). Don't pass + * normal malloc'd pointers, XXH_alignedMalloc has a specific data layout. + */ +static void XXH_alignedFree(void* p) +{ + if (p != NULL) { + xxh_u8* ptr = (xxh_u8*)p; + /* Get the offset byte we added in XXH_malloc. */ + xxh_u8 offset = ptr[-1]; + /* Free the original malloc'd pointer */ + xxh_u8* base = ptr - offset; + XXH_free(base); + } +} +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void) +{ + XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64); + if (state==NULL) return NULL; + XXH3_INITSTATE(state); + return state; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr) +{ + XXH_alignedFree(statePtr); + return XXH_OK; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API void +XXH3_copyState(XXH3_state_t* dst_state, const XXH3_state_t* src_state) +{ + memcpy(dst_state, src_state, sizeof(*dst_state)); +} + +static void +XXH3_reset_internal(XXH3_state_t* statePtr, + XXH64_hash_t seed, + const void* secret, size_t secretSize) +{ + size_t const initStart = offsetof(XXH3_state_t, bufferedSize); + size_t const initLength = offsetof(XXH3_state_t, nbStripesPerBlock) - initStart; + XXH_ASSERT(offsetof(XXH3_state_t, nbStripesPerBlock) > initStart); + XXH_ASSERT(statePtr != NULL); + /* set members from bufferedSize to nbStripesPerBlock (excluded) to 0 */ + memset((char*)statePtr + initStart, 0, initLength); + statePtr->acc[0] = XXH_PRIME32_3; + statePtr->acc[1] = XXH_PRIME64_1; + statePtr->acc[2] = XXH_PRIME64_2; + statePtr->acc[3] = XXH_PRIME64_3; + statePtr->acc[4] = XXH_PRIME64_4; + statePtr->acc[5] = XXH_PRIME32_2; + statePtr->acc[6] = XXH_PRIME64_5; + statePtr->acc[7] = XXH_PRIME32_1; + statePtr->seed = seed; + statePtr->extSecret = (const unsigned char*)secret; + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); + statePtr->secretLimit = secretSize - XXH_STRIPE_LEN; + statePtr->nbStripesPerBlock = statePtr->secretLimit / XXH_SECRET_CONSUME_RATE; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset(XXH3_state_t* statePtr) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, secret, secretSize); + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + return XXH_OK; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + if (statePtr == NULL) return XXH_ERROR; + if (seed==0) return XXH3_64bits_reset(statePtr); + if (seed != statePtr->seed) XXH3_initCustomSecret(statePtr->customSecret, seed); + XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/* Note : when XXH3_consumeStripes() is invoked, + * there must be a guarantee that at least one more byte must be consumed from input + * so that the function can blindly consume all stripes using the "normal" secret segment */ +XXH_FORCE_INLINE void +XXH3_consumeStripes(xxh_u64* XXH_RESTRICT acc, + size_t* XXH_RESTRICT nbStripesSoFarPtr, size_t nbStripesPerBlock, + const xxh_u8* XXH_RESTRICT input, size_t nbStripes, + const xxh_u8* XXH_RESTRICT secret, size_t secretLimit, + XXH3_f_accumulate_512 f_acc512, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ASSERT(nbStripes <= nbStripesPerBlock); /* can handle max 1 scramble per invocation */ + XXH_ASSERT(*nbStripesSoFarPtr < nbStripesPerBlock); + if (nbStripesPerBlock - *nbStripesSoFarPtr <= nbStripes) { + /* need a scrambling operation */ + size_t const nbStripesToEndofBlock = nbStripesPerBlock - *nbStripesSoFarPtr; + size_t const nbStripesAfterBlock = nbStripes - nbStripesToEndofBlock; + XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripesToEndofBlock, f_acc512); + f_scramble(acc, secret + secretLimit); + XXH3_accumulate(acc, input + nbStripesToEndofBlock * XXH_STRIPE_LEN, secret, nbStripesAfterBlock, f_acc512); + *nbStripesSoFarPtr = nbStripesAfterBlock; + } else { + XXH3_accumulate(acc, input, secret + nbStripesSoFarPtr[0] * XXH_SECRET_CONSUME_RATE, nbStripes, f_acc512); + *nbStripesSoFarPtr += nbStripes; + } +} + +/* + * Both XXH3_64bits_update and XXH3_128bits_update use this routine. + */ +XXH_FORCE_INLINE XXH_errorcode +XXH3_update(XXH3_state_t* state, + const xxh_u8* input, size_t len, + XXH3_f_accumulate_512 f_acc512, + XXH3_f_scrambleAcc f_scramble) +{ + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + { const xxh_u8* const bEnd = input + len; + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + + state->totalLen += len; + XXH_ASSERT(state->bufferedSize <= XXH3_INTERNALBUFFER_SIZE); + + if (state->bufferedSize + len <= XXH3_INTERNALBUFFER_SIZE) { /* fill in tmp buffer */ + XXH_memcpy(state->buffer + state->bufferedSize, input, len); + state->bufferedSize += (XXH32_hash_t)len; + return XXH_OK; + } + /* total input is now > XXH3_INTERNALBUFFER_SIZE */ + + #define XXH3_INTERNALBUFFER_STRIPES (XXH3_INTERNALBUFFER_SIZE / XXH_STRIPE_LEN) + XXH_STATIC_ASSERT(XXH3_INTERNALBUFFER_SIZE % XXH_STRIPE_LEN == 0); /* clean multiple */ + + /* + * Internal buffer is partially filled (always, except at beginning) + * Complete it, then consume it. + */ + if (state->bufferedSize) { + size_t const loadSize = XXH3_INTERNALBUFFER_SIZE - state->bufferedSize; + XXH_memcpy(state->buffer + state->bufferedSize, input, loadSize); + input += loadSize; + XXH3_consumeStripes(state->acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, XXH3_INTERNALBUFFER_STRIPES, + secret, state->secretLimit, + f_acc512, f_scramble); + state->bufferedSize = 0; + } + XXH_ASSERT(input < bEnd); + + /* Consume input by a multiple of internal buffer size */ + if (input+XXH3_INTERNALBUFFER_SIZE < bEnd) { + const xxh_u8* const limit = bEnd - XXH3_INTERNALBUFFER_SIZE; + do { + XXH3_consumeStripes(state->acc, + &state->nbStripesSoFar, state->nbStripesPerBlock, + input, XXH3_INTERNALBUFFER_STRIPES, + secret, state->secretLimit, + f_acc512, f_scramble); + input += XXH3_INTERNALBUFFER_SIZE; + } while (inputbuffer + sizeof(state->buffer) - XXH_STRIPE_LEN, input - XXH_STRIPE_LEN, XXH_STRIPE_LEN); + } + XXH_ASSERT(input < bEnd); + + /* Some remaining input (always) : buffer it */ + XXH_memcpy(state->buffer, input, (size_t)(bEnd-input)); + state->bufferedSize = (XXH32_hash_t)(bEnd-input); + } + + return XXH_OK; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_64bits_update(XXH3_state_t* state, const void* input, size_t len) +{ + return XXH3_update(state, (const xxh_u8*)input, len, + XXH3_accumulate_512, XXH3_scrambleAcc); +} + + +XXH_FORCE_INLINE void +XXH3_digest_long (XXH64_hash_t* acc, + const XXH3_state_t* state, + const unsigned char* secret) +{ + /* + * Digest on a local copy. This way, the state remains unaltered, and it can + * continue ingesting more input afterwards. + */ + memcpy(acc, state->acc, sizeof(state->acc)); + if (state->bufferedSize >= XXH_STRIPE_LEN) { + size_t const nbStripes = (state->bufferedSize - 1) / XXH_STRIPE_LEN; + size_t nbStripesSoFar = state->nbStripesSoFar; + XXH3_consumeStripes(acc, + &nbStripesSoFar, state->nbStripesPerBlock, + state->buffer, nbStripes, + secret, state->secretLimit, + XXH3_accumulate_512, XXH3_scrambleAcc); + /* last stripe */ + XXH3_accumulate_512(acc, + state->buffer + state->bufferedSize - XXH_STRIPE_LEN, + secret + state->secretLimit - XXH_SECRET_LASTACC_START); + } else { /* bufferedSize < XXH_STRIPE_LEN */ + xxh_u8 lastStripe[XXH_STRIPE_LEN]; + size_t const catchupSize = XXH_STRIPE_LEN - state->bufferedSize; + XXH_ASSERT(state->bufferedSize > 0); /* there is always some input buffered */ + memcpy(lastStripe, state->buffer + sizeof(state->buffer) - catchupSize, catchupSize); + memcpy(lastStripe + catchupSize, state->buffer, state->bufferedSize); + XXH3_accumulate_512(acc, + lastStripe, + secret + state->secretLimit - XXH_SECRET_LASTACC_START); + } +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH64_hash_t XXH3_64bits_digest (const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + return XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)state->totalLen * XXH_PRIME64_1); + } + /* totalLen <= XXH3_MIDSIZE_MAX: digesting a short input */ + if (state->seed) + return XXH3_64bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_64bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} + + +#define XXH_MIN(x, y) (((x) > (y)) ? (y) : (x)) + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API void +XXH3_generateSecret(void* secretBuffer, const void* customSeed, size_t customSeedSize) +{ + XXH_ASSERT(secretBuffer != NULL); + if (customSeedSize == 0) { + memcpy(secretBuffer, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); + return; + } + XXH_ASSERT(customSeed != NULL); + + { size_t const segmentSize = sizeof(XXH128_hash_t); + size_t const nbSegments = XXH_SECRET_DEFAULT_SIZE / segmentSize; + XXH128_canonical_t scrambler; + XXH64_hash_t seeds[12]; + size_t segnb; + XXH_ASSERT(nbSegments == 12); + XXH_ASSERT(segmentSize * nbSegments == XXH_SECRET_DEFAULT_SIZE); /* exact multiple */ + XXH128_canonicalFromHash(&scrambler, XXH128(customSeed, customSeedSize, 0)); + + /* + * Copy customSeed to seeds[], truncating or repeating as necessary. + */ + { size_t toFill = XXH_MIN(customSeedSize, sizeof(seeds)); + size_t filled = toFill; + memcpy(seeds, customSeed, toFill); + while (filled < sizeof(seeds)) { + toFill = XXH_MIN(filled, sizeof(seeds) - filled); + memcpy((char*)seeds + filled, seeds, toFill); + filled += toFill; + } } + + /* generate secret */ + memcpy(secretBuffer, &scrambler, sizeof(scrambler)); + for (segnb=1; segnb < nbSegments; segnb++) { + size_t const segmentStart = segnb * segmentSize; + XXH128_canonical_t segment; + XXH128_canonicalFromHash(&segment, + XXH128(&scrambler, sizeof(scrambler), XXH_readLE64(seeds + segnb) + segnb) ); + memcpy((char*)secretBuffer + segmentStart, &segment, sizeof(segment)); + } } +} + + +/* ========================================== + * XXH3 128 bits (a.k.a XXH128) + * ========================================== + * XXH3's 128-bit variant has better mixing and strength than the 64-bit variant, + * even without counting the significantly larger output size. + * + * For example, extra steps are taken to avoid the seed-dependent collisions + * in 17-240 byte inputs (See XXH3_mix16B and XXH128_mix32B). + * + * This strength naturally comes at the cost of some speed, especially on short + * lengths. Note that longer hashes are about as fast as the 64-bit version + * due to it using only a slight modification of the 64-bit loop. + * + * XXH128 is also more oriented towards 64-bit machines. It is still extremely + * fast for a _128-bit_ hash on 32-bit (it usually clears XXH64). + */ + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_len_1to3_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + /* A doubled version of 1to3_64b with different constants. */ + XXH_ASSERT(input != NULL); + XXH_ASSERT(1 <= len && len <= 3); + XXH_ASSERT(secret != NULL); + /* + * len = 1: combinedl = { input[0], 0x01, input[0], input[0] } + * len = 2: combinedl = { input[1], 0x02, input[0], input[1] } + * len = 3: combinedl = { input[2], 0x03, input[0], input[1] } + */ + { xxh_u8 const c1 = input[0]; + xxh_u8 const c2 = input[len >> 1]; + xxh_u8 const c3 = input[len - 1]; + xxh_u32 const combinedl = ((xxh_u32)c1 <<16) | ((xxh_u32)c2 << 24) + | ((xxh_u32)c3 << 0) | ((xxh_u32)len << 8); + xxh_u32 const combinedh = XXH_rotl32(XXH_swap32(combinedl), 13); + xxh_u64 const bitflipl = (XXH_readLE32(secret) ^ XXH_readLE32(secret+4)) + seed; + xxh_u64 const bitfliph = (XXH_readLE32(secret+8) ^ XXH_readLE32(secret+12)) - seed; + xxh_u64 const keyed_lo = (xxh_u64)combinedl ^ bitflipl; + xxh_u64 const keyed_hi = (xxh_u64)combinedh ^ bitfliph; + XXH128_hash_t h128; + h128.low64 = XXH64_avalanche(keyed_lo); + h128.high64 = XXH64_avalanche(keyed_hi); + return h128; + } +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(4 <= len && len <= 8); + seed ^= (xxh_u64)XXH_swap32((xxh_u32)seed) << 32; + { xxh_u32 const input_lo = XXH_readLE32(input); + xxh_u32 const input_hi = XXH_readLE32(input + len - 4); + xxh_u64 const input_64 = input_lo + ((xxh_u64)input_hi << 32); + xxh_u64 const bitflip = (XXH_readLE64(secret+16) ^ XXH_readLE64(secret+24)) + seed; + xxh_u64 const keyed = input_64 ^ bitflip; + + /* Shift len to the left to ensure it is even, this avoids even multiplies. */ + XXH128_hash_t m128 = XXH_mult64to128(keyed, XXH_PRIME64_1 + (len << 2)); + + m128.high64 += (m128.low64 << 1); + m128.low64 ^= (m128.high64 >> 3); + + m128.low64 = XXH_xorshift64(m128.low64, 35); + m128.low64 *= 0x9FB21C651E98DF25ULL; + m128.low64 = XXH_xorshift64(m128.low64, 28); + m128.high64 = XXH3_avalanche(m128.high64); + return m128; + } +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_len_9to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(input != NULL); + XXH_ASSERT(secret != NULL); + XXH_ASSERT(9 <= len && len <= 16); + { xxh_u64 const bitflipl = (XXH_readLE64(secret+32) ^ XXH_readLE64(secret+40)) - seed; + xxh_u64 const bitfliph = (XXH_readLE64(secret+48) ^ XXH_readLE64(secret+56)) + seed; + xxh_u64 const input_lo = XXH_readLE64(input); + xxh_u64 input_hi = XXH_readLE64(input + len - 8); + XXH128_hash_t m128 = XXH_mult64to128(input_lo ^ input_hi ^ bitflipl, XXH_PRIME64_1); + /* + * Put len in the middle of m128 to ensure that the length gets mixed to + * both the low and high bits in the 128x64 multiply below. + */ + m128.low64 += (xxh_u64)(len - 1) << 54; + input_hi ^= bitfliph; + /* + * Add the high 32 bits of input_hi to the high 32 bits of m128, then + * add the long product of the low 32 bits of input_hi and XXH_PRIME32_2 to + * the high 64 bits of m128. + * + * The best approach to this operation is different on 32-bit and 64-bit. + */ + if (sizeof(void *) < sizeof(xxh_u64)) { /* 32-bit */ + /* + * 32-bit optimized version, which is more readable. + * + * On 32-bit, it removes an ADC and delays a dependency between the two + * halves of m128.high64, but it generates an extra mask on 64-bit. + */ + m128.high64 += (input_hi & 0xFFFFFFFF00000000ULL) + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2); + } else { + /* + * 64-bit optimized (albeit more confusing) version. + * + * Uses some properties of addition and multiplication to remove the mask: + * + * Let: + * a = input_hi.lo = (input_hi & 0x00000000FFFFFFFF) + * b = input_hi.hi = (input_hi & 0xFFFFFFFF00000000) + * c = XXH_PRIME32_2 + * + * a + (b * c) + * Inverse Property: x + y - x == y + * a + (b * (1 + c - 1)) + * Distributive Property: x * (y + z) == (x * y) + (x * z) + * a + (b * 1) + (b * (c - 1)) + * Identity Property: x * 1 == x + * a + b + (b * (c - 1)) + * + * Substitute a, b, and c: + * input_hi.hi + input_hi.lo + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + * + * Since input_hi.hi + input_hi.lo == input_hi, we get this: + * input_hi + ((xxh_u64)input_hi.lo * (XXH_PRIME32_2 - 1)) + */ + m128.high64 += input_hi + XXH_mult32to64((xxh_u32)input_hi, XXH_PRIME32_2 - 1); + } + /* m128 ^= XXH_swap64(m128 >> 64); */ + m128.low64 ^= XXH_swap64(m128.high64); + + { /* 128x64 multiply: h128 = m128 * XXH_PRIME64_2; */ + XXH128_hash_t h128 = XXH_mult64to128(m128.low64, XXH_PRIME64_2); + h128.high64 += m128.high64 * XXH_PRIME64_2; + + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = XXH3_avalanche(h128.high64); + return h128; + } } +} + +/* + * Assumption: `secret` size is >= XXH3_SECRET_SIZE_MIN + */ +XXH_FORCE_INLINE XXH128_hash_t +XXH3_len_0to16_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_hash_t seed) +{ + XXH_ASSERT(len <= 16); + { if (len > 8) return XXH3_len_9to16_128b(input, len, secret, seed); + if (len >= 4) return XXH3_len_4to8_128b(input, len, secret, seed); + if (len) return XXH3_len_1to3_128b(input, len, secret, seed); + { XXH128_hash_t h128; + xxh_u64 const bitflipl = XXH_readLE64(secret+64) ^ XXH_readLE64(secret+72); + xxh_u64 const bitfliph = XXH_readLE64(secret+80) ^ XXH_readLE64(secret+88); + h128.low64 = XXH64_avalanche(seed ^ bitflipl); + h128.high64 = XXH64_avalanche( seed ^ bitfliph); + return h128; + } } +} + +/* + * A bit slower than XXH3_mix16B, but handles multiply by zero better. + */ +XXH_FORCE_INLINE XXH128_hash_t +XXH128_mix32B(XXH128_hash_t acc, const xxh_u8* input_1, const xxh_u8* input_2, + const xxh_u8* secret, XXH64_hash_t seed) +{ + acc.low64 += XXH3_mix16B (input_1, secret+0, seed); + acc.low64 ^= XXH_readLE64(input_2) + XXH_readLE64(input_2 + 8); + acc.high64 += XXH3_mix16B (input_2, secret+16, seed); + acc.high64 ^= XXH_readLE64(input_1) + XXH_readLE64(input_1 + 8); + return acc; +} + + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_len_17to128_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(16 < len && len <= 128); + + { XXH128_hash_t acc; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + if (len > 32) { + if (len > 64) { + if (len > 96) { + acc = XXH128_mix32B(acc, input+48, input+len-64, secret+96, seed); + } + acc = XXH128_mix32B(acc, input+32, input+len-48, secret+64, seed); + } + acc = XXH128_mix32B(acc, input+16, input+len-32, secret+32, seed); + } + acc = XXH128_mix32B(acc, input, input+len-16, secret, seed); + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +XXH_NO_INLINE XXH128_hash_t +XXH3_len_129to240_128b(const xxh_u8* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH64_hash_t seed) +{ + XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize; + XXH_ASSERT(128 < len && len <= XXH3_MIDSIZE_MAX); + + { XXH128_hash_t acc; + int const nbRounds = (int)len / 32; + int i; + acc.low64 = len * XXH_PRIME64_1; + acc.high64 = 0; + for (i=0; i<4; i++) { + acc = XXH128_mix32B(acc, + input + (32 * i), + input + (32 * i) + 16, + secret + (32 * i), + seed); + } + acc.low64 = XXH3_avalanche(acc.low64); + acc.high64 = XXH3_avalanche(acc.high64); + XXH_ASSERT(nbRounds >= 4); + for (i=4 ; i < nbRounds; i++) { + acc = XXH128_mix32B(acc, + input + (32 * i), + input + (32 * i) + 16, + secret + XXH3_MIDSIZE_STARTOFFSET + (32 * (i - 4)), + seed); + } + /* last bytes */ + acc = XXH128_mix32B(acc, + input + len - 16, + input + len - 32, + secret + XXH3_SECRET_SIZE_MIN - XXH3_MIDSIZE_LASTOFFSET - 16, + 0ULL - seed); + + { XXH128_hash_t h128; + h128.low64 = acc.low64 + acc.high64; + h128.high64 = (acc.low64 * XXH_PRIME64_1) + + (acc.high64 * XXH_PRIME64_4) + + ((len - seed) * XXH_PRIME64_2); + h128.low64 = XXH3_avalanche(h128.low64); + h128.high64 = (XXH64_hash_t)0 - XXH3_avalanche(h128.high64); + return h128; + } + } +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_internal(const void* XXH_RESTRICT input, size_t len, + const xxh_u8* XXH_RESTRICT secret, size_t secretSize, + XXH3_f_accumulate_512 f_acc512, + XXH3_f_scrambleAcc f_scramble) +{ + XXH_ALIGN(XXH_ACC_ALIGN) xxh_u64 acc[XXH_ACC_NB] = XXH3_INIT_ACC; + + XXH3_hashLong_internal_loop(acc, (const xxh_u8*)input, len, secret, secretSize, f_acc512, f_scramble); + + /* converge into final hash */ + XXH_STATIC_ASSERT(sizeof(acc) == 64); + XXH_ASSERT(secretSize >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + { XXH128_hash_t h128; + h128.low64 = XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)len * XXH_PRIME64_1); + h128.high64 = XXH3_mergeAccs(acc, + secret + secretSize + - sizeof(acc) - XXH_SECRET_MERGEACCS_START, + ~((xxh_u64)len * XXH_PRIME64_2)); + return h128; + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH128_hash_t +XXH3_hashLong_128b_default(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; (void)secret; (void)secretLen; + return XXH3_hashLong_128b_internal(input, len, XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_accumulate_512, XXH3_scrambleAcc); +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSecret(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)seed64; + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, secretLen, + XXH3_accumulate_512, XXH3_scrambleAcc); +} + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed_internal(const void* XXH_RESTRICT input, size_t len, + XXH64_hash_t seed64, + XXH3_f_accumulate_512 f_acc512, + XXH3_f_scrambleAcc f_scramble, + XXH3_f_initCustomSecret f_initSec) +{ + if (seed64 == 0) + return XXH3_hashLong_128b_internal(input, len, + XXH3_kSecret, sizeof(XXH3_kSecret), + f_acc512, f_scramble); + { XXH_ALIGN(XXH_SEC_ALIGN) xxh_u8 secret[XXH_SECRET_DEFAULT_SIZE]; + f_initSec(secret, seed64); + return XXH3_hashLong_128b_internal(input, len, (const xxh_u8*)secret, sizeof(secret), + f_acc512, f_scramble); + } +} + +/* + * It's important for performance that XXH3_hashLong is not inlined. + */ +XXH_NO_INLINE XXH128_hash_t +XXH3_hashLong_128b_withSeed(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen) +{ + (void)secret; (void)secretLen; + return XXH3_hashLong_128b_withSeed_internal(input, len, seed64, + XXH3_accumulate_512, XXH3_scrambleAcc, XXH3_initCustomSecret); +} + +typedef XXH128_hash_t (*XXH3_hashLong128_f)(const void* XXH_RESTRICT, size_t, + XXH64_hash_t, const void* XXH_RESTRICT, size_t); + +XXH_FORCE_INLINE XXH128_hash_t +XXH3_128bits_internal(const void* input, size_t len, + XXH64_hash_t seed64, const void* XXH_RESTRICT secret, size_t secretLen, + XXH3_hashLong128_f f_hl128) +{ + XXH_ASSERT(secretLen >= XXH3_SECRET_SIZE_MIN); + /* + * If an action is to be taken if `secret` conditions are not respected, + * it should be done here. + * For now, it's a contract pre-condition. + * Adding a check and a branch here would cost performance at every hash. + */ + if (len <= 16) + return XXH3_len_0to16_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, seed64); + if (len <= 128) + return XXH3_len_17to128_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + if (len <= XXH3_MIDSIZE_MAX) + return XXH3_len_129to240_128b((const xxh_u8*)input, len, (const xxh_u8*)secret, secretLen, seed64); + return f_hl128(input, len, seed64, secret, secretLen); +} + + +/* === Public XXH128 API === */ + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits(const void* input, size_t len) +{ + return XXH3_128bits_internal(input, len, 0, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_default); +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSecret(const void* input, size_t len, const void* secret, size_t secretSize) +{ + return XXH3_128bits_internal(input, len, 0, + (const xxh_u8*)secret, secretSize, + XXH3_hashLong_128b_withSecret); +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH3_128bits_withSeed(const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_internal(input, len, seed, + XXH3_kSecret, sizeof(XXH3_kSecret), + XXH3_hashLong_128b_withSeed); +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128(const void* input, size_t len, XXH64_hash_t seed) +{ + return XXH3_128bits_withSeed(input, len, seed); +} + + +/* === XXH3 128-bit streaming === */ + +/* + * All the functions are actually the same as for 64-bit streaming variant. + * The only difference is the finalization routine. + */ + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset(XXH3_state_t* statePtr) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, XXH3_kSecret, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSecret(XXH3_state_t* statePtr, const void* secret, size_t secretSize) +{ + if (statePtr == NULL) return XXH_ERROR; + XXH3_reset_internal(statePtr, 0, secret, secretSize); + if (secret == NULL) return XXH_ERROR; + if (secretSize < XXH3_SECRET_SIZE_MIN) return XXH_ERROR; + return XXH_OK; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_reset_withSeed(XXH3_state_t* statePtr, XXH64_hash_t seed) +{ + if (statePtr == NULL) return XXH_ERROR; + if (seed==0) return XXH3_128bits_reset(statePtr); + if (seed != statePtr->seed) XXH3_initCustomSecret(statePtr->customSecret, seed); + XXH3_reset_internal(statePtr, seed, NULL, XXH_SECRET_DEFAULT_SIZE); + return XXH_OK; +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH_errorcode +XXH3_128bits_update(XXH3_state_t* state, const void* input, size_t len) +{ + return XXH3_update(state, (const xxh_u8*)input, len, + XXH3_accumulate_512, XXH3_scrambleAcc); +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH128_hash_t XXH3_128bits_digest (const XXH3_state_t* state) +{ + const unsigned char* const secret = (state->extSecret == NULL) ? state->customSecret : state->extSecret; + if (state->totalLen > XXH3_MIDSIZE_MAX) { + XXH_ALIGN(XXH_ACC_ALIGN) XXH64_hash_t acc[XXH_ACC_NB]; + XXH3_digest_long(acc, state, secret); + XXH_ASSERT(state->secretLimit + XXH_STRIPE_LEN >= sizeof(acc) + XXH_SECRET_MERGEACCS_START); + { XXH128_hash_t h128; + h128.low64 = XXH3_mergeAccs(acc, + secret + XXH_SECRET_MERGEACCS_START, + (xxh_u64)state->totalLen * XXH_PRIME64_1); + h128.high64 = XXH3_mergeAccs(acc, + secret + state->secretLimit + XXH_STRIPE_LEN + - sizeof(acc) - XXH_SECRET_MERGEACCS_START, + ~((xxh_u64)state->totalLen * XXH_PRIME64_2)); + return h128; + } + } + /* len <= XXH3_MIDSIZE_MAX : short code */ + if (state->seed) + return XXH3_128bits_withSeed(state->buffer, (size_t)state->totalLen, state->seed); + return XXH3_128bits_withSecret(state->buffer, (size_t)(state->totalLen), + secret, state->secretLimit + XXH_STRIPE_LEN); +} + +/* 128-bit utility functions */ + +#include /* memcmp, memcpy */ + +/* return : 1 is equal, 0 if different */ +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API int XXH128_isEqual(XXH128_hash_t h1, XXH128_hash_t h2) +{ + /* note : XXH128_hash_t is compact, it has no padding byte */ + return !(memcmp(&h1, &h2, sizeof(h1))); +} + +/* This prototype is compatible with stdlib's qsort(). + * return : >0 if *h128_1 > *h128_2 + * <0 if *h128_1 < *h128_2 + * =0 if *h128_1 == *h128_2 */ +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API int XXH128_cmp(const void* h128_1, const void* h128_2) +{ + XXH128_hash_t const h1 = *(const XXH128_hash_t*)h128_1; + XXH128_hash_t const h2 = *(const XXH128_hash_t*)h128_2; + int const hcmp = (h1.high64 > h2.high64) - (h2.high64 > h1.high64); + /* note : bets that, in most cases, hash values are different */ + if (hcmp) return hcmp; + return (h1.low64 > h2.low64) - (h2.low64 > h1.low64); +} + + +/*====== Canonical representation ======*/ +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API void +XXH128_canonicalFromHash(XXH128_canonical_t* dst, XXH128_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH128_canonical_t) == sizeof(XXH128_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) { + hash.high64 = XXH_swap64(hash.high64); + hash.low64 = XXH_swap64(hash.low64); + } + memcpy(dst, &hash.high64, sizeof(hash.high64)); + memcpy((char*)dst + sizeof(hash.high64), &hash.low64, sizeof(hash.low64)); +} + +/*! @ingroup xxh3_family */ +XXH_PUBLIC_API XXH128_hash_t +XXH128_hashFromCanonical(const XXH128_canonical_t* src) +{ + XXH128_hash_t h; + h.high64 = XXH_readBE64(src); + h.low64 = XXH_readBE64(src->digest + 8); + return h; +} + +/* Pop our optimization override from above */ +#if XXH_VECTOR == XXH_AVX2 /* AVX2 */ \ + && defined(__GNUC__) && !defined(__clang__) /* GCC, not Clang */ \ + && defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__) /* respect -O0 and -Os */ +# pragma GCC pop_options +#endif + +#endif /* XXH_NO_LONG_LONG */ + +/*! + * @} + */ +#endif /* XXH_IMPLEMENTATION */ + + +#if defined (__cplusplus) +} +#endif diff --git a/third_party/xxhash/xxhsum.1 b/third_party/xxhash/xxhsum.1 new file mode 100644 index 00000000000..dd17108f102 --- /dev/null +++ b/third_party/xxhash/xxhsum.1 @@ -0,0 +1,165 @@ +. +.TH "XXHSUM" "1" "July 2020" "xxhsum 0.7.4" "User Commands" +. +.SH "NAME" +\fBxxhsum\fR \- print or check xxHash non\-cryptographic checksums +. +.SH "SYNOPSIS" +\fBxxhsum [