diff options
author | thegeorg <thegeorg@yandex-team.com> | 2022-11-09 12:13:47 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2022-11-09 12:13:47 +0300 |
commit | 80f5c1d76c74f49e72bece723f9c1b7a25852e70 (patch) | |
tree | d00038bca499594f3b058936272dea3b69bf822e /contrib/libs | |
parent | 41fc4a8aaa393fbb516c9e0edb6ffe98ab7097e5 (diff) | |
download | ydb-80f5c1d76c74f49e72bece723f9c1b7a25852e70.tar.gz |
Update contrib/libs/grpc to 1.44.0
Diffstat (limited to 'contrib/libs')
327 files changed, 15812 insertions, 15967 deletions
diff --git a/contrib/libs/grpc/CMakeLists.txt b/contrib/libs/grpc/CMakeLists.txt index 6c2673734c..d6ad4ea417 100644 --- a/contrib/libs/grpc/CMakeLists.txt +++ b/contrib/libs/grpc/CMakeLists.txt @@ -48,6 +48,7 @@ target_link_libraries(contrib-libs-grpc PUBLIC abseil-cpp-tstring-y_absl-functional abseil-cpp-tstring-y_absl-hash abseil-cpp-tstring-y_absl-meta + abseil-cpp-tstring-y_absl-random abseil-cpp-tstring-y_absl-status abseil-cpp-tstring-y_absl-strings abseil-cpp-tstring-y_absl-synchronization @@ -93,7 +94,6 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy_registry.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/local_subchannel_pool.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/proxy_mapper_registry.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_event_engine.cc @@ -109,12 +109,10 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_registry.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_throttle.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/server_address.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel_pool_interface.cc @@ -131,10 +129,10 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/http/server/http_server_filter.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/max_age/max_age_filter.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/service_config/service_config.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/service_config/service_config_parser.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/binder_connector.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc @@ -178,7 +176,6 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/http2_settings.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/huffsyms.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc @@ -230,6 +227,7 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/clusters/aggregate/v3/cluster.upb.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/transport_sockets/tls/v3/cert.upb.c @@ -330,6 +328,7 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/listener/v3/udp_listener_config.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/route.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/route/v3/scoped_route.upbdefs.c @@ -337,6 +336,7 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/transport_sockets/tls/v3/cert.upbdefs.c @@ -368,6 +368,11 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/v3/range.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/type/v3/semantic_version.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/annotations.upbdefs.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.c + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/http.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/protobuf/any.upbdefs.c ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/protobuf/descriptor.upbdefs.c @@ -397,11 +402,19 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_api.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_certificate_provider.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_channel_stack_modifier.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_client.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_client_stats.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_cluster.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_common_types.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_http_fault_filter.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_http_filters.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_listener.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_resource_type.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_route_config.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_routing.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/ext/xds/xds_server_config_fetcher.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/address_utils/parse_address.cc @@ -419,12 +432,8 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/handshaker_registry.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/channel/status_util.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression_args.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/message_compress.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/stream_compression.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/config/core_configuration.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/stats.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/debug/stats_data.cc @@ -465,7 +474,6 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_posix.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/tmpfile_windows.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gpr/wrap_memcpy.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/arena.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/examine_stack.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/fork.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/gprpp/global_config_env.cc @@ -582,13 +590,20 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/profiling/basic_timers.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/profiling/stap_timers.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/promise/activity.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resolver/resolver.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resolver/resolver_registry.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resolver/server_address.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resource_quota/api.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resource_quota/arena.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resource_quota/memory_quota.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resource_quota/resource_quota.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resource_quota/thread_quota.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/resource_quota/trace.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/authorization/authorization_policy_provider_vtable.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/authorization/matchers.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/authorization/sdk_server_authz_filter.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/context/security_context.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/alts/alts_credentials.cc @@ -601,7 +616,6 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/credentials.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/credentials_metadata.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_request_signer.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.cc @@ -644,6 +658,8 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/transport/tsi_error.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/security/util/json_util.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/service_config/service_config.cc + ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/service_config/service_config_parser.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/slice/b64.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/slice/percent_encoding.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/slice/slice.cc @@ -653,7 +669,6 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/slice/slice_refcount.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/slice/slice_split.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/slice/slice_string_helpers.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/slice/static_slice.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/api_trace.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/builtins.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/surface/byte_buffer.cc @@ -679,13 +694,9 @@ target_sources(contrib-libs-grpc PRIVATE ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/byte_stream.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/connectivity_state.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/error_utils.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/metadata.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/pid_controller.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/static_metadata.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/status_conversion.cc - ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/status_metadata.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/transport.cc ${CMAKE_SOURCE_DIR}/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc diff --git a/contrib/libs/grpc/include/grpc/grpc_security.h b/contrib/libs/grpc/include/grpc/grpc_security.h index 48f5afe08c..414f221657 100644 --- a/contrib/libs/grpc/include/grpc/grpc_security.h +++ b/contrib/libs/grpc/include/grpc/grpc_security.h @@ -920,6 +920,16 @@ GRPCAPI void grpc_tls_credentials_options_set_identity_cert_name( GRPCAPI void grpc_tls_credentials_options_set_cert_request_type( grpc_tls_credentials_options* options, grpc_ssl_client_certificate_request_type type); +/** + * EXPERIMENTAL API - Subject to change + * + * If set, gRPC will read all hashed x.509 CRL files in the directory and + * enforce the CRL files on all TLS handshakes. Only supported for OpenSSL + * version > 1.1. + * It is used for experimental purpose for now and subject to change. + */ +GRPCAPI void grpc_tls_credentials_options_set_crl_directory( + grpc_tls_credentials_options* options, const char* crl_directory); /** * EXPERIMENTAL API - Subject to change diff --git a/contrib/libs/grpc/include/grpc/impl/codegen/compression_types.h b/contrib/libs/grpc/include/grpc/impl/codegen/compression_types.h index 129310eae8..35f49075d0 100644 --- a/contrib/libs/grpc/include/grpc/impl/codegen/compression_types.h +++ b/contrib/libs/grpc/include/grpc/impl/codegen/compression_types.h @@ -60,8 +60,6 @@ typedef enum { GRPC_COMPRESS_NONE = 0, GRPC_COMPRESS_DEFLATE, GRPC_COMPRESS_GZIP, - /* EXPERIMENTAL: Stream compression is currently experimental. */ - GRPC_COMPRESS_STREAM_GZIP, /* TODO(ctiller): snappy */ GRPC_COMPRESS_ALGORITHMS_COUNT } grpc_compression_algorithm; diff --git a/contrib/libs/grpc/include/grpc/impl/codegen/grpc_types.h b/contrib/libs/grpc/include/grpc/impl/codegen/grpc_types.h index 97ca3e4c2c..5354574858 100644 --- a/contrib/libs/grpc/include/grpc/impl/codegen/grpc_types.h +++ b/contrib/libs/grpc/include/grpc/impl/codegen/grpc_types.h @@ -445,6 +445,12 @@ typedef struct { gRPC authorization check. */ #define GRPC_ARG_AUTHORIZATION_POLICY_PROVIDER \ "grpc.authorization_policy_provider" +/** EXPERIMENTAL. Updates to a server's configuration from a config fetcher (for + * example, listener updates from xDS) cause all older connections to be + * gracefully shut down (i.e., "drained") with a grace period configured by this + * channel arg. Int valued, milliseconds. Defaults to 10 minutes.*/ +#define GRPC_ARG_SERVER_CONFIG_CHANGE_DRAIN_GRACE_TIME_MS \ + "grpc.experimental.server_config_change_drain_grace_time_ms" /** \} */ /** Result of a grpc call. If the caller satisfies the prerequisites of a diff --git a/contrib/libs/grpc/include/grpcpp/create_channel_binder.h b/contrib/libs/grpc/include/grpcpp/create_channel_binder.h index 6d6dfb22d6..9b68e3a8e8 100644 --- a/contrib/libs/grpc/include/grpcpp/create_channel_binder.h +++ b/contrib/libs/grpc/include/grpcpp/create_channel_binder.h @@ -78,6 +78,15 @@ std::shared_ptr<grpc::Channel> CreateCustomBinderChannel( /// Returns true when the initialization is successful. bool InitializeBinderChannelJavaClass(void* jni_env_void); +/// EXPERIMENTAL Alternative version of `InitializeBinderChannelJavaClass(void* +/// jni_env_void)`. This version used a user-specified function to find the +/// required internal Java class. When a class is found, the `class_finder` +/// function should return a local reference to the class (jclass type). The +/// returned jclass will then be used to create global reference for gRPC to use +/// it later. After that, gRPC will DeleteLocalRef the returned local reference. +bool InitializeBinderChannelJavaClass( + void* jni_env_void, std::function<void*(TString)> class_finder); + } // namespace experimental } // namespace grpc diff --git a/contrib/libs/grpc/include/grpcpp/impl/codegen/client_context.h b/contrib/libs/grpc/include/grpcpp/impl/codegen/client_context.h index d8204fafde..f450b0e5ce 100644 --- a/contrib/libs/grpc/include/grpcpp/impl/codegen/client_context.h +++ b/contrib/libs/grpc/include/grpcpp/impl/codegen/client_context.h @@ -288,7 +288,7 @@ class ClientContext { /// with the possibility of receiving a cached response. void set_cacheable(bool cacheable) { cacheable_ = cacheable; } - /// EXPERIMENTAL: Trigger wait-for-ready or not on this request. + /// Trigger wait-for-ready or not on this request. /// See https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md. /// If set, if an RPC is made when a channel's connectivity state is /// TRANSIENT_FAILURE or CONNECTING, the call will not "fail fast", diff --git a/contrib/libs/grpc/src/compiler/objective_c_generator_helpers.h b/contrib/libs/grpc/src/compiler/objective_c_generator_helpers.h index cc8aa8d124..ce1e47aeaf 100644 --- a/contrib/libs/grpc/src/compiler/objective_c_generator_helpers.h +++ b/contrib/libs/grpc/src/compiler/objective_c_generator_helpers.h @@ -36,10 +36,30 @@ inline TString MessageHeaderName(const FileDescriptor* file) { return google::protobuf::compiler::objectivec::FilePath(file) + ".pbobjc.h"; } -inline TString ServiceClassName(const ServiceDescriptor* service) { +inline bool AsciiIsUpper(char c) { return c >= 'A' && c <= 'Z'; } + +inline ::TString ServiceClassName(const ServiceDescriptor* service) { const FileDescriptor* file = service->file(); - TString prefix = google::protobuf::compiler::objectivec::FileClassPrefix(file); - return prefix + service->name(); + ::TString prefix = + google::protobuf::compiler::objectivec::FileClassPrefix(file); + ::TString class_name = service->name(); + // We add the prefix in the cases where the string is missing a prefix. + // We define "missing a prefix" as where 'input': + // a) Doesn't start with the prefix or + // b) Isn't equivalent to the prefix or + // c) Has the prefix, but the letter after the prefix is lowercase + // This is the same semantics as the Objective-C protoc. + // https://github.com/protocolbuffers/protobuf/blob/c160ae52a91ca4c76936531d68cc846f8230dbb1/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc#L389 + if (class_name.rfind(prefix, 0) == 0) { + if (class_name.length() == prefix.length() || + !AsciiIsUpper(class_name[prefix.length()])) { + return prefix + class_name; + } else { + return class_name; + } + } else { + return prefix + class_name; + } } inline ::TString LocalImport(const ::TString& import) { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.h index 64f8ef6157..70efe6b7f9 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.h @@ -22,7 +22,7 @@ #include <grpc/slice.h> #include "src/core/ext/filters/client_channel/lb_policy.h" -#include "src/core/lib/gprpp/arena.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/slice/slice.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc index 5433d5cc23..1ab329b333 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc @@ -48,13 +48,10 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/local_subchannel_pool.h" #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_filter.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/ext/filters/deadline/deadline_filter.h" -#include "src/core/ext/service_config/service_config.h" -#include "src/core/ext/service_config/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/connected_channel.h" @@ -65,15 +62,15 @@ #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/service_config/service_config.h" +#include "src/core/lib/service_config/service_config_call_data.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.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" // // Client channel filter @@ -417,16 +414,11 @@ class ClientChannel::ResolverResultHandler : public Resolver::ResultHandler { GRPC_CHANNEL_STACK_UNREF(chand_->owning_stack_, "ResolverResultHandler"); } - void ReturnResult(Resolver::Result result) override + void ReportResult(Resolver::Result result) override Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { chand_->OnResolverResultChangedLocked(std::move(result)); } - void ReturnError(grpc_error_handle error) override - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(chand_->work_serializer_) { - chand_->OnResolverErrorLocked(error); - } - private: ClientChannel* chand_; }; @@ -1122,7 +1114,6 @@ ClientChannel::~ClientChannel() { } DestroyResolverAndLbPolicyLocked(); grpc_channel_args_destroy(channel_args_); - GRPC_ERROR_UNREF(resolver_transient_failure_error_); // Stop backup polling. grpc_client_channel_stop_backup_polling(interested_parties_); grpc_pollset_set_destroy(interested_parties_); @@ -1203,26 +1194,29 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { // // We track a list of strings to eventually be concatenated and traced. y_absl::InlinedVector<const char*, 3> trace_strings; - if (result.addresses.empty() && previous_resolution_contained_addresses_) { + const bool resolution_contains_addresses = + result.addresses.ok() && !result.addresses->empty(); + if (!resolution_contains_addresses && + previous_resolution_contained_addresses_) { trace_strings.push_back("Address list became empty"); - } else if (!result.addresses.empty() && + } else if (resolution_contains_addresses && !previous_resolution_contained_addresses_) { trace_strings.push_back("Address list became non-empty"); } - previous_resolution_contained_addresses_ = !result.addresses.empty(); + previous_resolution_contained_addresses_ = resolution_contains_addresses; TString service_config_error_string_storage; - if (result.service_config_error != GRPC_ERROR_NONE) { + if (!result.service_config.ok()) { service_config_error_string_storage = - grpc_error_std_string(result.service_config_error); + result.service_config.status().ToString(); trace_strings.push_back(service_config_error_string_storage.c_str()); } // Choose the service config. RefCountedPtr<ServiceConfig> service_config; RefCountedPtr<ConfigSelector> config_selector; - if (result.service_config_error != GRPC_ERROR_NONE) { + if (!result.service_config.ok()) { 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_std_string(result.service_config_error).c_str()); + this, result.service_config.status().ToString().c_str()); } // If the service config was invalid, then fallback to the // previously returned service config. @@ -1236,13 +1230,13 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { service_config = saved_service_config_; config_selector = saved_config_selector_; } else { - // We received an invalid service config and we don't have a + // We received a service config error and we don't have a // previous service config to fall back to. Put the channel into // TRANSIENT_FAILURE. - OnResolverErrorLocked(GRPC_ERROR_REF(result.service_config_error)); + OnResolverErrorLocked(result.service_config.status()); trace_strings.push_back("no valid service config"); } - } else if (result.service_config == nullptr) { + } else if (*result.service_config == nullptr) { // Resolver did not return any service config. if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, @@ -1253,9 +1247,12 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { service_config = default_service_config_; } else { // Use ServiceConfig and ConfigSelector returned by resolver. - service_config = result.service_config; + service_config = std::move(*result.service_config); config_selector = ConfigSelector::GetFromChannelArgs(*result.args); } + // Note: The only case in which service_config is null here is if the resolver + // returned a service config error and we don't have a previous service + // config to fall back to. if (service_config != nullptr) { // Extract global config for client channel. const internal::ClientChannelGlobalParsedConfig* parsed_service_config = @@ -1307,28 +1304,21 @@ void ClientChannel::OnResolverResultChangedLocked(Resolver::Result result) { } } -void ClientChannel::OnResolverErrorLocked(grpc_error_handle error) { - if (resolver_ == nullptr) { - GRPC_ERROR_UNREF(error); - return; - } +void ClientChannel::OnResolverErrorLocked(y_absl::Status status) { + if (resolver_ == nullptr) return; if (GRPC_TRACE_FLAG_ENABLED(grpc_client_channel_routing_trace)) { gpr_log(GPR_INFO, "chand=%p: resolver transient failure: %s", this, - grpc_error_std_string(error).c_str()); + status.ToString().c_str()); } // If we already have an LB policy from a previous resolution // result, then we continue to let it set the connectivity state. // Otherwise, we go into TRANSIENT_FAILURE. if (lb_policy_ == nullptr) { - grpc_error_handle state_error = - GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( - "Resolver transient failure", &error, 1); - y_absl::Status status = grpc_error_to_absl_status(state_error); + grpc_error_handle error = absl_status_to_grpc_error(status); { MutexLock lock(&resolution_mu_); // Update resolver transient failure. - GRPC_ERROR_UNREF(resolver_transient_failure_error_); - resolver_transient_failure_error_ = state_error; + resolver_transient_failure_error_ = status; // Process calls that were queued waiting for the resolver result. for (ResolverQueuedCall* call = resolver_queued_calls_; call != nullptr; call = call->next) { @@ -1340,12 +1330,12 @@ void ClientChannel::OnResolverErrorLocked(grpc_error_handle error) { } } } + GRPC_ERROR_UNREF(error); // Update connectivity state. UpdateStateAndPickerLocked( GRPC_CHANNEL_TRANSIENT_FAILURE, status, "resolver failure", y_absl::make_unique<LoadBalancingPolicy::TransientFailurePicker>(status)); } - GRPC_ERROR_UNREF(error); } void ClientChannel::CreateOrUpdateLbPolicyLocked( @@ -1356,6 +1346,7 @@ void ClientChannel::CreateOrUpdateLbPolicyLocked( LoadBalancingPolicy::UpdateArgs update_args; update_args.addresses = std::move(result.addresses); update_args.config = std::move(lb_policy_config); + update_args.resolution_note = std::move(result.resolution_note); // Add health check service name to channel args. y_absl::InlinedVector<grpc_arg, 1> args_to_add; if (health_check_service_name.has_value()) { @@ -1496,8 +1487,7 @@ void ClientChannel::UpdateServiceConfigInDataPlaneLocked() { // after releasing the lock to keep the critical section small. { MutexLock lock(&resolution_mu_); - GRPC_ERROR_UNREF(resolver_transient_failure_error_); - resolver_transient_failure_error_ = GRPC_ERROR_NONE; + resolver_transient_failure_error_ = y_absl::OkStatus(); // Update service config. received_service_config_data_ = true; // Old values will be unreffed after lock is released. @@ -2353,12 +2343,11 @@ bool ClientChannel::CallData::CheckResolutionLocked(grpc_call_element* elem, 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) { + y_absl::Status resolver_error = chand->resolver_transient_failure_error_; + if (!resolver_error.ok() && (send_initial_metadata_flags & + GRPC_INITIAL_METADATA_WAIT_FOR_READY) == 0) { MaybeRemoveCallFromResolverQueuedCallsLocked(elem); - *error = GRPC_ERROR_REF(resolver_error); + *error = absl_status_to_grpc_error(resolver_error); return true; } // Either the resolver has not yet returned a result, or it has @@ -2414,16 +2403,25 @@ void ClientChannel::CallData::CreateDynamicCall(grpc_call_element* elem) { class ClientChannel::LoadBalancedCall::Metadata : public LoadBalancingPolicy::MetadataInterface { public: - Metadata(LoadBalancedCall* lb_call, grpc_metadata_batch* batch) - : lb_call_(lb_call), batch_(batch) {} + explicit Metadata(grpc_metadata_batch* batch) : batch_(batch) {} void Add(y_absl::string_view key, y_absl::string_view value) override { - grpc_linked_mdelem* linked_mdelem = static_cast<grpc_linked_mdelem*>( - lb_call_->arena_->Alloc(sizeof(grpc_linked_mdelem))); - linked_mdelem->md = grpc_mdelem_from_slices( - ExternallyManagedSlice(key.data(), key.size()), - ExternallyManagedSlice(value.data(), value.size())); - GPR_ASSERT(batch_->LinkTail(linked_mdelem) == GRPC_ERROR_NONE); + // Gross, egregious hack to support legacy grpclb behavior. + // TODO(ctiller): Use a promise context for this once that plumbing is done. + if (key == GrpcLbClientStatsMetadata::key()) { + batch_->Set( + GrpcLbClientStatsMetadata(), + const_cast<GrpcLbClientStats*>( + reinterpret_cast<const GrpcLbClientStats*>(value.data()))); + return; + } + batch_->Append(key, Slice::FromStaticString(value), + [key](y_absl::string_view error, const Slice& value) { + gpr_log(GPR_ERROR, "%s", + y_absl::StrCat(error, " key:", key, + " value:", value.as_string_view()) + .c_str()); + }); } std::vector<std::pair<TString, TString>> TestOnlyCopyToVector() @@ -2435,18 +2433,15 @@ class ClientChannel::LoadBalancedCall::Metadata y_absl::optional<y_absl::string_view> Lookup(y_absl::string_view key, TString* buffer) const override { - return batch_->GetValue(key, buffer); + return batch_->GetStringValue(key, buffer); } private: class Encoder { public: - void Encode(grpc_mdelem md) { - auto key = StringViewFromSlice(GRPC_MDKEY(md)); - if (key != ":path") { - out_.emplace_back(TString(key), - TString(StringViewFromSlice(GRPC_MDVALUE(md)))); - } + void Encode(const Slice& key, const Slice& value) { + out_.emplace_back(TString(key.as_string_view()), + TString(value.as_string_view())); } template <class Which> @@ -2457,6 +2452,9 @@ class ClientChannel::LoadBalancedCall::Metadata } void Encode(GrpcTimeoutMetadata, grpc_millis) {} + void Encode(HttpPathMetadata, const Slice&) {} + void Encode(HttpMethodMetadata, + const typename HttpMethodMetadata::ValueType&) {} std::vector<std::pair<TString, TString>> Take() { return std::move(out_); @@ -2466,7 +2464,6 @@ class ClientChannel::LoadBalancedCall::Metadata std::vector<std::pair<TString, TString>> out_; }; - LoadBalancedCall* lb_call_; grpc_metadata_batch* batch_; }; @@ -2558,7 +2555,6 @@ ClientChannel::LoadBalancedCall::LoadBalancedCall( GetCallAttemptTracer(args.context, is_transparent_retry)) {} ClientChannel::LoadBalancedCall::~LoadBalancedCall() { - grpc_slice_unref_internal(path_); GRPC_ERROR_UNREF(cancel_error_); GRPC_ERROR_UNREF(failure_error_); if (backend_metric_data_ != nullptr) { @@ -2877,10 +2873,8 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady( } else { // Get status from headers. const auto& md = *self->recv_trailing_metadata_; - const auto& fields = md.legacy_index()->named; - GPR_ASSERT(fields.grpc_status != nullptr); grpc_status_code code = - grpc_get_status_code_from_metadata(fields.grpc_status->md); + md.get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN); if (code != GRPC_STATUS_OK) { y_absl::string_view message; if (const auto* grpc_message = md.get_pointer(GrpcMessageMetadata())) { @@ -2898,7 +2892,7 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady( // If the LB policy requested a callback for trailing metadata, invoke // the callback. if (self->lb_subchannel_call_tracker_ != nullptr) { - Metadata trailing_metadata(self, self->recv_trailing_metadata_); + Metadata trailing_metadata(self->recv_trailing_metadata_); BackendMetricAccessor backend_metric_accessor(self); LoadBalancingPolicy::SubchannelCallTrackerInterface::FinishArgs args = { status, &trailing_metadata, &backend_metric_accessor}; @@ -2919,7 +2913,7 @@ void ClientChannel::LoadBalancedCall::RecvTrailingMetadataReady( void ClientChannel::LoadBalancedCall::CreateSubchannelCall() { SubchannelCall::Args call_args = { - std::move(connected_subchannel_), pollent_, path_, /*start_time=*/0, + std::move(connected_subchannel_), pollent_, path_.Ref(), /*start_time=*/0, deadline_, arena_, // TODO(roth): When we implement hedging support, we will probably // need to use a separate call context for each subchannel call. @@ -3063,10 +3057,10 @@ bool ClientChannel::LoadBalancedCall::PickSubchannelLocked( send_initial_metadata.send_initial_metadata_flags; // Perform LB pick. LoadBalancingPolicy::PickArgs pick_args; - pick_args.path = StringViewFromSlice(path_); + pick_args.path = path_.as_string_view(); LbCallState lb_call_state(this); pick_args.call_state = &lb_call_state; - Metadata initial_metadata(this, initial_metadata_batch); + Metadata initial_metadata(initial_metadata_batch); pick_args.initial_metadata = &initial_metadata; auto result = chand_->picker_->Pick(pick_args); return HandlePickResult<bool>( diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h index 5289ac24bc..5a4d80fd5f 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h @@ -33,14 +33,10 @@ #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/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/subchannel.h" #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h" -#include "src/core/ext/service_config/service_config.h" -#include "src/core/ext/service_config/service_config_call_data.h" -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/channel/call_tracer.h" #include "src/core/lib/channel/context.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" @@ -48,6 +44,10 @@ #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/resolver/resolver.h" +#include "src/core/lib/service_config/service_config.h" +#include "src/core/lib/service_config/service_config_call_data.h" +#include "src/core/lib/service_config/service_config_parser.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" @@ -216,7 +216,7 @@ class ClientChannel { void OnResolverResultChangedLocked(Resolver::Result result) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); - void OnResolverErrorLocked(grpc_error_handle error) + void OnResolverErrorLocked(y_absl::Status status) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_); void CreateOrUpdateLbPolicyLocked( @@ -288,8 +288,8 @@ class ClientChannel { ResolverQueuedCall* resolver_queued_calls_ Y_ABSL_GUARDED_BY(resolution_mu_) = nullptr; // Data from service config. - grpc_error_handle resolver_transient_failure_error_ - Y_ABSL_GUARDED_BY(resolution_mu_) = GRPC_ERROR_NONE; + y_absl::Status resolver_transient_failure_error_ + Y_ABSL_GUARDED_BY(resolution_mu_); bool received_service_config_data_ Y_ABSL_GUARDED_BY(resolution_mu_) = false; RefCountedPtr<ServiceConfig> service_config_ Y_ABSL_GUARDED_BY(resolution_mu_); RefCountedPtr<ConfigSelector> config_selector_ @@ -447,7 +447,7 @@ class ClientChannel::LoadBalancedCall // 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. + Slice path_; // Request path. grpc_millis deadline_; Arena* arena_; grpc_call_stack* owning_call_; diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_plugin.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_plugin.cc index 31a084cd40..abd225bcd5 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_plugin.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_plugin.cc @@ -32,11 +32,11 @@ #include "src/core/ext/filters/client_channel/http_proxy.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #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/lib/config/core_configuration.h" +#include "src/core/lib/resolver/resolver_registry.h" void grpc_client_channel_init(void) { grpc_core::internal::ClientChannelServiceConfigParser::Register(); diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h index 9dfd9c66c5..b31fcd3442 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h @@ -27,13 +27,13 @@ #include <grpc/grpc.h> -#include "src/core/ext/service_config/service_config.h" -#include "src/core/ext/service_config/service_config_call_data.h" -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/gprpp/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/resource_quota/arena.h" +#include "src/core/lib/service_config/service_config.h" +#include "src/core/lib/service_config/service_config_call_data.h" +#include "src/core/lib/service_config/service_config_parser.h" #include "src/core/lib/transport/metadata_batch.h" // Channel arg key for ConfigSelector. diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/dynamic_filters.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/dynamic_filters.h index 08a7f4985e..03211ec108 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/dynamic_filters.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/dynamic_filters.h @@ -23,10 +23,10 @@ #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/ref_counted.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/resource_quota/arena.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.cc index c6b07bcf92..6185393032 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.cc @@ -25,11 +25,13 @@ #include "upb/upb.hpp" +#include <grpc/status.h> + #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/resource_quota/api.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/error_utils.h" -#include "src/core/lib/transport/status_metadata.h" #include "src/proto/grpc/health/v1/health.upb.h" #define HEALTH_CHECK_INITIAL_CONNECT_BACKOFF_SECONDS 1 @@ -59,6 +61,10 @@ HealthCheckClient::HealthCheckClient( connected_subchannel_(std::move(connected_subchannel)), interested_parties_(interested_parties), channelz_node_(std::move(channelz_node)), + call_allocator_( + ResourceQuotaFromChannelArgs(connected_subchannel_->args()) + ->memory_quota() + ->CreateMemoryAllocator(service_name_)), watcher_(std::move(watcher)), retry_backoff_( BackOff::Options() @@ -253,7 +259,8 @@ HealthCheckClient::CallState::CallState( : health_check_client_(std::move(health_check_client)), pollent_(grpc_polling_entity_create_from_pollset_set(interested_parties)), arena_(Arena::Create(health_check_client_->connected_subchannel_ - ->GetInitialCallSizeEstimate())), + ->GetInitialCallSizeEstimate(), + &health_check_client_->call_allocator_)), payload_(context_), send_initial_metadata_(arena_), send_trailing_metadata_(arena_), @@ -287,7 +294,7 @@ void HealthCheckClient::CallState::StartCall() { SubchannelCall::Args args = { health_check_client_->connected_subchannel_, &pollent_, - GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH, + Slice::FromStaticString("/grpc.health.v1.Health/Watch"), gpr_get_cycle_counter(), // start_time GRPC_MILLIS_INF_FUTURE, // deadline arena_, @@ -319,12 +326,9 @@ void HealthCheckClient::CallState::StartCall() { batch_.on_complete = GRPC_CLOSURE_INIT(&on_complete_, OnComplete, this, grpc_schedule_on_exec_ctx); // Add send_initial_metadata op. - error = grpc_metadata_batch_add_head( - &send_initial_metadata_, &path_metadata_storage_, - grpc_mdelem_from_slices( - GRPC_MDSTR_PATH, - GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH), - GRPC_BATCH_PATH); + send_initial_metadata_.Set( + HttpPathMetadata(), + Slice::FromStaticString("/grpc.health.v1.Health/Watch")); GPR_ASSERT(error == GRPC_ERROR_NONE); payload_.send_initial_metadata.send_initial_metadata = &send_initial_metadata_; @@ -553,15 +557,13 @@ void HealthCheckClient::CallState::RecvTrailingMetadataReady( GRPC_CALL_COMBINER_STOP(&self->call_combiner_, "recv_trailing_metadata_ready"); // Get call status. - grpc_status_code status = GRPC_STATUS_UNKNOWN; + grpc_status_code status = + self->recv_trailing_metadata_.get(GrpcStatusMetadata()) + .value_or(GRPC_STATUS_UNKNOWN); if (error != GRPC_ERROR_NONE) { grpc_error_get_status(error, GRPC_MILLIS_INF_FUTURE, &status, nullptr /* slice */, nullptr /* http_error */, nullptr /* error_string */); - } else if (self->recv_trailing_metadata_.legacy_index()->named.grpc_status != - nullptr) { - status = grpc_get_status_code_from_metadata( - self->recv_trailing_metadata_.legacy_index()->named.grpc_status->md); } if (GRPC_TRACE_FLAG_ENABLED(grpc_health_check_client_trace)) { gpr_log(GPR_INFO, diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.h index d70c02406b..25ead3d8c3 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.h @@ -29,7 +29,6 @@ #include "src/core/ext/filters/client_channel/client_channel_channelz.h" #include "src/core/ext/filters/client_channel/subchannel.h" #include "src/core/lib/backoff/backoff.h" -#include "src/core/lib/gprpp/arena.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" @@ -37,6 +36,7 @@ #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" @@ -60,7 +60,7 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> { class CallState : public Orphanable { public: CallState(RefCountedPtr<HealthCheckClient> health_check_client, - grpc_pollset_set* interested_parties_); + grpc_pollset_set* interested_parties); ~CallState() override; void Orphan() override; @@ -111,7 +111,6 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> { // send_initial_metadata grpc_metadata_batch send_initial_metadata_; - grpc_linked_mdelem path_metadata_storage_; // send_message ManualConstructor<SliceBufferByteStream> send_message_; @@ -155,6 +154,7 @@ class HealthCheckClient : public InternallyRefCounted<HealthCheckClient> { RefCountedPtr<ConnectedSubchannel> connected_subchannel_; grpc_pollset_set* interested_parties_; // Do not own. RefCountedPtr<channelz::SubchannelNode> channelz_node_; + MemoryAllocator call_allocator_; Mutex mu_; RefCountedPtr<ConnectivityStateWatcherInterface> watcher_ diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/http_connect_handshaker.cc index 3b963f0fe9..de6ed16de3 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/http_connect_handshaker.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/http_connect_handshaker.cc @@ -30,7 +30,6 @@ #include <grpc/support/string_util.h> #include "src/core/ext/filters/client_channel/client_channel.h" -#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/channel/handshaker_registry.h" @@ -39,6 +38,7 @@ #include "src/core/lib/gprpp/sync.h" #include "src/core/lib/http/format_request.h" #include "src/core/lib/http/parser.h" +#include "src/core/lib/resolver/resolver_registry.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/uri/uri_parser.h" diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.cc index 44363b4ac9..e3da7698d7 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.cc @@ -54,27 +54,27 @@ void LoadBalancingPolicy::Orphan() { // LoadBalancingPolicy::UpdateArgs // -LoadBalancingPolicy::UpdateArgs::UpdateArgs(const UpdateArgs& other) { - addresses = other.addresses; - config = other.config; - args = grpc_channel_args_copy(other.args); -} - -LoadBalancingPolicy::UpdateArgs::UpdateArgs(UpdateArgs&& other) noexcept { - addresses = std::move(other.addresses); - config = std::move(other.config); - // TODO(roth): Use std::move() once channel args is converted to C++. - args = other.args; +LoadBalancingPolicy::UpdateArgs::UpdateArgs(const UpdateArgs& other) + : addresses(other.addresses), + config(other.config), + resolution_note(other.resolution_note), + args(grpc_channel_args_copy(other.args)) {} + +LoadBalancingPolicy::UpdateArgs::UpdateArgs(UpdateArgs&& other) noexcept + : addresses(std::move(other.addresses)), + config(std::move(other.config)), + resolution_note(std::move(other.resolution_note)), + // TODO(roth): Use std::move() once channel args is converted to C++. + args(other.args) { other.args = nullptr; } LoadBalancingPolicy::UpdateArgs& LoadBalancingPolicy::UpdateArgs::operator=( const UpdateArgs& other) { - if (&other == this) { - return *this; - } + if (&other == this) return *this; addresses = other.addresses; config = other.config; + resolution_note = other.resolution_note; grpc_channel_args_destroy(args); args = grpc_channel_args_copy(other.args); return *this; @@ -84,6 +84,7 @@ LoadBalancingPolicy::UpdateArgs& LoadBalancingPolicy::UpdateArgs::operator=( UpdateArgs&& other) noexcept { addresses = std::move(other.addresses); config = std::move(other.config); + resolution_note = std::move(other.resolution_note); // TODO(roth): Use std::move() once channel args is converted to C++. grpc_channel_args_destroy(args); args = other.args; diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.h index e88ad554f3..864e329d27 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.h @@ -23,15 +23,16 @@ #include <iterator> #include "y_absl/status/status.h" +#include "y_absl/status/statusor.h" #include "y_absl/strings/string_view.h" #include "y_absl/types/variant.h" -#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/filters/client_channel/subchannel_interface.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/work_serializer.h" +#include "src/core/lib/resolver/server_address.h" #include "src/core/lib/transport/connectivity_state.h" namespace grpc_core { @@ -325,8 +326,20 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> { /// Data passed to the UpdateLocked() method when new addresses and /// config are available. struct UpdateArgs { - ServerAddressList addresses; + /// A list of addresses, or an error indicating a failure to obtain the + /// list of addresses. + y_absl::StatusOr<ServerAddressList> addresses; + /// The LB policy config. RefCountedPtr<Config> config; + /// A human-readable note providing context about the name resolution that + /// provided this update. LB policies may wish to include this message + /// in RPC failure status messages. For example, if the update has an + /// empty list of addresses, this message might say "no DNS entries + /// found for <name>". + TString resolution_note; + + // TODO(roth): Before making this a public API, find a better + // abstraction for representing channel args. const grpc_channel_args* args = nullptr; // TODO(roth): Remove everything below once channel args is @@ -368,6 +381,9 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> { /// Updates the policy with new data from the resolver. Will be invoked /// immediately after LB policy is constructed, and then again whenever /// the resolver returns a new result. + // TODO(roth): Change this to return some indication as to whether the + // update has been accepted, so that we can indicate to the resolver + // whether it should go into backoff to retry the resolution. virtual void UpdateLocked(UpdateArgs) = 0; // NOLINT /// Tries to enter a READY connectivity state. @@ -438,4 +454,4 @@ class LoadBalancingPolicy : public InternallyRefCounted<LoadBalancingPolicy> { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H */ +#endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_H diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc index 7f2ca80148..9a6d966ff2 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc @@ -69,10 +69,11 @@ MakeHierarchicalPathAttribute(std::vector<TString> path) { return y_absl::make_unique<HierarchicalPathAttribute>(std::move(path)); } -HierarchicalAddressMap MakeHierarchicalAddressMap( - const ServerAddressList& addresses) { +y_absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap( + const y_absl::StatusOr<ServerAddressList>& addresses) { + if (!addresses.ok()) return addresses.status(); HierarchicalAddressMap result; - for (const ServerAddress& address : addresses) { + for (const ServerAddress& address : *addresses) { const HierarchicalPathAttribute* path_attribute = static_cast<const HierarchicalPathAttribute*>( address.GetAttribute(kHierarchicalPathAttributeKey)); diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.h index 79c970ce55..cac9bbf09a 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.h @@ -23,7 +23,9 @@ #include <util/generic/string.h> #include <vector> -#include "src/core/ext/filters/client_channel/server_address.h" +#include "y_absl/status/statusor.h" + +#include "src/core/lib/resolver/server_address.h" // The resolver returns a flat list of addresses. When a hierarchy of // LB policies is in use, each leaf of the hierarchy will need a @@ -92,10 +94,9 @@ MakeHierarchicalPathAttribute(std::vector<TString> path); using HierarchicalAddressMap = std::map<TString, ServerAddressList>; // Splits up the addresses into a separate list for each child. -HierarchicalAddressMap MakeHierarchicalAddressMap( - const ServerAddressList& addresses); +y_absl::StatusOr<HierarchicalAddressMap> MakeHierarchicalAddressMap( + const y_absl::StatusOr<ServerAddressList>& addresses); } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_ADDRESS_FILTERING_H \ - */ +#endif // GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_ADDRESS_FILTERING_H diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc index a3cf12ac7c..fe64441f03 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc @@ -102,14 +102,10 @@ static void clr_start_transport_stream_op_batch( if (batch->send_initial_metadata) { // Grab client stats object from metadata. auto client_stats_md = - batch->payload->send_initial_metadata.send_initial_metadata->Remove( - grpc_slice_from_static_string( - grpc_core::kGrpcLbClientStatsMetadataKey)); + batch->payload->send_initial_metadata.send_initial_metadata->Take( + grpc_core::GrpcLbClientStatsMetadata()); if (client_stats_md.has_value()) { - grpc_core::GrpcLbClientStats* client_stats = - const_cast<grpc_core::GrpcLbClientStats*>( - reinterpret_cast<const grpc_core::GrpcLbClientStats*>( - GRPC_SLICE_START_PTR(*client_stats_md))); + grpc_core::GrpcLbClientStats* client_stats = *client_stats_md; if (client_stats != nullptr) { calld->client_stats.reset(client_stats); // Intercept completion. diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc index 113d764252..b861f5de08 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc @@ -80,7 +80,6 @@ #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #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" @@ -96,11 +95,11 @@ #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/resolver/server_address.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/static_metadata.h" #define GRPC_GRPCLB_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_GRPCLB_RECONNECT_BACKOFF_MULTIPLIER 1.6 @@ -113,9 +112,6 @@ namespace grpc_core { TraceFlag grpc_lb_glb_trace(false, "glb"); -const char kGrpcLbClientStatsMetadataKey[] = "grpclb_client_stats"; -const char kGrpcLbLbTokenMetadataKey[] = "lb-token"; - const char kGrpcLbAddressAttributeKey[] = "grpclb"; namespace { @@ -401,10 +397,7 @@ class GrpcLb : public LoadBalancingPolicy { void ShutdownLocked() override; // Helper functions used in UpdateLocked(). - void ProcessAddressesAndChannelArgsLocked(const ServerAddressList& addresses, - const grpc_channel_args& args); - static ServerAddressList AddNullLbTokenToAddresses( - const ServerAddressList& addresses); + void UpdateBalancerChannelLocked(const grpc_channel_args& args); void CancelBalancerChannelConnectivityWatchLocked(); @@ -473,7 +466,10 @@ class GrpcLb : public LoadBalancingPolicy { // Whether we're in fallback mode. bool fallback_mode_ = false; // The backend addresses from the resolver. - ServerAddressList fallback_backend_addresses_; + y_absl::StatusOr<ServerAddressList> fallback_backend_addresses_; + // The last resolution note from our parent. + // To be passed to child policy when fallback_backend_addresses_ is empty. + TString resolution_note_; // State for fallback-at-startup checks. // Timeout after startup after which we will go into fallback mode if // we have not received a serverlist from the balancer. @@ -653,7 +649,7 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) { // a string and rely on the client_load_reporting filter to know // how to interpret it. args.initial_metadata->Add( - kGrpcLbClientStatsMetadataKey, + GrpcLbClientStatsMetadata::key(), y_absl::string_view(reinterpret_cast<const char*>(client_stats), 0)); // Update calls-started. client_stats->AddCallStarted(); @@ -666,7 +662,7 @@ GrpcLb::PickResult GrpcLb::Picker::Pick(PickArgs args) { char* lb_token = static_cast<char*>( args.call_state->Alloc(subchannel_wrapper->lb_token().size() + 1)); strcpy(lb_token, subchannel_wrapper->lb_token().c_str()); - args.initial_metadata->Add(kGrpcLbLbTokenMetadataKey, lb_token); + args.initial_metadata->Add(LbTokenMetadata::key(), lb_token); } // Unwrap subchannel to pass up to the channel. complete_pick->subchannel = subchannel_wrapper->wrapped_subchannel(); @@ -794,7 +790,7 @@ GrpcLb::BalancerCallState::BalancerCallState( lb_call_ = grpc_channel_create_pollset_set_call( grpclb_policy()->lb_channel_, nullptr, GRPC_PROPAGATE_DEFAULTS, grpclb_policy_->interested_parties(), - GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD, + Slice::FromStaticString("/grpc.lb.v1.LoadBalancer/BalanceLoad").c_slice(), nullptr, deadline, nullptr); // Init the LB call request payload. upb::Arena arena; @@ -1441,8 +1437,20 @@ void GrpcLb::UpdateLocked(UpdateArgs args) { const bool is_initial_update = lb_channel_ == nullptr; config_ = args.config; GPR_ASSERT(config_ != nullptr); - ProcessAddressesAndChannelArgsLocked(args.addresses, *args.args); - // Update the existing child policy. + // Update fallback address list. + fallback_backend_addresses_ = std::move(args.addresses); + if (fallback_backend_addresses_.ok()) { + // Add null LB token attributes. + for (ServerAddress& address : *fallback_backend_addresses_) { + address = address.WithAttribute( + kGrpcLbAddressAttributeKey, + y_absl::make_unique<TokenAndClientStatsAttribute>("", nullptr)); + } + } + resolution_note_ = std::move(args.resolution_note); + // Update balancer channel. + UpdateBalancerChannelLocked(*args.args); + // Update the existing child policy, if any. if (child_policy_ != nullptr) CreateOrUpdateChildPolicyLocked(); // If this is the initial update, start the fallback-at-startup checks // and the balancer call. @@ -1471,21 +1479,7 @@ void GrpcLb::UpdateLocked(UpdateArgs args) { // helpers for UpdateLocked() // -ServerAddressList GrpcLb::AddNullLbTokenToAddresses( - const ServerAddressList& addresses) { - ServerAddressList addresses_out; - for (const ServerAddress& address : addresses) { - addresses_out.emplace_back(address.WithAttribute( - kGrpcLbAddressAttributeKey, - y_absl::make_unique<TokenAndClientStatsAttribute>("", nullptr))); - } - return addresses_out; -} - -void GrpcLb::ProcessAddressesAndChannelArgsLocked( - const ServerAddressList& addresses, const grpc_channel_args& args) { - // Update fallback address list. - fallback_backend_addresses_ = AddNullLbTokenToAddresses(addresses); +void GrpcLb::UpdateBalancerChannelLocked(const grpc_channel_args& args) { // Make sure that GRPC_ARG_LB_POLICY_NAME is set in channel args, // since we use this to trigger the client_load_reporting filter. static const char* args_to_remove[] = {GRPC_ARG_LB_POLICY_NAME}; @@ -1687,9 +1681,14 @@ void GrpcLb::CreateOrUpdateChildPolicyLocked() { // If CreateOrUpdateChildPolicyLocked() is invoked when we haven't // received any serverlist from the balancer, we use the fallback backends // returned by the resolver. Note that the fallback backend list may be - // empty, in which case the new round_robin policy will keep the requested - // picks pending. + // empty, in which case the new child policy will fail the picks. update_args.addresses = fallback_backend_addresses_; + if (fallback_backend_addresses_.ok() && + fallback_backend_addresses_->empty()) { + update_args.resolution_note = y_absl::StrCat( + "grpclb in fallback mode without any balancer addresses: ", + resolution_note_); + } } else { update_args.addresses = serverlist_->GetServerAddressList( lb_calld_ == nullptr ? nullptr : lb_calld_->client_stats()); diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h index 27e7a3a333..91aa541b90 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h @@ -36,12 +36,5 @@ #define GRPC_ARG_GRPCLB_SUBCHANNEL_CACHE_INTERVAL_MS \ "grpc.internal.grpclb_subchannel_cache_interval_ms" -namespace grpc_core { - -extern const char kGrpcLbClientStatsMetadataKey[]; -extern const char kGrpcLbLbTokenMetadataKey[]; - -} // namespace grpc_core - #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H \ */ diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h index f95341e3f4..32ee1dd880 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h @@ -21,7 +21,7 @@ #include <grpc/impl/codegen/grpc_types.h> -#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/resolver/server_address.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h index 8ea4885285..d737b9ecb4 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h @@ -23,7 +23,7 @@ #include <grpc/impl/codegen/grpc_types.h> -#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/resolver/server_address.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc index 8146d3996e..80ea41b422 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc @@ -29,10 +29,10 @@ #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/lb_policy/grpclb/grpclb_channel.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/resolver/server_address.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/slice/slice_internal.h" diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc index aaf575c9bf..b94fa16829 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc @@ -1,20 +1,18 @@ -/* - * - * 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 <grpc/support/port_platform.h> @@ -24,11 +22,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/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/resolver/server_address.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/error_utils.h" @@ -181,20 +179,25 @@ void PickFirst::ResetBackoffLocked() { } void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() { - // Create a subchannel list from the latest_update_args_. + // Create a subchannel list from latest_update_args_. + ServerAddressList addresses; + if (latest_update_args_.addresses.ok()) { + addresses = *latest_update_args_.addresses; + } auto subchannel_list = MakeOrphanable<PickFirstSubchannelList>( - this, &grpc_lb_pick_first_trace, latest_update_args_.addresses, + this, &grpc_lb_pick_first_trace, std::move(addresses), *latest_update_args_.args); // Empty update or no valid subchannels. if (subchannel_list->num_subchannels() == 0) { // Unsubscribe from all current subchannels. subchannel_list_ = std::move(subchannel_list); // Empty list. selected_ = nullptr; - // If not idle, put the channel in TRANSIENT_FAILURE. - // (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.) - y_absl::Status status = y_absl::UnavailableError("Empty update"); + // Put the channel in TRANSIENT_FAILURE. + y_absl::Status status = + latest_update_args_.addresses.ok() + ? y_absl::UnavailableError(y_absl::StrCat( + "empty address list: ", latest_update_args_.resolution_note)) + : latest_update_args_.addresses.status(); channel_control_helper()->UpdateState( GRPC_CHANNEL_TRANSIENT_FAILURE, status, y_absl::make_unique<TransientFailurePicker>(status)); @@ -258,17 +261,28 @@ void PickFirst::AttemptToConnectUsingLatestUpdateArgsLocked() { void PickFirst::UpdateLocked(UpdateArgs args) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_pick_first_trace)) { - gpr_log(GPR_INFO, - "Pick First %p received update with %" PRIuPTR " addresses", this, - args.addresses.size()); + if (args.addresses.ok()) { + gpr_log(GPR_INFO, + "Pick First %p received update with %" PRIuPTR " addresses", this, + args.addresses->size()); + } else { + gpr_log(GPR_INFO, "Pick First %p received update with address error: %s", + this, args.addresses.status().ToString().c_str()); + } } - // Update the latest_update_args_ + // Add GRPC_ARG_INHIBIT_HEALTH_CHECKING channel arg. grpc_arg new_arg = grpc_channel_arg_integer_create( const_cast<char*>(GRPC_ARG_INHIBIT_HEALTH_CHECKING), 1); const grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args.args, &new_arg, 1); std::swap(new_args, args.args); grpc_channel_args_destroy(new_args); + // If the update contains a resolver error and we have a previous update + // that was not a resolver error, keep using the previous addresses. + if (!args.addresses.ok() && latest_update_args_.config != nullptr) { + args.addresses = std::move(latest_update_args_.addresses); + } + // Update latest_update_args_. latest_update_args_ = std::move(args); // If we are not in idle, start connection attempt immediately. // Otherwise, we defer the attempt into ExitIdleLocked(). diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc index 79739f5099..5417311351 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc @@ -224,7 +224,7 @@ class PriorityLb : public LoadBalancingPolicy { // Current channel args and config from the resolver. const grpc_channel_args* args_ = nullptr; RefCountedPtr<PriorityLbConfig> config_; - HierarchicalAddressMap addresses_; + y_absl::StatusOr<HierarchicalAddressMap> addresses_; // Internal state. bool shutting_down_ = false; @@ -557,7 +557,11 @@ void PriorityLb::ChildPriority::UpdateLocked( // Construct update args. UpdateArgs update_args; update_args.config = std::move(config); - update_args.addresses = priority_policy_->addresses_[name_]; + if (priority_policy_->addresses_.ok()) { + update_args.addresses = (*priority_policy_->addresses_)[name_]; + } else { + update_args.addresses = priority_policy_->addresses_.status(); + } update_args.args = grpc_channel_args_copy(priority_policy_->args_); // Update the policy. if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_priority_trace)) { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc index 389548e027..860c00a996 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc @@ -37,7 +37,6 @@ #include "src/core/lib/gprpp/sync.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" namespace grpc_core { @@ -106,6 +105,7 @@ class RingHashLbConfig : public LoadBalancingPolicy::Config { // // ring_hash LB policy // + class RingHash : public LoadBalancingPolicy { public: explicit RingHash(Args args); @@ -118,8 +118,9 @@ class RingHash : public LoadBalancingPolicy { private: ~RingHash() override; - // Forward declaration. + // Forward declarations. class RingHashSubchannelList; + class Ring; // Data for a particular subchannel in a subchannel list. // This subclass adds the following functionality: @@ -136,9 +137,10 @@ class RingHash : public LoadBalancingPolicy { : SubchannelData(subchannel_list, address, std::move(subchannel)), address_(address) {} - grpc_connectivity_state connectivity_state() const { - return last_connectivity_state_; + grpc_connectivity_state GetConnectivityState() const { + return connectivity_state_for_picker_.load(std::memory_order_relaxed); } + const ServerAddress& address() const { return address_; } bool seen_failure_since_ready() const { return seen_failure_since_ready_; } @@ -156,6 +158,8 @@ class RingHash : public LoadBalancingPolicy { ServerAddress address_; grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_SHUTDOWN; + std::atomic<grpc_connectivity_state> connectivity_state_for_picker_{ + GRPC_CHANNEL_IDLE}; bool seen_failure_since_ready_ = false; }; @@ -193,6 +197,9 @@ class RingHash : public LoadBalancingPolicy { // Transient Failure. bool UpdateRingHashConnectivityStateLocked(); + // Create a new ring from this subchannel list. + RefCountedPtr<Ring> MakeRing(); + private: size_t num_idle_ = 0; size_t num_ready_ = 0; @@ -200,20 +207,31 @@ class RingHash : public LoadBalancingPolicy { size_t num_transient_failure_ = 0; }; + class Ring : public RefCounted<Ring> { + public: + struct Entry { + uint64_t hash; + RingHashSubchannelData* subchannel; + }; + + Ring(RingHash* parent, + RefCountedPtr<RingHashSubchannelList> subchannel_list); + + const std::vector<Entry>& ring() const { return ring_; } + + private: + RefCountedPtr<RingHashSubchannelList> subchannel_list_; + std::vector<Entry> ring_; + }; + class Picker : public SubchannelPicker { public: - Picker(RefCountedPtr<RingHash> parent, - RingHashSubchannelList* subchannel_list); + Picker(RefCountedPtr<RingHash> parent, RefCountedPtr<Ring> ring) + : parent_(std::move(parent)), ring_(std::move(ring)) {} PickResult Pick(PickArgs args) override; private: - struct RingEntry { - uint64_t hash; - RefCountedPtr<SubchannelInterface> subchannel; - grpc_connectivity_state connectivity_state; - }; - // A fire-and-forget class that schedules subchannel connection attempts // on the control plane WorkSerializer. class SubchannelConnectionAttempter : public Orphanable { @@ -255,9 +273,7 @@ class RingHash : public LoadBalancingPolicy { }; RefCountedPtr<RingHash> parent_; - - // A ring of subchannels. - std::vector<RingEntry> ring_; + RefCountedPtr<Ring> ring_; }; void ShutdownLocked() override; @@ -269,16 +285,19 @@ class RingHash : public LoadBalancingPolicy { OrphanablePtr<RingHashSubchannelList> subchannel_list_; // indicating if we are shutting down. bool shutdown_ = false; + + // Current ring. + RefCountedPtr<Ring> ring_; }; // -// RingHash::Picker +// RingHash::Ring // -RingHash::Picker::Picker(RefCountedPtr<RingHash> parent, - RingHashSubchannelList* subchannel_list) - : parent_(std::move(parent)) { - size_t num_subchannels = subchannel_list->num_subchannels(); +RingHash::Ring::Ring(RingHash* parent, + RefCountedPtr<RingHashSubchannelList> subchannel_list) + : subchannel_list_(std::move(subchannel_list)) { + size_t num_subchannels = subchannel_list_->num_subchannels(); // Store the weights while finding the sum. struct AddressWeight { TString address; @@ -291,7 +310,7 @@ RingHash::Picker::Picker(RefCountedPtr<RingHash> parent, size_t sum = 0; address_weights.reserve(num_subchannels); for (size_t i = 0; i < num_subchannels; ++i) { - RingHashSubchannelData* sd = subchannel_list->subchannel(i); + RingHashSubchannelData* sd = subchannel_list_->subchannel(i); const ServerAddressWeightAttribute* weight_attribute = static_cast< const ServerAddressWeightAttribute*>(sd->address().GetAttribute( ServerAddressWeightAttribute::kServerAddressWeightAttributeKey)); @@ -322,8 +341,8 @@ RingHash::Picker::Picker(RefCountedPtr<RingHash> parent, // weights aren't provided, all hosts should get an equal number of hashes. In // the case where this number exceeds the max_ring_size, it's scaled back down // to fit. - const size_t min_ring_size = parent_->config_->min_ring_size(); - const size_t max_ring_size = parent_->config_->max_ring_size(); + const size_t min_ring_size = parent->config_->min_ring_size(); + const size_t max_ring_size = parent->config_->max_ring_size(); const double scale = std::min( std::ceil(min_normalized_weight * min_ring_size) / min_normalized_weight, static_cast<double>(max_ring_size)); @@ -347,17 +366,13 @@ RingHash::Picker::Picker(RefCountedPtr<RingHash> parent, auto offset_start = hash_key_buffer.end(); target_hashes += scale * address_weights[i].normalized_weight; size_t count = 0; - auto current_state = - subchannel_list->subchannel(i)->subchannel()->CheckConnectivityState(); while (current_hashes < target_hashes) { const TString count_str = y_absl::StrCat(count); hash_key_buffer.insert(offset_start, count_str.begin(), count_str.end()); y_absl::string_view hash_key(hash_key_buffer.data(), hash_key_buffer.size()); const uint64_t hash = XXH64(hash_key.data(), hash_key.size(), 0); - ring_.push_back({hash, - subchannel_list->subchannel(i)->subchannel()->Ref(), - current_state}); + ring_.push_back({hash, subchannel_list_->subchannel(i)}); ++count; ++current_hashes; hash_key_buffer.erase(offset_start, hash_key_buffer.end()); @@ -368,17 +383,21 @@ RingHash::Picker::Picker(RefCountedPtr<RingHash> parent, std::max(static_cast<uint64_t>(i), max_hashes_per_host); } std::sort(ring_.begin(), ring_.end(), - [](const RingEntry& lhs, const RingEntry& rhs) -> bool { + [](const Entry& lhs, const Entry& rhs) -> bool { return lhs.hash < rhs.hash; }); if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { gpr_log(GPR_INFO, - "[RH %p picker %p] created picker from subchannel_list=%p " + "[RH %p picker %p] created ring from subchannel_list=%p " "with %" PRIuPTR " ring entries", - parent_.get(), this, subchannel_list, ring_.size()); + parent, this, subchannel_list_.get(), ring_.size()); } } +// +// RingHash::Picker +// + RingHash::PickResult RingHash::Picker::Pick(PickArgs args) { auto hash = args.call_state->ExperimentalGetCallAttribute(kRequestRingHashAttribute); @@ -387,20 +406,21 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) { return PickResult::Fail( y_absl::InternalError("xds ring hash value is not a number")); } + const std::vector<Ring::Entry>& ring = ring_->ring(); // Ported from https://github.com/RJ/ketama/blob/master/libketama/ketama.c // (ketama_get_server) NOTE: The algorithm depends on using signed integers // for lowp, highp, and first_index. Do not change them! int64_t lowp = 0; - int64_t highp = ring_.size(); + int64_t highp = ring.size(); int64_t first_index = 0; while (true) { first_index = (lowp + highp) / 2; - if (first_index == static_cast<int64_t>(ring_.size())) { + if (first_index == static_cast<int64_t>(ring.size())) { first_index = 0; break; } - uint64_t midval = ring_[first_index].hash; - uint64_t midval1 = first_index == 0 ? 0 : ring_[first_index - 1].hash; + uint64_t midval = ring[first_index].hash; + uint64_t midval1 = first_index == 0 ? 0 : ring[first_index - 1].hash; if (h <= midval && h > midval1) { break; } @@ -423,35 +443,41 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) { } subchannel_connection_attempter->AddSubchannel(std::move(subchannel)); }; - switch (ring_[first_index].connectivity_state) { + switch (ring[first_index].subchannel->GetConnectivityState()) { case GRPC_CHANNEL_READY: - return PickResult::Complete(ring_[first_index].subchannel); + return PickResult::Complete( + ring[first_index].subchannel->subchannel()->Ref()); case GRPC_CHANNEL_IDLE: - ScheduleSubchannelConnectionAttempt(ring_[first_index].subchannel); + ScheduleSubchannelConnectionAttempt( + ring[first_index].subchannel->subchannel()->Ref()); Y_ABSL_FALLTHROUGH_INTENDED; case GRPC_CHANNEL_CONNECTING: return PickResult::Queue(); default: // GRPC_CHANNEL_TRANSIENT_FAILURE break; } - ScheduleSubchannelConnectionAttempt(ring_[first_index].subchannel); + ScheduleSubchannelConnectionAttempt( + ring[first_index].subchannel->subchannel()->Ref()); // Loop through remaining subchannels to find one in READY. // On the way, we make sure the right set of connection attempts // will happen. bool found_second_subchannel = false; bool found_first_non_failed = false; - for (size_t i = 1; i < ring_.size(); ++i) { - const RingEntry& entry = ring_[(first_index + i) % ring_.size()]; - if (entry.subchannel == ring_[first_index].subchannel) { + for (size_t i = 1; i < ring.size(); ++i) { + const Ring::Entry& entry = ring[(first_index + i) % ring.size()]; + if (entry.subchannel == ring[first_index].subchannel) { continue; } - if (entry.connectivity_state == GRPC_CHANNEL_READY) { - return PickResult::Complete(entry.subchannel); + grpc_connectivity_state connectivity_state = + entry.subchannel->GetConnectivityState(); + if (connectivity_state == GRPC_CHANNEL_READY) { + return PickResult::Complete(entry.subchannel->subchannel()->Ref()); } if (!found_second_subchannel) { - switch (entry.connectivity_state) { + switch (connectivity_state) { case GRPC_CHANNEL_IDLE: - ScheduleSubchannelConnectionAttempt(entry.subchannel); + ScheduleSubchannelConnectionAttempt( + entry.subchannel->subchannel()->Ref()); Y_ABSL_FALLTHROUGH_INTENDED; case GRPC_CHANNEL_CONNECTING: return PickResult::Queue(); @@ -461,11 +487,13 @@ RingHash::PickResult RingHash::Picker::Pick(PickArgs args) { found_second_subchannel = true; } if (!found_first_non_failed) { - if (entry.connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { - ScheduleSubchannelConnectionAttempt(entry.subchannel); + if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { + ScheduleSubchannelConnectionAttempt( + entry.subchannel->subchannel()->Ref()); } else { - if (entry.connectivity_state == GRPC_CHANNEL_IDLE) { - ScheduleSubchannelConnectionAttempt(entry.subchannel); + if (connectivity_state == GRPC_CHANNEL_IDLE) { + ScheduleSubchannelConnectionAttempt( + entry.subchannel->subchannel()->Ref()); } found_first_non_failed = true; } @@ -498,7 +526,7 @@ void RingHash::RingHashSubchannelList::StartWatchingLocked() { p->channel_control_helper()->UpdateState( GRPC_CHANNEL_READY, y_absl::Status(), y_absl::make_unique<Picker>(p->Ref(DEBUG_LOCATION, "RingHashPicker"), - this)); + p->ring_)); } void RingHash::RingHashSubchannelList::UpdateStateCountersLocked( @@ -547,7 +575,7 @@ bool RingHash::RingHashSubchannelList::UpdateRingHashConnectivityStateLocked() { p->channel_control_helper()->UpdateState( GRPC_CHANNEL_READY, y_absl::Status(), y_absl::make_unique<Picker>(p->Ref(DEBUG_LOCATION, "RingHashPicker"), - this)); + p->ring_)); return false; } if (num_connecting_ > 0 && num_transient_failure_ < 2) { @@ -560,7 +588,7 @@ bool RingHash::RingHashSubchannelList::UpdateRingHashConnectivityStateLocked() { p->channel_control_helper()->UpdateState( GRPC_CHANNEL_IDLE, y_absl::Status(), y_absl::make_unique<Picker>(p->Ref(DEBUG_LOCATION, "RingHashPicker"), - this)); + p->ring_)); return false; } y_absl::Status status = @@ -571,6 +599,11 @@ bool RingHash::RingHashSubchannelList::UpdateRingHashConnectivityStateLocked() { return true; } +RefCountedPtr<RingHash::Ring> RingHash::RingHashSubchannelList::MakeRing() { + RingHash* p = static_cast<RingHash*>(policy()); + return MakeRefCounted<Ring>(p, Ref(DEBUG_LOCATION, "Ring")); +} + // // RingHash::RingHashSubchannelData // @@ -581,7 +614,7 @@ void RingHash::RingHashSubchannelData::UpdateConnectivityStateLocked( if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { gpr_log( GPR_INFO, - "[RR %p] connectivity changed for subchannel %p, subchannel_list %p " + "[RH %p] connectivity changed for subchannel %p, subchannel_list %p " "(index %" PRIuPTR " of %" PRIuPTR "): prev_state=%s new_state=%s", p, subchannel(), subchannel_list(), Index(), subchannel_list()->num_subchannels(), @@ -614,6 +647,9 @@ void RingHash::RingHashSubchannelData::ProcessConnectivityChangeLocked( grpc_connectivity_state connectivity_state) { RingHash* p = static_cast<RingHash*>(subchannel_list()->policy()); GPR_ASSERT(subchannel() != nullptr); + // Update connectivity state used by picker. + connectivity_state_for_picker_.store(connectivity_state, + std::memory_order_relaxed); // If the new state is TRANSIENT_FAILURE, re-resolve. // Only do this if we've started watching, not at startup time. // Otherwise, if the subchannel was already in state TRANSIENT_FAILURE @@ -623,7 +659,7 @@ void RingHash::RingHashSubchannelData::ProcessConnectivityChangeLocked( if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { gpr_log(GPR_INFO, - "[RR %p] Subchannel %p has gone into TRANSIENT_FAILURE. " + "[RH %p] Subchannel %p has gone into TRANSIENT_FAILURE. " "Requesting re-resolution", p, subchannel()); } @@ -680,36 +716,52 @@ void RingHash::ShutdownLocked() { } shutdown_ = true; subchannel_list_.reset(); + ring_.reset(DEBUG_LOCATION, "RingHash"); } void RingHash::ResetBackoffLocked() { subchannel_list_->ResetBackoffLocked(); } void RingHash::UpdateLocked(UpdateArgs args) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { - gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses", - this, args.addresses.size()); - } config_ = std::move(args.config); - // Filter out any address with weight 0. ServerAddressList addresses; - addresses.reserve(args.addresses.size()); - for (ServerAddress& address : args.addresses) { - const ServerAddressWeightAttribute* weight_attribute = - static_cast<const ServerAddressWeightAttribute*>(address.GetAttribute( - ServerAddressWeightAttribute::kServerAddressWeightAttributeKey)); - if (weight_attribute == nullptr || weight_attribute->weight() > 0) { - addresses.push_back(std::move(address)); + if (args.addresses.ok()) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { + gpr_log(GPR_INFO, "[RH %p] received update with %" PRIuPTR " addresses", + this, args.addresses->size()); + } + // Filter out any address with weight 0. + addresses.reserve(args.addresses->size()); + for (ServerAddress& address : *args.addresses) { + const ServerAddressWeightAttribute* weight_attribute = + static_cast<const ServerAddressWeightAttribute*>(address.GetAttribute( + ServerAddressWeightAttribute::kServerAddressWeightAttributeKey)); + if (weight_attribute == nullptr || weight_attribute->weight() > 0) { + addresses.emplace_back(std::move(address)); + } + } + } else { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_ring_hash_trace)) { + gpr_log(GPR_INFO, "[RH %p] received update with addresses error: %s", + this, args.addresses.status().ToString().c_str()); } + // If we already have a subchannel list, then ignore the resolver + // failure and keep using the existing list. + if (subchannel_list_ != nullptr) return; } subchannel_list_ = MakeOrphanable<RingHashSubchannelList>( this, &grpc_lb_ring_hash_trace, std::move(addresses), *args.args); if (subchannel_list_->num_subchannels() == 0) { // If the new list is empty, immediately transition to TRANSIENT_FAILURE. - y_absl::Status status = y_absl::UnavailableError("Empty update"); + y_absl::Status status = + args.addresses.ok() ? y_absl::UnavailableError(y_absl::StrCat( + "empty address list: ", args.resolution_note)) + : args.addresses.status(); channel_control_helper()->UpdateState( GRPC_CHANNEL_TRANSIENT_FAILURE, status, y_absl::make_unique<TransientFailurePicker>(status)); } else { + // Build the ring. + ring_ = subchannel_list_->MakeRing(); // Start watching the new list. subchannel_list_->StartWatchingLocked(); } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc index c437c52207..966f015631 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc @@ -52,7 +52,6 @@ #include "src/core/ext/filters/client_channel/lb_policy/child_policy_handler.h" #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #include "src/core/ext/filters/client_channel/lb_policy_registry.h" -#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" @@ -64,13 +63,13 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/json/json.h" #include "src/core/lib/json/json_util.h" +#include "src/core/lib/resolver/resolver_registry.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/error_utils.h" -#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/uri/uri_parser.h" #include "src/proto/grpc/lookup/v1/rls.upb.h" @@ -93,9 +92,9 @@ const grpc_millis kCacheBackoffInitial = 1 * GPR_MS_PER_SEC; const double kCacheBackoffMultiplier = 1.6; const double kCacheBackoffJitter = 0.2; const grpc_millis kCacheBackoffMax = 120 * GPR_MS_PER_SEC; -const grpc_millis kDefaultThrottleWindowSize = 30 * GPR_MS_PER_SEC; -const double kDefaultThrottleRatioForSuccesses = 2.0; -const int kDefaultThrottlePaddings = 8; +const grpc_millis kDefaultThrottleWindowSizeMs = 30 * GPR_MS_PER_SEC; +const float kDefaultThrottleRatioForSuccesses = 2.0; +const int kDefaultThrottlePadding = 8; const grpc_millis kCacheCleanupTimerInterval = 60 * GPR_MS_PER_SEC; const int64_t kMaxCacheSizeBytes = 5 * 1024 * 1024; @@ -557,8 +556,13 @@ class RlsLb : public LoadBalancingPolicy { // Throttle state for RLS requests. class Throttle { public: - explicit Throttle(int window_size_seconds = 0, - double ratio_for_successes = 0, int paddings = 0); + explicit Throttle( + int window_size_ms = kDefaultThrottleWindowSizeMs, + float ratio_for_successes = kDefaultThrottleRatioForSuccesses, + int padding = kDefaultThrottlePadding) + : window_size_ms_(window_size_ms), + ratio_for_successes_(ratio_for_successes), + padding_(padding) {} bool ShouldThrottle() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); @@ -566,15 +570,15 @@ class RlsLb : public LoadBalancingPolicy { Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&RlsLb::mu_); private: - grpc_millis window_size_; - double ratio_for_successes_; - int paddings_; + grpc_millis window_size_ms_; + float ratio_for_successes_; + int padding_; - // Logged timestamp of requests. + // Logged timestamps of requests. std::deque<grpc_millis> requests_ Y_ABSL_GUARDED_BY(&RlsLb::mu_); - // Logged timestamp of responses that were successful. - std::deque<grpc_millis> successes_ Y_ABSL_GUARDED_BY(&RlsLb::mu_); + // Logged timestamps of failures. + std::deque<grpc_millis> failures_ Y_ABSL_GUARDED_BY(&RlsLb::mu_); }; RefCountedPtr<RlsLb> lb_policy_; @@ -669,7 +673,7 @@ class RlsLb : public LoadBalancingPolicy { OrphanablePtr<RlsChannel> rls_channel_ Y_ABSL_GUARDED_BY(mu_); // Accessed only from within WorkSerializer. - ServerAddressList addresses_; + y_absl::StatusOr<ServerAddressList> addresses_; const grpc_channel_args* channel_args_ = nullptr; RefCountedPtr<RlsLbConfig> config_; RefCountedPtr<ChildPolicyWrapper> default_child_policy_; @@ -1459,41 +1463,40 @@ void RlsLb::RlsChannel::StateWatcher::OnConnectivityStateChange( // RlsLb::RlsChannel::Throttle // -RlsLb::RlsChannel::Throttle::Throttle(int window_size_seconds, - double ratio_for_successes, - int paddings) { - GPR_DEBUG_ASSERT(window_size_seconds >= 0); - GPR_DEBUG_ASSERT(ratio_for_successes >= 0); - GPR_DEBUG_ASSERT(paddings >= 0); - window_size_ = window_size_seconds == 0 ? window_size_seconds * GPR_MS_PER_SEC - : kDefaultThrottleWindowSize; - ratio_for_successes_ = ratio_for_successes == 0 - ? kDefaultThrottleRatioForSuccesses - : ratio_for_successes; - paddings_ = paddings == 0 ? kDefaultThrottlePaddings : paddings; -} - bool RlsLb::RlsChannel::Throttle::ShouldThrottle() { grpc_millis now = ExecCtx::Get()->Now(); - while (!requests_.empty() && now - requests_.front() > window_size_) { + while (!requests_.empty() && now - requests_.front() > window_size_ms_) { requests_.pop_front(); } - while (!successes_.empty() && now - successes_.front() > window_size_) { - successes_.pop_front(); - } - int successes = successes_.size(); - int requests = requests_.size(); - bool result = ((rand() % (requests + paddings_)) < - static_cast<double>(requests) - - static_cast<double>(successes) * ratio_for_successes_); - requests_.push_back(now); - return result; + while (!failures_.empty() && now - failures_.front() > window_size_ms_) { + failures_.pop_front(); + } + // Compute probability of throttling. + float num_requests = requests_.size(); + float num_successes = num_requests - failures_.size(); + // Note: it's possible that this ratio will be negative, in which case + // no throttling will be done. + float throttle_probability = + (num_requests - (num_successes * ratio_for_successes_)) / + (num_requests + padding_); + // Generate a random number for the request. + std::random_device rd; + std::mt19937 mt(rd()); + std::uniform_real_distribution<float> dist(0, 1.0); + // Check if we should throttle the request. + bool throttle = dist(mt) < throttle_probability; + // If we're throttling, record the request and the failure. + if (throttle) { + requests_.push_back(now); + failures_.push_back(now); + } + return throttle; } void RlsLb::RlsChannel::Throttle::RegisterResponse(bool success) { - if (success) { - successes_.push_back(ExecCtx::Get()->Now()); - } + grpc_millis now = ExecCtx::Get()->Now(); + requests_.push_back(now); + if (!success) failures_.push_back(now); } // @@ -1762,7 +1765,7 @@ void RlsLb::RlsRequest::OnRlsCallCompleteLocked(grpc_error_handle error) { { MutexLock lock(&lb_policy_->mu_); if (lb_policy_->is_shutdown_) return; - rls_channel_->ReportResponseLocked(!response.status.ok()); + rls_channel_->ReportResponseLocked(response.status.ok()); Cache::Entry* cache_entry = lb_policy_->cache_.FindOrInsert(key_); child_policies_to_finish_update = cache_entry->OnRlsResponseLocked( std::move(response), std::move(backoff_state_)); @@ -1863,19 +1866,28 @@ void RlsLb::UpdateLocked(UpdateArgs args) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace)) { gpr_log(GPR_INFO, "[rlslb %p] policy updated", this); } - // Swap out config, addresses, and channel args. + // Swap out config. RefCountedPtr<RlsLbConfig> old_config = std::move(config_); config_ = std::move(args.config); - ServerAddressList old_addresses = std::move(addresses_); - addresses_ = std::move(args.addresses); - grpc_channel_args_destroy(channel_args_); - channel_args_ = grpc_channel_args_copy(args.args); if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_rls_trace) && (old_config == nullptr || old_config->child_policy_config() != config_->child_policy_config())) { gpr_log(GPR_INFO, "[rlslb %p] updated child policy config: %s", this, config_->child_policy_config().Dump().c_str()); } + // Swap out addresses. + // If the new address list is an error and we have an existing address list, + // stick with the existing addresses. + y_absl::StatusOr<ServerAddressList> old_addresses; + if (args.addresses.ok()) { + old_addresses = std::move(addresses_); + addresses_ = std::move(args.addresses); + } else { + old_addresses = addresses_; + } + // Swap out channel args. + grpc_channel_args_destroy(channel_args_); + channel_args_ = grpc_channel_args_copy(args.args); // Determine whether we need to update all child policies. bool update_child_policies = old_config == nullptr || diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc index d77aea0399..a4aae3e85e 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc @@ -1,28 +1,18 @@ -/* - * - * 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. - * - */ - -/** Round Robin Policy. - * - * Before every pick, the \a get_next_ready_subchannel_index_locked function - * returns the p->subchannel_list->subchannels index for next subchannel, - * respecting the relative order of the addresses provided upon creation or - * updates. Note however that updates will start picking from the beginning of - * the updated list. */ +// +// 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 <grpc/support/port_platform.h> @@ -41,7 +31,6 @@ #include "src/core/lib/gprpp/sync.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" namespace grpc_core { @@ -166,15 +155,14 @@ class RoundRobin : public LoadBalancingPolicy { void ShutdownLocked() override; - /** list of subchannels */ + // List of subchannels. OrphanablePtr<RoundRobinSubchannelList> subchannel_list_; - /** Latest version of the subchannel list. - * Subchannel connectivity callbacks will only promote updated subchannel - * lists if they equal \a latest_pending_subchannel_list. In other words, - * racing callbacks that reference outdated subchannel lists won't perform any - * update. */ + // Latest pending subchannel list. + // When we get an updated address list, we create a new subchannel list + // for it here, and we wait to swap it into subchannel_list_ until the new + // list becomes READY. OrphanablePtr<RoundRobinSubchannelList> latest_pending_subchannel_list_; - /** are we shutting down? */ + bool shutdown_ = false; }; @@ -303,31 +291,30 @@ void RoundRobin::RoundRobinSubchannelList:: RoundRobin* p = static_cast<RoundRobin*>(policy()); // Only set connectivity state if this is the current subchannel list. if (p->subchannel_list_.get() != this) return; - /* In priority order. The first rule to match terminates the search (ie, if we - * are on rule n, all previous rules were unfulfilled). - * - * 1) RULE: ANY subchannel is READY => policy is READY. - * CHECK: subchannel_list->num_ready > 0. - * - * 2) RULE: ANY subchannel is CONNECTING => policy is CONNECTING. - * CHECK: sd->curr_connectivity_state == CONNECTING. - * - * 3) RULE: ALL subchannels are TRANSIENT_FAILURE => policy is - * TRANSIENT_FAILURE. - * CHECK: subchannel_list->num_transient_failures == - * subchannel_list->num_subchannels. - */ + // In priority order. The first rule to match terminates the search (ie, if we + // are on rule n, all previous rules were unfulfilled). + // + // 1) RULE: ANY subchannel is READY => policy is READY. + // CHECK: subchannel_list->num_ready > 0. + // + // 2) RULE: ANY subchannel is CONNECTING => policy is CONNECTING. + // CHECK: sd->curr_connectivity_state == CONNECTING. + // + // 3) RULE: ALL subchannels are TRANSIENT_FAILURE => policy is + // TRANSIENT_FAILURE. + // CHECK: subchannel_list->num_transient_failures == + // subchannel_list->num_subchannels. if (num_ready_ > 0) { - /* 1) READY */ + // 1) READY p->channel_control_helper()->UpdateState( GRPC_CHANNEL_READY, y_absl::Status(), y_absl::make_unique<Picker>(p, this)); } else if (num_connecting_ > 0) { - /* 2) CONNECTING */ + // 2) CONNECTING p->channel_control_helper()->UpdateState( GRPC_CHANNEL_CONNECTING, y_absl::Status(), y_absl::make_unique<QueuePicker>(p->Ref(DEBUG_LOCATION, "QueuePicker"))); } else if (num_transient_failure_ == num_subchannels()) { - /* 3) TRANSIENT_FAILURE */ + // 3) TRANSIENT_FAILURE y_absl::Status status = y_absl::UnavailableError("connections to all backends failing"); p->channel_control_helper()->UpdateState( @@ -432,24 +419,38 @@ void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked( } void RoundRobin::UpdateLocked(UpdateArgs args) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { - gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses", - this, args.addresses.size()); - } - // Replace latest_pending_subchannel_list_. - if (latest_pending_subchannel_list_ != nullptr) { + ServerAddressList addresses; + if (args.addresses.ok()) { if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { - gpr_log(GPR_INFO, - "[RR %p] Shutting down previous pending subchannel list %p", this, - latest_pending_subchannel_list_.get()); + gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses", + this, args.addresses->size()); + } + addresses = std::move(*args.addresses); + } else { + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace)) { + gpr_log(GPR_INFO, "[RR %p] received update with address error: %s", this, + args.addresses.status().ToString().c_str()); } + // If we already have a subchannel list, then ignore the resolver + // failure and keep using the existing list. + if (subchannel_list_ != nullptr) return; + } + // Replace latest_pending_subchannel_list_. + if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_round_robin_trace) && + latest_pending_subchannel_list_ != nullptr) { + gpr_log(GPR_INFO, + "[RR %p] Shutting down previous pending subchannel list %p", this, + latest_pending_subchannel_list_.get()); } latest_pending_subchannel_list_ = MakeOrphanable<RoundRobinSubchannelList>( - this, &grpc_lb_round_robin_trace, std::move(args.addresses), *args.args); + this, &grpc_lb_round_robin_trace, std::move(addresses), *args.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. - y_absl::Status status = y_absl::UnavailableError("Empty update"); + y_absl::Status status = + args.addresses.ok() ? y_absl::UnavailableError(y_absl::StrCat( + "empty address list: ", args.resolution_note)) + : args.addresses.status(); channel_control_helper()->UpdateState( GRPC_CHANNEL_TRANSIENT_FAILURE, status, y_absl::make_unique<TransientFailurePicker>(status)); diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h index 5076b7e848..15a303d943 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h @@ -29,18 +29,16 @@ #include <grpc/support/alloc.h> #include "src/core/ext/filters/client_channel/lb_policy_registry.h" -#include "src/core/ext/filters/client_channel/server_address.h" -// TODO(roth): Should not need the include of subchannel.h here, since -// 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/manual_constructor.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/resolver/server_address.h" #include "src/core/lib/transport/connectivity_state.h" // Code for maintaining a list of subchannels within an LB policy. @@ -176,13 +174,18 @@ class SubchannelData { template <typename SubchannelListType, typename SubchannelDataType> class SubchannelList : public InternallyRefCounted<SubchannelListType> { public: - typedef y_absl::InlinedVector<SubchannelDataType, 10> SubchannelVector; + // We use ManualConstructor here to support SubchannelDataType classes + // that are not copyable. + typedef y_absl::InlinedVector<ManualConstructor<SubchannelDataType>, 10> + SubchannelVector; // The number of subchannels in the list. size_t num_subchannels() const { return subchannels_.size(); } // The data for the subchannel at a particular index. - SubchannelDataType* subchannel(size_t index) { return &subchannels_[index]; } + SubchannelDataType* subchannel(size_t index) { + return subchannels_[index].get(); + } // Returns true if the subchannel list is shutting down. bool shutting_down() const { return shutting_down_; } @@ -387,7 +390,8 @@ SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList( tracer_->name(), policy_, this, subchannels_.size(), subchannel.get(), address.ToString().c_str()); } - subchannels_.emplace_back(this, std::move(address), std::move(subchannel)); + subchannels_.emplace_back(); + subchannels_.back().Init(this, std::move(address), std::move(subchannel)); } } @@ -397,6 +401,9 @@ SubchannelList<SubchannelListType, SubchannelDataType>::~SubchannelList() { gpr_log(GPR_INFO, "[%s %p] Destroying subchannel_list %p", tracer_->name(), policy_, this); } + for (auto& sd : subchannels_) { + sd.Destroy(); + } } template <typename SubchannelListType, typename SubchannelDataType> @@ -407,8 +414,7 @@ void SubchannelList<SubchannelListType, SubchannelDataType>::ShutdownLocked() { } GPR_ASSERT(!shutting_down_); shutting_down_ = true; - for (size_t i = 0; i < subchannels_.size(); i++) { - SubchannelDataType* sd = &subchannels_[i]; + for (auto& sd : subchannels_) { sd->ShutdownLocked(); } } @@ -416,8 +422,7 @@ void SubchannelList<SubchannelListType, SubchannelDataType>::ShutdownLocked() { template <typename SubchannelListType, typename SubchannelDataType> void SubchannelList<SubchannelListType, SubchannelDataType>::ResetBackoffLocked() { - for (size_t i = 0; i < subchannels_.size(); i++) { - SubchannelDataType* sd = &subchannels_[i]; + for (auto& sd : subchannels_) { sd->ResetBackoffLocked(); } } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc index c96f6b28b7..3ff30cbd98 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc @@ -123,7 +123,7 @@ class WeightedTargetLb : public LoadBalancingPolicy { void Orphan() override; void UpdateLocked(const WeightedTargetLbConfig::ChildConfig& config, - ServerAddressList addresses, + y_absl::StatusOr<ServerAddressList> addresses, const grpc_channel_args* args); void ResetBackoffLocked(); void DeactivateLocked(); @@ -296,13 +296,18 @@ void WeightedTargetLb::UpdateLocked(UpdateArgs args) { } } // Update all children. - HierarchicalAddressMap address_map = + y_absl::StatusOr<HierarchicalAddressMap> address_map = MakeHierarchicalAddressMap(args.addresses); for (const auto& p : config_->target_map()) { const TString& name = p.first; const WeightedTargetLbConfig::ChildConfig& config = p.second; - targets_[name]->UpdateLocked(config, std::move(address_map[name]), - args.args); + y_absl::StatusOr<ServerAddressList> addresses; + if (address_map.ok()) { + addresses = std::move((*address_map)[name]); + } else { + addresses = address_map.status(); + } + targets_[name]->UpdateLocked(config, std::move(addresses), args.args); } UpdateStateLocked(); } @@ -473,7 +478,8 @@ WeightedTargetLb::WeightedChild::CreateChildPolicyLocked( void WeightedTargetLb::WeightedChild::UpdateLocked( const WeightedTargetLbConfig::ChildConfig& config, - ServerAddressList addresses, const grpc_channel_args* args) { + y_absl::StatusOr<ServerAddressList> addresses, + const grpc_channel_args* args) { if (weighted_target_policy_->shutting_down_) return; // Update child weight. weight_ = config.weight; diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc index d93feec59b..ba77cf6d49 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc @@ -25,6 +25,7 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/xds/xds_certificate_provider.h" #include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_cluster.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/orphanable.h" @@ -66,12 +67,12 @@ class CdsLb : public LoadBalancingPolicy { private: // Watcher for getting cluster data from XdsClient. - class ClusterWatcher : public XdsClient::ClusterWatcherInterface { + class ClusterWatcher : public XdsClusterResourceType::WatcherInterface { public: ClusterWatcher(RefCountedPtr<CdsLb> parent, TString name) : parent_(std::move(parent)), name_(std::move(name)) {} - void OnClusterChanged(XdsApi::CdsUpdate cluster_data) override { + void OnResourceChanged(XdsClusterResource cluster_data) override { Ref().release(); // Ref held by lambda parent_->work_serializer()->Run( // TODO(roth): When we move to C++14, capture cluster_data with @@ -111,7 +112,7 @@ class CdsLb : public LoadBalancingPolicy { // Not owned, so do not dereference. ClusterWatcher* watcher = nullptr; // Most recent update obtained from this watcher. - y_absl::optional<XdsApi::CdsUpdate> update; + y_absl::optional<XdsClusterResource> update; }; // Delegating helper to be passed to child policy. @@ -139,15 +140,15 @@ class CdsLb : public LoadBalancingPolicy { const TString& name, Json::Array* discovery_mechanisms, std::set<TString>* clusters_needed); void OnClusterChanged(const TString& name, - XdsApi::CdsUpdate cluster_data); + XdsClusterResource cluster_data); void OnError(const TString& name, grpc_error_handle error); void OnResourceDoesNotExist(const TString& name); grpc_error_handle UpdateXdsCertificateProvider( - const TString& cluster_name, const XdsApi::CdsUpdate& cluster_data); + const TString& cluster_name, const XdsClusterResource& cluster_data); void CancelClusterDataWatch(y_absl::string_view cluster_name, - XdsClient::ClusterWatcherInterface* watcher, + ClusterWatcher* watcher, bool delay_unsubscription = false); void MaybeDestroyChildPolicyLocked(); @@ -301,7 +302,8 @@ void CdsLb::UpdateLocked(UpdateArgs args) { } auto watcher = MakeRefCounted<ClusterWatcher>(Ref(), config_->cluster()); watchers_[config_->cluster()].watcher = watcher.get(); - xds_client_->WatchClusterData(config_->cluster(), std::move(watcher)); + XdsClusterResourceType::StartWatch(xds_client_.get(), config_->cluster(), + std::move(watcher)); } } @@ -326,13 +328,15 @@ bool CdsLb::GenerateDiscoveryMechanismForCluster( name.c_str()); } state.watcher = watcher.get(); - xds_client_->WatchClusterData(name, std::move(watcher)); + XdsClusterResourceType::StartWatch(xds_client_.get(), name, + std::move(watcher)); return false; } // Don't have the update we need yet. if (!state.update.has_value()) return false; // For AGGREGATE clusters, recursively expand to child clusters. - if (state.update->cluster_type == XdsApi::CdsUpdate::ClusterType::AGGREGATE) { + if (state.update->cluster_type == + XdsClusterResource::ClusterType::AGGREGATE) { bool missing_cluster = false; for (const TString& child_name : state.update->prioritized_cluster_names) { @@ -348,13 +352,13 @@ bool CdsLb::GenerateDiscoveryMechanismForCluster( {"max_concurrent_requests", state.update->max_concurrent_requests}, }; switch (state.update->cluster_type) { - case XdsApi::CdsUpdate::ClusterType::EDS: + case XdsClusterResource::ClusterType::EDS: mechanism["type"] = "EDS"; if (!state.update->eds_service_name.empty()) { mechanism["edsServiceName"] = state.update->eds_service_name; } break; - case XdsApi::CdsUpdate::ClusterType::LOGICAL_DNS: + case XdsClusterResource::ClusterType::LOGICAL_DNS: mechanism["type"] = "LOGICAL_DNS"; mechanism["dnsHostname"] = state.update->dns_hostname; break; @@ -371,7 +375,7 @@ bool CdsLb::GenerateDiscoveryMechanismForCluster( } void CdsLb::OnClusterChanged(const TString& name, - XdsApi::CdsUpdate cluster_data) { + XdsClusterResource cluster_data) { if (GRPC_TRACE_FLAG_ENABLED(grpc_cds_lb_trace)) { gpr_log( GPR_INFO, @@ -509,7 +513,7 @@ void CdsLb::OnResourceDoesNotExist(const TString& name) { } grpc_error_handle CdsLb::UpdateXdsCertificateProvider( - const TString& cluster_name, const XdsApi::CdsUpdate& cluster_data) { + const TString& cluster_name, const XdsClusterResource& cluster_data) { // Early out if channel is not configured to use xds security. grpc_channel_credentials* channel_credentials = grpc_channel_credentials_find_in_args(args_); @@ -609,7 +613,7 @@ grpc_error_handle CdsLb::UpdateXdsCertificateProvider( } void CdsLb::CancelClusterDataWatch(y_absl::string_view cluster_name, - XdsClient::ClusterWatcherInterface* watcher, + ClusterWatcher* watcher, bool delay_unsubscription) { if (xds_certificate_provider_ != nullptr) { TString name(cluster_name); @@ -619,7 +623,7 @@ void CdsLb::CancelClusterDataWatch(y_absl::string_view cluster_name, nullptr); xds_certificate_provider_->UpdateSubjectAlternativeNameMatchers(name, {}); } - xds_client_->CancelClusterDataWatch(cluster_name, watcher, + XdsClusterResourceType::CancelWatch(xds_client_.get(), cluster_name, watcher, delay_unsubscription); } // diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds.h index b73746f5da..9a9c8901c6 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds.h @@ -19,9 +19,9 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/ext/xds/xds_client_stats.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/resolver/server_address.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc index 62c64efb44..e55698f4c5 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc @@ -30,6 +30,7 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/xds/xds_client.h" #include "src/core/ext/xds/xds_client_stats.h" +#include "src/core/ext/xds/xds_endpoint.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" @@ -120,7 +121,7 @@ class XdsClusterImplLbConfig : public LoadBalancingPolicy::Config { TString cluster_name, TString eds_service_name, y_absl::optional<TString> lrs_load_reporting_server_name, uint32_t max_concurrent_requests, - RefCountedPtr<XdsApi::EdsUpdate::DropConfig> drop_config) + RefCountedPtr<XdsEndpointResource::DropConfig> drop_config) : child_policy_(std::move(child_policy)), cluster_name_(std::move(cluster_name)), eds_service_name_(std::move(eds_service_name)), @@ -140,7 +141,7 @@ class XdsClusterImplLbConfig : public LoadBalancingPolicy::Config { return lrs_load_reporting_server_name_; }; uint32_t max_concurrent_requests() const { return max_concurrent_requests_; } - RefCountedPtr<XdsApi::EdsUpdate::DropConfig> drop_config() const { + RefCountedPtr<XdsEndpointResource::DropConfig> drop_config() const { return drop_config_; } @@ -150,7 +151,7 @@ class XdsClusterImplLbConfig : public LoadBalancingPolicy::Config { TString eds_service_name_; y_absl::optional<TString> lrs_load_reporting_server_name_; uint32_t max_concurrent_requests_; - RefCountedPtr<XdsApi::EdsUpdate::DropConfig> drop_config_; + RefCountedPtr<XdsEndpointResource::DropConfig> drop_config_; }; // xDS Cluster Impl LB policy. @@ -205,7 +206,7 @@ class XdsClusterImplLb : public LoadBalancingPolicy { RefCountedPtr<CircuitBreakerCallCounterMap::CallCounter> call_counter_; uint32_t max_concurrent_requests_; - RefCountedPtr<XdsApi::EdsUpdate::DropConfig> drop_config_; + RefCountedPtr<XdsEndpointResource::DropConfig> drop_config_; RefCountedPtr<XdsClusterDropStats> drop_stats_; RefCountedPtr<RefCountedPicker> picker_; }; @@ -238,7 +239,7 @@ class XdsClusterImplLb : public LoadBalancingPolicy { OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked( const grpc_channel_args* args); - void UpdateChildPolicyLocked(ServerAddressList addresses, + void UpdateChildPolicyLocked(y_absl::StatusOr<ServerAddressList> addresses, const grpc_channel_args* args); void MaybeUpdatePickerLocked(); @@ -470,8 +471,8 @@ void XdsClusterImplLb::UpdateLocked(UpdateArgs args) { config_->cluster_name(), config_->eds_service_name()); } else { // Cluster name, EDS service name, and LRS server name should never - // change, because the EDS policy above us should be swapped out if - // that happens. + // change, because the xds_cluster_resolver policy above us should be + // swapped out if that happens. GPR_ASSERT(config_->cluster_name() == old_config->cluster_name()); GPR_ASSERT(config_->eds_service_name() == old_config->eds_service_name()); GPR_ASSERT(config_->lrs_load_reporting_server_name() == @@ -541,8 +542,9 @@ OrphanablePtr<LoadBalancingPolicy> XdsClusterImplLb::CreateChildPolicyLocked( return lb_policy; } -void XdsClusterImplLb::UpdateChildPolicyLocked(ServerAddressList addresses, - const grpc_channel_args* args) { +void XdsClusterImplLb::UpdateChildPolicyLocked( + y_absl::StatusOr<ServerAddressList> addresses, + const grpc_channel_args* args) { // Create policy if needed. if (child_policy_ == nullptr) { child_policy_ = CreateChildPolicyLocked(args); @@ -736,7 +738,7 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { } } // Drop config. - auto drop_config = MakeRefCounted<XdsApi::EdsUpdate::DropConfig>(); + auto drop_config = MakeRefCounted<XdsEndpointResource::DropConfig>(); it = json.object_value().find("dropCategories"); if (it == json.object_value().end()) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -762,7 +764,7 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { private: static std::vector<grpc_error_handle> ParseDropCategories( - const Json& json, XdsApi::EdsUpdate::DropConfig* drop_config) { + const Json& json, XdsEndpointResource::DropConfig* drop_config) { std::vector<grpc_error_handle> error_list; if (json.type() != Json::Type::ARRAY) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( @@ -786,7 +788,7 @@ class XdsClusterImplLbFactory : public LoadBalancingPolicyFactory { } static std::vector<grpc_error_handle> ParseDropCategory( - const Json& json, XdsApi::EdsUpdate::DropConfig* drop_config) { + const Json& json, XdsEndpointResource::DropConfig* drop_config) { std::vector<grpc_error_handle> error_list; if (json.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc index 3e97b184dd..5b826147e9 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc @@ -122,7 +122,7 @@ class XdsClusterManagerLb : public LoadBalancingPolicy { void Orphan() override; void UpdateLocked(RefCountedPtr<LoadBalancingPolicy::Config> config, - const ServerAddressList& addresses, + const y_absl::StatusOr<ServerAddressList>& addresses, const grpc_channel_args* args); void ExitIdleLocked(); void ResetBackoffLocked(); @@ -441,7 +441,8 @@ XdsClusterManagerLb::ClusterChild::CreateChildPolicyLocked( void XdsClusterManagerLb::ClusterChild::UpdateLocked( RefCountedPtr<LoadBalancingPolicy::Config> config, - const ServerAddressList& addresses, const grpc_channel_args* args) { + const y_absl::StatusOr<ServerAddressList>& addresses, + const grpc_channel_args* args) { if (xds_cluster_manager_policy_->shutting_down_) return; // Update child weight. // Reactivate if needed. diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc index 262de95d31..7c6a3300f7 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc @@ -34,16 +34,17 @@ #include "src/core/ext/filters/client_channel/lb_policy_factory.h" #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/resolver_registry.h" -#include "src/core/ext/filters/client_channel/server_address.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_endpoint.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/work_serializer.h" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/resolver/server_address.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/uri/uri_parser.h" @@ -105,8 +106,7 @@ class XdsClusterResolverLbConfig : public LoadBalancingPolicy::Config { // Xds Cluster Resolver LB policy. class XdsClusterResolverLb : public LoadBalancingPolicy { public: - XdsClusterResolverLb(RefCountedPtr<XdsClient> xds_client, Args args, - TString server_name, bool is_xds_uri); + XdsClusterResolverLb(RefCountedPtr<XdsClient> xds_client, Args args); const char* name() const override { return kXdsClusterResolver; } @@ -139,7 +139,6 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { // to use for LRS load reporting. Caller must ensure that config_ is set // before calling. std::pair<y_absl::string_view, y_absl::string_view> GetLrsClusterKey() const { - if (!parent_->is_xds_uri_) return {parent_->server_name_, y_absl::string_view{}}; return { parent_->config_->discovery_mechanisms()[index_].cluster_name, parent_->config_->discovery_mechanisms()[index_].eds_service_name}; @@ -167,7 +166,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { bool disable_reresolution() override { return true; } private: - class EndpointWatcher : public XdsClient::EndpointWatcherInterface { + class EndpointWatcher : public XdsEndpointResourceType::WatcherInterface { public: explicit EndpointWatcher( RefCountedPtr<EdsDiscoveryMechanism> discovery_mechanism) @@ -175,13 +174,13 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { ~EndpointWatcher() override { discovery_mechanism_.reset(DEBUG_LOCATION, "EndpointWatcher"); } - void OnEndpointChanged(XdsApi::EdsUpdate update) override { + void OnResourceChanged(XdsEndpointResource update) override { Ref().release(); // ref held by callback discovery_mechanism_->parent()->work_serializer()->Run( // TODO(yashykt): When we move to C++14, capture update with // std::move [this, update]() mutable { - OnEndpointChangedHelper(std::move(update)); + OnResourceChangedHelper(std::move(update)); Unref(); }, DEBUG_LOCATION); @@ -209,7 +208,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { // Code accessing protected methods of `DiscoveryMechanism` need to be // in methods of this class rather than in lambdas to work around an MSVC // bug. - void OnEndpointChangedHelper(XdsApi::EdsUpdate update) { + void OnResourceChangedHelper(XdsEndpointResource update) { discovery_mechanism_->parent()->OnEndpointChanged( discovery_mechanism_->index(), std::move(update)); } @@ -229,7 +228,6 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { friend class EndpointWatcher; y_absl::string_view GetEdsResourceName() const { - if (!parent()->is_xds_uri_) return parent()->server_name_; if (!parent() ->config_->discovery_mechanisms()[index()] .eds_service_name.empty()) { @@ -270,9 +268,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { ~ResolverResultHandler() override {} - void ReturnResult(Resolver::Result result) override; - - void ReturnError(grpc_error_handle error) override; + void ReportResult(Resolver::Result result) override; private: RefCountedPtr<LogicalDNSDiscoveryMechanism> discovery_mechanism_; @@ -292,10 +288,10 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { // (The sum of this across all discovery mechanisms should always equal // the number of priorities in priority_list_.) uint32_t num_priorities = 0; - RefCountedPtr<XdsApi::EdsUpdate::DropConfig> drop_config; + RefCountedPtr<XdsEndpointResource::DropConfig> drop_config; // Populated only when an update has been delivered by the mechanism // but has not yet been applied to the LB policy's combined priority_list_. - y_absl::optional<XdsApi::EdsUpdate::PriorityList> pending_priority_list; + y_absl::optional<XdsEndpointResource::PriorityList> pending_priority_list; }; class Helper : public ChannelControlHelper { @@ -328,13 +324,13 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { void ShutdownLocked() override; - void OnEndpointChanged(size_t index, XdsApi::EdsUpdate update); + void OnEndpointChanged(size_t index, XdsEndpointResource update); void OnError(size_t index, grpc_error_handle error); void OnResourceDoesNotExist(size_t index); void MaybeDestroyChildPolicyLocked(); - void UpdatePriorityList(XdsApi::EdsUpdate::PriorityList priority_list); + void UpdatePriorityList(XdsEndpointResource::PriorityList priority_list); void UpdateChildPolicyLocked(); OrphanablePtr<LoadBalancingPolicy> CreateChildPolicyLocked( const grpc_channel_args* args); @@ -346,10 +342,6 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { // The xds client and endpoint watcher. RefCountedPtr<XdsClient> xds_client_; - // Server name from target URI. - TString server_name_; - bool is_xds_uri_; - // Current channel args and config from the resolver. const grpc_channel_args* args_ = nullptr; RefCountedPtr<XdsClusterResolverLbConfig> config_; @@ -361,7 +353,7 @@ class XdsClusterResolverLb : public LoadBalancingPolicy { std::vector<DiscoveryMechanismEntry> discovery_mechanisms_; // The latest data from the endpoint watcher. - XdsApi::EdsUpdate::PriorityList priority_list_; + XdsEndpointResource::PriorityList priority_list_; // State used to retain child policy names for priority policy. std::vector<size_t /*child_number*/> priority_child_numbers_; @@ -423,8 +415,8 @@ void XdsClusterResolverLb::EdsDiscoveryMechanism::Start() { auto watcher = MakeRefCounted<EndpointWatcher>( Ref(DEBUG_LOCATION, "EdsDiscoveryMechanism")); watcher_ = watcher.get(); - parent()->xds_client_->WatchEndpointData(GetEdsResourceName(), - std::move(watcher)); + XdsEndpointResourceType::StartWatch(parent()->xds_client_.get(), + GetEdsResourceName(), std::move(watcher)); } void XdsClusterResolverLb::EdsDiscoveryMechanism::Orphan() { @@ -434,8 +426,8 @@ void XdsClusterResolverLb::EdsDiscoveryMechanism::Orphan() { ":%p cancelling xds watch for %s", parent(), index(), this, TString(GetEdsResourceName()).c_str()); } - parent()->xds_client_->CancelEndpointDataWatch(GetEdsResourceName(), - watcher_); + XdsEndpointResourceType::CancelWatch(parent()->xds_client_.get(), + GetEdsResourceName(), watcher_); Unref(); } @@ -496,47 +488,38 @@ void XdsClusterResolverLb::LogicalDNSDiscoveryMechanism::Orphan() { // void XdsClusterResolverLb::LogicalDNSDiscoveryMechanism::ResolverResultHandler:: - ReturnResult(Resolver::Result result) { - // convert result to eds update - XdsApi::EdsUpdate update; - XdsApi::EdsUpdate::Priority::Locality locality; + ReportResult(Resolver::Result result) { + if (!result.addresses.ok()) { + discovery_mechanism_->parent()->OnError( + discovery_mechanism_->index(), + absl_status_to_grpc_error(result.addresses.status())); + return; + } + // Convert resolver result to EDS update. + // TODO(roth): Figure out a way to pass resolution_note through to the + // child policy. + XdsEndpointResource update; + XdsEndpointResource::Priority::Locality locality; locality.name = MakeRefCounted<XdsLocalityName>("", "", ""); locality.lb_weight = 1; - locality.endpoints = std::move(result.addresses); - XdsApi::EdsUpdate::Priority priority; + locality.endpoints = std::move(*result.addresses); + XdsEndpointResource::Priority priority; priority.localities.emplace(locality.name.get(), std::move(locality)); update.priorities.emplace_back(std::move(priority)); discovery_mechanism_->parent()->OnEndpointChanged( discovery_mechanism_->index(), std::move(update)); } -void XdsClusterResolverLb::LogicalDNSDiscoveryMechanism::ResolverResultHandler:: - ReturnError(grpc_error_handle error) { - discovery_mechanism_->parent()->OnError(discovery_mechanism_->index(), error); -} - // // XdsClusterResolverLb public methods // XdsClusterResolverLb::XdsClusterResolverLb(RefCountedPtr<XdsClient> xds_client, - Args args, TString 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) { + 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 -- 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_) { - // Couple polling. - grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(), - interested_parties()); + gpr_log(GPR_INFO, "[xds_cluster_resolver_lb %p] created -- xds_client=%p", + this, xds_client_.get()); } } @@ -556,11 +539,6 @@ void XdsClusterResolverLb::ShutdownLocked() { shutting_down_ = true; MaybeDestroyChildPolicyLocked(); discovery_mechanisms_.clear(); - if (!is_xds_uri_) { - // Decouple polling. - grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(), - interested_parties()); - } xds_client_.reset(DEBUG_LOCATION, "XdsClusterResolverLb"); // Destroy channel args. grpc_channel_args_destroy(args_); @@ -617,9 +595,6 @@ void XdsClusterResolverLb::UpdateLocked(UpdateArgs args) { } void XdsClusterResolverLb::ResetBackoffLocked() { - // When the XdsClient is instantiated in the resolver instead of in this - // LB policy, this is done via the resolver, so we don't need to do it here. - if (!is_xds_uri_ && xds_client_ != nullptr) xds_client_->ResetBackoff(); if (child_policy_ != nullptr) { child_policy_->ResetBackoffLocked(); } @@ -630,7 +605,7 @@ void XdsClusterResolverLb::ExitIdleLocked() { } void XdsClusterResolverLb::OnEndpointChanged(size_t index, - XdsApi::EdsUpdate update) { + XdsEndpointResource update) { if (shutting_down_) return; if (GRPC_TRACE_FLAG_ENABLED(grpc_lb_xds_cluster_resolver_trace)) { gpr_log(GPR_INFO, @@ -660,7 +635,7 @@ void XdsClusterResolverLb::OnEndpointChanged(size_t index, if (!mechanism.first_update_received) return; } // Construct new priority list. - XdsApi::EdsUpdate::PriorityList priority_list; + XdsEndpointResource::PriorityList priority_list; size_t priority_index = 0; for (DiscoveryMechanismEntry& mechanism : discovery_mechanisms_) { // If the mechanism has a pending update, use that. @@ -694,7 +669,7 @@ void XdsClusterResolverLb::OnError(size_t index, grpc_error_handle error) { if (!discovery_mechanisms_[index].first_update_received) { // Call OnEndpointChanged with an empty update just like // OnResourceDoesNotExist. - OnEndpointChanged(index, XdsApi::EdsUpdate()); + OnEndpointChanged(index, XdsEndpointResource()); } } @@ -705,7 +680,7 @@ void XdsClusterResolverLb::OnResourceDoesNotExist(size_t index) { this, index); if (shutting_down_) return; // Call OnEndpointChanged with an empty update. - OnEndpointChanged(index, XdsApi::EdsUpdate()); + OnEndpointChanged(index, XdsEndpointResource()); } // @@ -713,7 +688,7 @@ void XdsClusterResolverLb::OnResourceDoesNotExist(size_t index) { // void XdsClusterResolverLb::UpdatePriorityList( - XdsApi::EdsUpdate::PriorityList priority_list) { + XdsEndpointResource::PriorityList priority_list) { // Build some maps from locality to child number and the reverse from // the old data in priority_list_ and priority_child_numbers_. std::map<XdsLocalityName*, size_t /*child_number*/, XdsLocalityName::Less> @@ -1010,7 +985,6 @@ grpc_channel_args* XdsClusterResolverLb::CreateChildPolicyArgsLocked( grpc_channel_arg_integer_create( const_cast<char*>(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()); } @@ -1050,40 +1024,16 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { public: OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy( LoadBalancingPolicy::Args args) const override { - // Find server name. - const char* server_uri = - grpc_channel_args_find_string(args.args, GRPC_ARG_SERVER_URI); - GPR_ASSERT(server_uri != nullptr); - y_absl::StatusOr<URI> uri = URI::Parse(server_uri); - GPR_ASSERT(uri.ok() && !uri->path().empty()); - y_absl::string_view server_name = y_absl::StripPrefix(uri->path(), "/"); - // Determine if it's an xds URI. - bool is_xds_uri = - uri->scheme() == "xds" || uri->scheme() == "google-c2p-experimental"; - // Get XdsClient. RefCountedPtr<XdsClient> 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; - } + gpr_log(GPR_ERROR, + "XdsClient not present in channel args -- cannot instantiate " + "xds_cluster_resolver LB policy"); + return nullptr; } - return MakeOrphanable<XdsClusterResolverChildHandler>( - std::move(xds_client), std::move(args), server_name, is_xds_uri); + return MakeOrphanable<XdsClusterResolverChildHandler>(std::move(xds_client), + std::move(args)); } const char* name() const override { return kXdsClusterResolver; } @@ -1268,13 +1218,10 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { class XdsClusterResolverChildHandler : public ChildPolicyHandler { public: XdsClusterResolverChildHandler(RefCountedPtr<XdsClient> xds_client, - Args args, y_absl::string_view server_name, - bool is_xds_uri) + Args args) : ChildPolicyHandler(std::move(args), &grpc_lb_xds_cluster_resolver_trace), - xds_client_(std::move(xds_client)), - server_name_(server_name), - is_xds_uri_(is_xds_uri) {} + xds_client_(std::move(xds_client)) {} bool ConfigChangeRequiresNewPolicyInstance( LoadBalancingPolicy::Config* old_config, @@ -1291,14 +1238,11 @@ class XdsClusterResolverLbFactory : public LoadBalancingPolicyFactory { OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy( const char* /*name*/, LoadBalancingPolicy::Args args) const override { - return MakeOrphanable<XdsClusterResolverLb>(xds_client_, std::move(args), - server_name_, is_xds_uri_); + return MakeOrphanable<XdsClusterResolverLb>(xds_client_, std::move(args)); } private: RefCountedPtr<XdsClient> xds_client_; - TString server_name_; - bool is_xds_uri_; }; }; diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc index 151da7be84..468c4a5e76 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc @@ -23,11 +23,11 @@ #include <grpc/support/alloc.h> #include <grpc/support/string_util.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/gpr/string.h" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/resolver/server_address.h" namespace grpc_core { namespace { @@ -46,7 +46,7 @@ class BinderResolver : public Resolver { result.addresses = std::move(addresses_); result.args = channel_args_; channel_args_ = nullptr; - result_handler_->ReturnResult(std::move(result)); + result_handler_->ReportResult(std::move(result)); } void ShutdownLocked() override {} diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc index 26173d8f31..094265e2b7 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc @@ -1,20 +1,18 @@ -/* - * - * 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 <grpc/support/port_platform.h> @@ -37,9 +35,6 @@ #include "src/core/ext/filters/client_channel/lb_policy_registry.h" #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #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/ext/service_config/service_config.h" #include "src/core/lib/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" @@ -50,6 +45,10 @@ #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/json/json.h" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/resolver/server_address.h" +#include "src/core/lib/service_config/service_config.h" +#include "src/core/lib/transport/error_utils.h" #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6 @@ -60,9 +59,9 @@ namespace grpc_core { namespace { -class AresDnsResolver : public Resolver { +class AresClientChannelDNSResolver : public Resolver { public: - explicit AresDnsResolver(ResolverArgs args); + explicit AresClientChannelDNSResolver(ResolverArgs args); void StartLocked() override; @@ -73,7 +72,7 @@ class AresDnsResolver : public Resolver { void ShutdownLocked() override; private: - ~AresDnsResolver() override; + ~AresClientChannelDNSResolver() override; void MaybeStartResolvingLocked(); void StartResolvingLocked(); @@ -127,7 +126,7 @@ class AresDnsResolver : public Resolver { bool shutdown_initiated_ = false; }; -AresDnsResolver::AresDnsResolver(ResolverArgs args) +AresClientChannelDNSResolver::AresClientChannelDNSResolver(ResolverArgs args) : dns_server_(args.uri.authority()), name_to_resolve_(y_absl::StripPrefix(args.uri.path(), "/")), channel_args_(grpc_channel_args_copy(args.args)), @@ -157,48 +156,53 @@ AresDnsResolver::AresDnsResolver(ResolverArgs args) GRPC_CLOSURE_INIT(&on_resolved_, OnResolved, this, grpc_schedule_on_exec_ctx); } -AresDnsResolver::~AresDnsResolver() { - GRPC_CARES_TRACE_LOG("resolver:%p destroying AresDnsResolver", this); +AresClientChannelDNSResolver::~AresClientChannelDNSResolver() { + GRPC_CARES_TRACE_LOG("resolver:%p destroying AresClientChannelDNSResolver", + this); grpc_channel_args_destroy(channel_args_); } -void AresDnsResolver::StartLocked() { - GRPC_CARES_TRACE_LOG("resolver:%p AresDnsResolver::StartLocked() is called.", - this); +void AresClientChannelDNSResolver::StartLocked() { + GRPC_CARES_TRACE_LOG( + "resolver:%p AresClientChannelDNSResolver::StartLocked() is called.", + this); MaybeStartResolvingLocked(); } -void AresDnsResolver::RequestReresolutionLocked() { +void AresClientChannelDNSResolver::RequestReresolutionLocked() { if (!resolving_) { MaybeStartResolvingLocked(); } } -void AresDnsResolver::ResetBackoffLocked() { +void AresClientChannelDNSResolver::ResetBackoffLocked() { if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); } backoff_.Reset(); } -void AresDnsResolver::ShutdownLocked() { +void AresClientChannelDNSResolver::ShutdownLocked() { shutdown_initiated_ = true; if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); } if (pending_request_ != nullptr) { - grpc_cancel_ares_request_locked(pending_request_); + grpc_cancel_ares_request(pending_request_); } } -void AresDnsResolver::OnNextResolution(void* arg, grpc_error_handle error) { - AresDnsResolver* r = static_cast<AresDnsResolver*>(arg); +void AresClientChannelDNSResolver::OnNextResolution(void* arg, + grpc_error_handle error) { + AresClientChannelDNSResolver* r = + static_cast<AresClientChannelDNSResolver*>(arg); (void)GRPC_ERROR_REF(error); // ref owned by lambda r->work_serializer_->Run([r, error]() { r->OnNextResolutionLocked(error); }, DEBUG_LOCATION); } -void AresDnsResolver::OnNextResolutionLocked(grpc_error_handle error) { +void AresClientChannelDNSResolver::OnNextResolutionLocked( + grpc_error_handle error) { GRPC_CARES_TRACE_LOG( "resolver:%p re-resolution timer fired. error: %s. shutdown_initiated_: " "%d", @@ -303,14 +307,16 @@ TString ChooseServiceConfig(char* service_config_choice_json, return service_config->Dump(); } -void AresDnsResolver::OnResolved(void* arg, grpc_error_handle error) { - AresDnsResolver* r = static_cast<AresDnsResolver*>(arg); +void AresClientChannelDNSResolver::OnResolved(void* arg, + grpc_error_handle error) { + AresClientChannelDNSResolver* r = + static_cast<AresClientChannelDNSResolver*>(arg); (void)GRPC_ERROR_REF(error); // ref owned by lambda r->work_serializer_->Run([r, error]() { r->OnResolvedLocked(error); }, DEBUG_LOCATION); } -void AresDnsResolver::OnResolvedLocked(grpc_error_handle error) { +void AresClientChannelDNSResolver::OnResolvedLocked(grpc_error_handle error) { GPR_ASSERT(resolving_); resolving_ = false; delete pending_request_; @@ -320,21 +326,35 @@ void AresDnsResolver::OnResolvedLocked(grpc_error_handle error) { GRPC_ERROR_UNREF(error); return; } + // TODO(roth): Change logic to be able to report failures for addresses + // and service config independently of each other. if (addresses_ != nullptr || balancer_addresses_ != nullptr) { Result result; if (addresses_ != nullptr) { result.addresses = std::move(*addresses_); + } else { + result.addresses = ServerAddressList(); } if (service_config_json_ != nullptr) { - TString service_config_string = ChooseServiceConfig( - service_config_json_, &result.service_config_error); + grpc_error_handle service_config_error = GRPC_ERROR_NONE; + TString service_config_string = + ChooseServiceConfig(service_config_json_, &service_config_error); gpr_free(service_config_json_); - if (result.service_config_error == GRPC_ERROR_NONE && + RefCountedPtr<ServiceConfig> service_config; + if (service_config_error == GRPC_ERROR_NONE && !service_config_string.empty()) { GRPC_CARES_TRACE_LOG("resolver:%p selected service config choice: %s", this, service_config_string.c_str()); - result.service_config = ServiceConfig::Create( - channel_args_, service_config_string, &result.service_config_error); + service_config = ServiceConfig::Create( + channel_args_, service_config_string, &service_config_error); + } + if (service_config_error != GRPC_ERROR_NONE) { + result.service_config = y_absl::UnavailableError( + y_absl::StrCat("failed to parse service config: ", + grpc_error_std_string(service_config_error))); + GRPC_ERROR_UNREF(service_config_error); + } else { + result.service_config = std::move(service_config); } } y_absl::InlinedVector<grpc_arg, 1> new_args; @@ -344,7 +364,7 @@ void AresDnsResolver::OnResolvedLocked(grpc_error_handle error) { } result.args = grpc_channel_args_copy_and_add(channel_args_, new_args.data(), new_args.size()); - result_handler_->ReturnResult(std::move(result)); + result_handler_->ReportResult(std::move(result)); addresses_.reset(); balancer_addresses_.reset(); // Reset backoff state so that we start from the beginning when the @@ -353,12 +373,15 @@ void AresDnsResolver::OnResolvedLocked(grpc_error_handle error) { } else { GRPC_CARES_TRACE_LOG("resolver:%p dns resolution failed: %s", this, grpc_error_std_string(error).c_str()); - TString error_message = - y_absl::StrCat("DNS resolution failed for service: ", name_to_resolve_); - result_handler_->ReturnError(grpc_error_set_int( - GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(error_message.c_str(), - &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); + TString error_message; + grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &error_message); + y_absl::Status status = y_absl::UnavailableError(y_absl::StrCat( + "DNS resolution failed for ", name_to_resolve_, ": ", error_message)); + Result result; + result.addresses = status; + result.service_config = status; + result.args = grpc_channel_args_copy(channel_args_); + result_handler_->ReportResult(std::move(result)); // Set retry timer. // InvalidateNow to avoid getting stuck re-initializing this timer // in a loop while draining the currently-held WorkSerializer. @@ -386,7 +409,7 @@ void AresDnsResolver::OnResolvedLocked(grpc_error_handle error) { GRPC_ERROR_UNREF(error); } -void AresDnsResolver::MaybeStartResolvingLocked() { +void AresClientChannelDNSResolver::MaybeStartResolvingLocked() { // If there is an existing timer, the time it fires is the earliest time we // can start the next resolution. if (have_next_resolution_timer_) return; @@ -420,7 +443,7 @@ void AresDnsResolver::MaybeStartResolvingLocked() { StartResolvingLocked(); } -void AresDnsResolver::StartResolvingLocked() { +void AresClientChannelDNSResolver::StartResolvingLocked() { // TODO(roth): We currently deal with this ref manually. Once the // new closure API is done, find a way to track this ref with the timer // callback as part of the type system. @@ -428,12 +451,12 @@ void AresDnsResolver::StartResolvingLocked() { GPR_ASSERT(!resolving_); resolving_ = true; service_config_json_ = nullptr; - pending_request_ = grpc_dns_lookup_ares_locked( + pending_request_ = grpc_dns_lookup_ares( dns_server_.c_str(), name_to_resolve_.c_str(), kDefaultSecurePort, interested_parties_, &on_resolved_, &addresses_, enable_srv_queries_ ? &balancer_addresses_ : nullptr, request_service_config_ ? &service_config_json_ : nullptr, - query_timeout_ms_, work_serializer_); + query_timeout_ms_); last_resolution_timestamp_ = ExecCtx::Get()->Now(); GRPC_CARES_TRACE_LOG("resolver:%p Started resolving. pending_request_:%p", this, pending_request_); @@ -442,8 +465,7 @@ void AresDnsResolver::StartResolvingLocked() { // // Factory // - -class AresDnsResolverFactory : public ResolverFactory { +class AresClientChannelDNSResolverFactory : public ResolverFactory { public: bool IsValidUri(const URI& uri) const override { if (y_absl::StripPrefix(uri.path(), "/").empty()) { @@ -454,42 +476,149 @@ class AresDnsResolverFactory : public ResolverFactory { } OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override { - return MakeOrphanable<AresDnsResolver>(std::move(args)); + return MakeOrphanable<AresClientChannelDNSResolver>(std::move(args)); } const char* scheme() const override { return "dns"; } }; -} // namespace +class AresDNSResolver : public DNSResolver { + public: + class AresRequest : public DNSResolver::Request { + public: + AresRequest( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* interested_parties, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_resolve_address_done) + : name_(TString(name)), + default_port_(TString(default_port)), + interested_parties_(interested_parties), + on_resolve_address_done_(std::move(on_resolve_address_done)) { + GRPC_CARES_TRACE_LOG("AresRequest:%p ctor", this); + GRPC_CLOSURE_INIT(&on_dns_lookup_done_, OnDnsLookupDone, this, + grpc_schedule_on_exec_ctx); + } -} // namespace grpc_core + ~AresRequest() override { + GRPC_CARES_TRACE_LOG("AresRequest:%p dtor ares_request_:%p", this, + ares_request_.get()); + } -extern grpc_address_resolver_vtable* grpc_resolve_address_impl; -static grpc_address_resolver_vtable* default_resolver; + void Start() override { + y_absl::MutexLock lock(&mu_); + Ref().release(); // ref held by resolution + ares_request_ = std::unique_ptr<grpc_ares_request>(grpc_dns_lookup_ares( + "" /* dns_server */, name_.c_str(), default_port_.c_str(), + interested_parties_, &on_dns_lookup_done_, &addresses_, + nullptr /* balancer_addresses */, nullptr /* service_config_json */, + GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS)); + GRPC_CARES_TRACE_LOG("AresRequest:%p Start ares_request_:%p", this, + ares_request_.get()); + } -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, - addresses); -} + void Orphan() override { + { + y_absl::MutexLock lock(&mu_); + GRPC_CARES_TRACE_LOG("AresRequest:%p Orphan ares_request_:%p", this, + ares_request_.get()); + grpc_cancel_ares_request(ares_request_.get()); + } + Unref(); + } + + private: + static void OnDnsLookupDone(void* arg, grpc_error_handle error) { + AresRequest* r = static_cast<AresRequest*>(arg); + std::vector<grpc_resolved_address> resolved_addresses; + { + y_absl::MutexLock lock(&r->mu_); + GRPC_CARES_TRACE_LOG("AresRequest:%p OnDnsLookupDone error:%s", r, + grpc_error_std_string(error).c_str()); + if (r->addresses_ != nullptr) { + resolved_addresses.reserve(r->addresses_->size()); + for (const auto& server_address : *r->addresses_) { + resolved_addresses.push_back(server_address.address()); + } + } + } + if (error == GRPC_ERROR_NONE) { + // it's safe to run this inline since we've already been scheduled + // on the ExecCtx + r->on_resolve_address_done_(std::move(resolved_addresses)); + } else { + r->on_resolve_address_done_(grpc_error_to_absl_status(error)); + } + r->Unref(); + } + + // mutex to synchronize access to this object (but not to the ares_request + // object itself). + y_absl::Mutex mu_; + // the name to resolve + const TString name_; + // the default port to use if name doesn't have one + const TString default_port_; + // parties interested in our I/O + grpc_pollset_set* const interested_parties_; + // user-provided completion callback + const std::function<void( + y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_resolve_address_done_; + // currently resolving addresses + std::unique_ptr<ServerAddressList> addresses_ Y_ABSL_GUARDED_BY(mu_); + // closure to call when the resolve_address_ares request completes + // a closure wrapping on_resolve_address_done, which should be invoked + // when the grpc_dns_lookup_ares operation is done. + grpc_closure on_dns_lookup_done_ Y_ABSL_GUARDED_BY(mu_); + // underlying ares_request that the query is performed on + std::unique_ptr<grpc_ares_request> ares_request_ Y_ABSL_GUARDED_BY(mu_); + }; + + // gets the singleton instance, possibly creating it first + static AresDNSResolver* GetOrCreate() { + static AresDNSResolver* instance = new AresDNSResolver(); + return instance; + } + + OrphanablePtr<DNSResolver::Request> ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* interested_parties, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) override { + return MakeOrphanable<AresRequest>(name, default_port, interested_parties, + std::move(on_done)); + } + + y_absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking( + y_absl::string_view name, y_absl::string_view default_port) override { + // TODO(apolcyn): change this to wrap the async version of the c-ares + // API with a promise, and remove the reference to the previous resolver. + return default_resolver_->ResolveNameBlocking(name, default_port); + } -static grpc_address_resolver_vtable ares_resolver = { - grpc_resolve_address_ares, blocking_resolve_address_ares}; + private: + // the previous default DNS resolver, used to delegate blocking DNS calls to + DNSResolver* default_resolver_ = GetDNSResolver(); +}; -static bool should_use_ares(const char* resolver_env) { +bool ShouldUseAres(const char* resolver_env) { // TODO(lidiz): Remove the "g_custom_iomgr_enabled" flag once c-ares support // custom IO managers (e.g. gevent). return !g_custom_iomgr_enabled && resolver_env != nullptr && (gpr_stricmp(resolver_env, "ares") == 0); } -static bool g_use_ares_dns_resolver; +bool g_use_ares_dns_resolver; + +} // namespace + +} // namespace grpc_core void grpc_resolver_dns_ares_init() { grpc_core::UniquePtr<char> resolver = GPR_GLOBAL_CONFIG_GET(grpc_dns_resolver); - if (should_use_ares(resolver.get())) { - g_use_ares_dns_resolver = true; + if (grpc_core::ShouldUseAres(resolver.get())) { + grpc_core::g_use_ares_dns_resolver = true; gpr_log(GPR_DEBUG, "Using ares dns resolver"); address_sorting_init(); grpc_error_handle error = grpc_ares_init(); @@ -497,19 +626,16 @@ void grpc_resolver_dns_ares_init() { GRPC_LOG_IF_ERROR("grpc_ares_init() failed", error); return; } - if (default_resolver == nullptr) { - default_resolver = grpc_resolve_address_impl; - } - grpc_set_resolver_impl(&ares_resolver); + grpc_core::SetDNSResolver(grpc_core::AresDNSResolver::GetOrCreate()); grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( - y_absl::make_unique<grpc_core::AresDnsResolverFactory>()); + y_absl::make_unique<grpc_core::AresClientChannelDNSResolverFactory>()); } else { - g_use_ares_dns_resolver = false; + grpc_core::g_use_ares_dns_resolver = false; } } void grpc_resolver_dns_ares_shutdown() { - if (g_use_ares_dns_resolver) { + if (grpc_core::g_use_ares_dns_resolver) { address_sorting_shutdown(); grpc_ares_cleanup(); } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h index 41b3ae0dba..57d0299d4e 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h @@ -23,8 +23,8 @@ #include <ares.h> +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" #include "src/core/lib/iomgr/pollset_set.h" -#include "src/core/lib/iomgr/work_serializer.h" namespace grpc_core { @@ -36,18 +36,23 @@ class GrpcPolledFd { public: virtual ~GrpcPolledFd() {} /* Called when c-ares library is interested and there's no pending callback */ - virtual void RegisterForOnReadableLocked(grpc_closure* read_closure) = 0; + virtual void RegisterForOnReadableLocked(grpc_closure* read_closure) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) = 0; /* Called when c-ares library is interested and there's no pending callback */ - virtual void RegisterForOnWriteableLocked(grpc_closure* write_closure) = 0; + virtual void RegisterForOnWriteableLocked(grpc_closure* write_closure) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) = 0; /* Indicates if there is data left even after just being read from */ - virtual bool IsFdStillReadableLocked() = 0; + virtual bool IsFdStillReadableLocked() + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) = 0; /* Called once and only once. Must cause cancellation of any pending * read/write callbacks. */ - virtual void ShutdownLocked(grpc_error_handle error) = 0; + virtual void ShutdownLocked(grpc_error_handle error) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) = 0; /* Get the underlying ares_socket_t that this was created from */ - virtual ares_socket_t GetWrappedAresSocketLocked() = 0; + virtual ares_socket_t GetWrappedAresSocketLocked() + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) = 0; /* A unique name, for logging */ - virtual const char* GetName() = 0; + virtual const char* GetName() const = 0; }; /* A GrpcPolledFdFactory is 1-to-1 with and owned by the @@ -59,14 +64,19 @@ class GrpcPolledFdFactory { virtual ~GrpcPolledFdFactory() {} /* Creates a new wrapped fd for the current platform */ virtual GrpcPolledFd* NewGrpcPolledFdLocked( - ares_socket_t as, grpc_pollset_set* driver_pollset_set, - std::shared_ptr<WorkSerializer> work_serializer) = 0; + ares_socket_t as, grpc_pollset_set* driver_pollset_set) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) = 0; /* Optionally configures the ares channel after creation */ - virtual void ConfigureAresChannelLocked(ares_channel channel) = 0; + virtual void ConfigureAresChannelLocked(ares_channel channel) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) = 0; }; -std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory( - std::shared_ptr<WorkSerializer> work_serializer); +/* Creates a new polled fd factory. + * Note that even though ownership of mu is not transferred, the mu + * parameter is guaranteed to be alive for the the whole lifetime of + * the resulting GrpcPolledFdFactory as well as any GrpcPolledFd + * returned by the factory. */ +std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(Mutex* mu); } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc index 5f6ab30d1a..afb8ec451e 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc @@ -59,49 +59,53 @@ class GrpcPolledFdPosix : public GrpcPolledFd { grpc_fd_orphan(fd_, nullptr, &phony_release_fd, "c-ares query finished"); } - void RegisterForOnReadableLocked(grpc_closure* read_closure) override { + void RegisterForOnReadableLocked(grpc_closure* read_closure) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) override { grpc_fd_notify_on_read(fd_, read_closure); } - void RegisterForOnWriteableLocked(grpc_closure* write_closure) override { + void RegisterForOnWriteableLocked(grpc_closure* write_closure) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) override { grpc_fd_notify_on_write(fd_, write_closure); } - bool IsFdStillReadableLocked() override { + bool IsFdStillReadableLocked() + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) override { size_t bytes_available = 0; return ioctl(grpc_fd_wrapped_fd(fd_), FIONREAD, &bytes_available) == 0 && bytes_available > 0; } - void ShutdownLocked(grpc_error_handle error) override { + void ShutdownLocked(grpc_error_handle error) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) override { grpc_fd_shutdown(fd_, error); } - ares_socket_t GetWrappedAresSocketLocked() override { return as_; } + ares_socket_t GetWrappedAresSocketLocked() + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) override { + return as_; + } - const char* GetName() override { return name_.c_str(); } + const char* GetName() const override { return name_.c_str(); } private: - TString name_; - ares_socket_t as_; - grpc_fd* fd_; - grpc_pollset_set* driver_pollset_set_; + const TString name_; + const ares_socket_t as_; + grpc_fd* fd_ Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); + grpc_pollset_set* driver_pollset_set_ Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); }; class GrpcPolledFdFactoryPosix : public GrpcPolledFdFactory { public: GrpcPolledFd* NewGrpcPolledFdLocked( - ares_socket_t as, grpc_pollset_set* driver_pollset_set, - std::shared_ptr<WorkSerializer> /*work_serializer*/) override { + ares_socket_t as, grpc_pollset_set* driver_pollset_set) override { return new GrpcPolledFdPosix(as, driver_pollset_set); } void ConfigureAresChannelLocked(ares_channel /*channel*/) override {} }; -std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory( - std::shared_ptr<WorkSerializer> work_serializer) { - (void)work_serializer; +std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(Mutex* /* mu */) { return y_absl::make_unique<GrpcPolledFdFactoryPosix>(); } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc index ce843af2e0..82a50835d6 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc @@ -41,7 +41,6 @@ #include "src/core/lib/iomgr/sockaddr_windows.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_windows.h" -#include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/slice/slice_internal.h" /* TODO(apolcyn): remove this hack after fixing upstream. @@ -100,10 +99,9 @@ class GrpcPolledFdWindows { WRITE_WAITING_FOR_VERIFICATION_UPON_RETRY, }; - GrpcPolledFdWindows(ares_socket_t as, - std::shared_ptr<WorkSerializer> work_serializer, - int address_family, int socket_type) - : work_serializer_(std::move(work_serializer)), + GrpcPolledFdWindows(ares_socket_t as, Mutex* mu, int address_family, + int socket_type) + : mu_(mu), read_buf_(grpc_empty_slice()), write_buf_(grpc_empty_slice()), tcp_write_state_(WRITE_IDLE), @@ -260,7 +258,7 @@ class GrpcPolledFdWindows { return grpc_winsocket_wrapped_socket(winsocket_); } - const char* GetName() { return name_.c_str(); } + const char* GetName() const { return name_.c_str(); } ares_ssize_t RecvFrom(WSAErrorContext* wsa_error_ctx, void* data, ares_socket_t data_len, int flags, @@ -422,12 +420,8 @@ class GrpcPolledFdWindows { static void OnTcpConnect(void* arg, grpc_error_handle error) { GrpcPolledFdWindows* grpc_polled_fd = static_cast<GrpcPolledFdWindows*>(arg); - (void)GRPC_ERROR_REF(error); // ref owned by lambda - grpc_polled_fd->work_serializer_->Run( - [grpc_polled_fd, error]() { - grpc_polled_fd->OnTcpConnectLocked(error); - }, - DEBUG_LOCATION); + MutexLock lock(grpc_polled_fd->mu_); + grpc_polled_fd->OnTcpConnectLocked(error); } void OnTcpConnectLocked(grpc_error_handle error) { @@ -469,7 +463,6 @@ class GrpcPolledFdWindows { if (pending_continue_register_for_on_writeable_locked_) { ContinueRegisterForOnWriteableLocked(); } - GRPC_ERROR_UNREF(error); } int Connect(WSAErrorContext* wsa_error_ctx, const struct sockaddr* target, @@ -575,10 +568,9 @@ class GrpcPolledFdWindows { static void OnIocpReadable(void* arg, grpc_error_handle error) { GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg); - (void)GRPC_ERROR_REF(error); // ref owned by lambda - polled_fd->work_serializer_->Run( - [polled_fd, error]() { polled_fd->OnIocpReadableLocked(error); }, - DEBUG_LOCATION); + (void)GRPC_ERROR_REF(error); + MutexLock lock(polled_fd->mu_); + polled_fd->OnIocpReadableLocked(error); } // TODO(apolcyn): improve this error handling to be less conversative. @@ -620,10 +612,9 @@ class GrpcPolledFdWindows { static void OnIocpWriteable(void* arg, grpc_error_handle error) { GrpcPolledFdWindows* polled_fd = static_cast<GrpcPolledFdWindows*>(arg); - (void)GRPC_ERROR_REF(error); // error owned by lambda - polled_fd->work_serializer_->Run( - [polled_fd, error]() { polled_fd->OnIocpWriteableLocked(error); }, - DEBUG_LOCATION); + (void)GRPC_ERROR_REF(error); + MutexLock lock(polled_fd->mu_); + polled_fd->OnIocpWriteableLocked(error); } void OnIocpWriteableLocked(grpc_error_handle error) { @@ -658,7 +649,7 @@ class GrpcPolledFdWindows { void set_gotten_into_driver_list() { gotten_into_driver_list_ = true; } private: - std::shared_ptr<WorkSerializer> work_serializer_; + Mutex* mu_; char recv_from_source_addr_[200]; ares_socklen_t recv_from_source_addr_len_; grpc_slice read_buf_; @@ -671,7 +662,7 @@ class GrpcPolledFdWindows { grpc_winsocket* winsocket_; // tcp_write_state_ is only used on TCP GrpcPolledFds WriteState tcp_write_state_; - TString name_; + const TString name_; bool gotten_into_driver_list_; int address_family_; int socket_type_; @@ -700,8 +691,7 @@ struct SockToPolledFdEntry { * with a GrpcPolledFdWindows factory and event driver */ class SockToPolledFdMap { public: - explicit SockToPolledFdMap(std::shared_ptr<WorkSerializer> work_serializer) - : work_serializer_(std::move(work_serializer)) {} + explicit SockToPolledFdMap(Mutex* mu) : mu_(mu) {} ~SockToPolledFdMap() { GPR_ASSERT(head_ == nullptr); } @@ -759,7 +749,7 @@ class SockToPolledFdMap { } grpc_tcp_set_non_block(s); GrpcPolledFdWindows* polled_fd = - new GrpcPolledFdWindows(s, map->work_serializer_, af, type); + new GrpcPolledFdWindows(s, map->mu_, af, type); GRPC_CARES_TRACE_LOG( "fd:|%s| created with params af:%d type:%d protocol:%d", polled_fd->GetName(), af, type, protocol); @@ -814,8 +804,8 @@ class SockToPolledFdMap { } private: + Mutex* mu_; SockToPolledFdEntry* head_ = nullptr; - std::shared_ptr<WorkSerializer> work_serializer_; }; const struct ares_socket_functions custom_ares_sock_funcs = { @@ -856,21 +846,18 @@ class GrpcPolledFdWindowsWrapper : public GrpcPolledFd { return wrapped_->GetWrappedAresSocketLocked(); } - const char* GetName() override { return wrapped_->GetName(); } + const char* GetName() const override { return wrapped_->GetName(); } private: - GrpcPolledFdWindows* wrapped_; + GrpcPolledFdWindows* const wrapped_; }; class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory { public: - explicit GrpcPolledFdFactoryWindows( - std::shared_ptr<WorkSerializer> work_serializer) - : sock_to_polled_fd_map_(std::move(work_serializer)) {} + explicit GrpcPolledFdFactoryWindows(Mutex* mu) : sock_to_polled_fd_map_(mu) {} GrpcPolledFd* NewGrpcPolledFdLocked( - ares_socket_t as, grpc_pollset_set* driver_pollset_set, - std::shared_ptr<WorkSerializer> work_serializer) override { + ares_socket_t as, grpc_pollset_set* driver_pollset_set) override { GrpcPolledFdWindows* polled_fd = sock_to_polled_fd_map_.LookupPolledFd(as); // Set a flag so that the virtual socket "close" method knows it // doesn't need to call ShutdownLocked, since now the driver will. @@ -887,10 +874,8 @@ class GrpcPolledFdFactoryWindows : public GrpcPolledFdFactory { SockToPolledFdMap sock_to_polled_fd_map_; }; -std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory( - std::shared_ptr<WorkSerializer> work_serializer) { - return y_absl::make_unique<GrpcPolledFdFactoryWindows>( - std::move(work_serializer)); +std::unique_ptr<GrpcPolledFdFactory> NewGrpcPolledFdFactory(Mutex* mu) { + return y_absl::make_unique<GrpcPolledFdFactoryWindows>(mu); } } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc index f21f27830e..e420e3727a 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc @@ -57,55 +57,63 @@ grpc_core::TraceFlag grpc_trace_cares_address_sorting(false, grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver"); typedef struct fd_node { + /* default constructor exists only for linked list manipulation */ + fd_node() : ev_driver(nullptr) {} + + explicit fd_node(grpc_ares_ev_driver* ev_driver) : ev_driver(ev_driver) {} + /** the owner of this fd node */ - grpc_ares_ev_driver* ev_driver; + grpc_ares_ev_driver* const ev_driver; /** a closure wrapping on_readable_locked, which should be invoked when the grpc_fd in this node becomes readable. */ - grpc_closure read_closure; + grpc_closure read_closure Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** a closure wrapping on_writable_locked, which should be invoked when the grpc_fd in this node becomes writable. */ - grpc_closure write_closure; + grpc_closure write_closure Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** next fd node in the list */ - struct fd_node* next; + struct fd_node* next Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** wrapped fd that's polled by grpc's poller for the current platform */ - grpc_core::GrpcPolledFd* grpc_polled_fd; + grpc_core::GrpcPolledFd* grpc_polled_fd + Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** if the readable closure has been registered */ - bool readable_registered; + bool readable_registered Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** if the writable closure has been registered */ - bool writable_registered; + bool writable_registered Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** if the fd has been shutdown yet from grpc iomgr perspective */ - bool already_shutdown; + bool already_shutdown Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); } fd_node; struct grpc_ares_ev_driver { + explicit grpc_ares_ev_driver(grpc_ares_request* request) : request(request) {} + /** the ares_channel owned by this event driver */ - ares_channel channel; + ares_channel channel Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** pollset set for driving the IO events of the channel */ - grpc_pollset_set* pollset_set; + grpc_pollset_set* pollset_set Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** refcount of the event driver */ gpr_refcount refs; - /** work_serializer to synchronize c-ares and I/O callbacks on */ - std::shared_ptr<grpc_core::WorkSerializer> work_serializer; /** a list of grpc_fd that this event driver is currently using. */ - fd_node* fds; + fd_node* fds Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** is this event driver being shut down */ - bool shutting_down; + bool shutting_down Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** request object that's using this ev driver */ - grpc_ares_request* request; + grpc_ares_request* const request; /** Owned by the ev_driver. Creates new GrpcPolledFd's */ - std::unique_ptr<grpc_core::GrpcPolledFdFactory> polled_fd_factory; + std::unique_ptr<grpc_core::GrpcPolledFdFactory> polled_fd_factory + Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** query timeout in milliseconds */ - int query_timeout_ms; + int query_timeout_ms Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** alarm to cancel active queries */ - grpc_timer query_timeout; + grpc_timer query_timeout Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** cancels queries on a timeout */ - grpc_closure on_timeout_locked; + grpc_closure on_timeout_locked Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** alarm to poll ares_process on in case fd events don't happen */ - grpc_timer ares_backup_poll_alarm; + grpc_timer ares_backup_poll_alarm Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); /** polls ares_process on a periodic timer */ - grpc_closure on_ares_backup_poll_alarm_locked; + grpc_closure on_ares_backup_poll_alarm_locked + Y_ABSL_GUARDED_BY(&grpc_ares_request::mu); }; // TODO(apolcyn): make grpc_ares_hostbyname_request a sub-class @@ -125,8 +133,10 @@ typedef struct grpc_ares_hostbyname_request { const char* qtype; } grpc_ares_hostbyname_request; -static void grpc_ares_request_ref_locked(grpc_ares_request* r); -static void grpc_ares_request_unref_locked(grpc_ares_request* r); +static void grpc_ares_request_ref_locked(grpc_ares_request* r) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu); +static void grpc_ares_request_unref_locked(grpc_ares_request* r) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu); // TODO(apolcyn): as a part of C++-ification, find a way to // organize per-query and per-resolution information in such a way @@ -153,14 +163,19 @@ class GrpcAresQuery { }; static grpc_ares_ev_driver* grpc_ares_ev_driver_ref( - grpc_ares_ev_driver* ev_driver) { + grpc_ares_ev_driver* ev_driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { GRPC_CARES_TRACE_LOG("request:%p Ref ev_driver %p", ev_driver->request, ev_driver); gpr_ref(&ev_driver->refs); return ev_driver; } -static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) { +static void grpc_ares_complete_request_locked(grpc_ares_request* r) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu); + +static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { GRPC_CARES_TRACE_LOG("request:%p Unref ev_driver %p", ev_driver->request, ev_driver); if (gpr_unref(&ev_driver->refs)) { @@ -173,17 +188,19 @@ static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver) { } } -static void fd_node_destroy_locked(fd_node* fdn) { +static void fd_node_destroy_locked(fd_node* fdn) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { GRPC_CARES_TRACE_LOG("request:%p delete fd: %s", fdn->ev_driver->request, fdn->grpc_polled_fd->GetName()); GPR_ASSERT(!fdn->readable_registered); GPR_ASSERT(!fdn->writable_registered); GPR_ASSERT(fdn->already_shutdown); delete fdn->grpc_polled_fd; - gpr_free(fdn); + delete fdn; } -static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) { +static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { if (!fdn->already_shutdown) { fdn->already_shutdown = true; fdn->grpc_polled_fd->ShutdownLocked( @@ -192,7 +209,8 @@ static void fd_node_shutdown_locked(fd_node* fdn, const char* reason) { } void grpc_ares_ev_driver_on_queries_complete_locked( - grpc_ares_ev_driver* ev_driver) { + grpc_ares_ev_driver* ev_driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { // We mark the event driver as being shut down. // grpc_ares_notify_on_event_locked will shut down any remaining // fds. @@ -202,7 +220,8 @@ void grpc_ares_ev_driver_on_queries_complete_locked( grpc_ares_ev_driver_unref(ev_driver); } -void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) { +void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { ev_driver->shutting_down = true; fd_node* fn = ev_driver->fds; while (fn != nullptr) { @@ -213,7 +232,8 @@ void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) { // Search fd in the fd_node list head. This is an O(n) search, the max possible // value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests. -static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) { +static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { fd_node phony_head; phony_head.next = *head; fd_node* node = &phony_head; @@ -230,7 +250,8 @@ static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) { } static grpc_millis calculate_next_ares_backup_poll_alarm_ms( - grpc_ares_ev_driver* driver) { + grpc_ares_ev_driver* driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { // An alternative here could be to use ares_timeout to try to be more // accurate, but that would require using "struct timeval"'s, which just makes // things a bit more complicated. So just poll every second, as suggested @@ -244,8 +265,9 @@ 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_handle error) { +static void on_timeout(void* arg, grpc_error_handle error) { + grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg); + grpc_core::MutexLock lock(&driver->request->mu); GRPC_CARES_TRACE_LOG( "request:%p ev_driver=%p on_timeout_locked. driver->shutting_down=%d. " "err=%s", @@ -255,28 +277,10 @@ static void on_timeout_locked(grpc_ares_ev_driver* driver, grpc_ares_ev_driver_shutdown_locked(driver); } grpc_ares_ev_driver_unref(driver); - GRPC_ERROR_UNREF(error); } -static void on_timeout(void* arg, grpc_error_handle error) { - grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg); - (void)GRPC_ERROR_REF(error); // ref owned by lambda - driver->work_serializer->Run( - [driver, error]() { on_timeout_locked(driver, error); }, DEBUG_LOCATION); -} - -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_handle error); - -static void on_ares_backup_poll_alarm(void* arg, grpc_error_handle error) { - grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg); - (void)GRPC_ERROR_REF(error); - driver->work_serializer->Run( - [driver, error]() { on_ares_backup_poll_alarm_locked(driver, error); }, - DEBUG_LOCATION); -} +static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu); /* In case of non-responsive DNS servers, dropped packets, etc., c-ares has * intelligent timeout and retry logic, which we can take advantage of by @@ -286,8 +290,9 @@ static void on_ares_backup_poll_alarm(void* arg, grpc_error_handle error) { * b) when some time has passed without fd events having happened * 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_handle error) { +static void on_ares_backup_poll_alarm(void* arg, grpc_error_handle error) { + grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg); + grpc_core::MutexLock lock(&driver->request->mu); GRPC_CARES_TRACE_LOG( "request:%p ev_driver=%p on_ares_backup_poll_alarm_locked. " "driver->shutting_down=%d. " @@ -325,10 +330,11 @@ static void on_ares_backup_poll_alarm_locked(grpc_ares_ev_driver* driver, grpc_ares_notify_on_event_locked(driver); } grpc_ares_ev_driver_unref(driver); - GRPC_ERROR_UNREF(error); } -static void on_readable_locked(fd_node* fdn, grpc_error_handle error) { +static void on_readable(void* arg, grpc_error_handle error) { + fd_node* fdn = static_cast<fd_node*>(arg); + grpc_core::MutexLock lock(&fdn->ev_driver->request->mu); GPR_ASSERT(fdn->readable_registered); grpc_ares_ev_driver* ev_driver = fdn->ev_driver; const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); @@ -350,17 +356,11 @@ static void on_readable_locked(fd_node* fdn, grpc_error_handle error) { } grpc_ares_notify_on_event_locked(ev_driver); grpc_ares_ev_driver_unref(ev_driver); - GRPC_ERROR_UNREF(error); } -static void on_readable(void* arg, grpc_error_handle error) { +static void on_writable(void* arg, grpc_error_handle error) { fd_node* fdn = static_cast<fd_node*>(arg); - (void)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_handle error) { + grpc_core::MutexLock lock(&fdn->ev_driver->request->mu); GPR_ASSERT(fdn->writable_registered); grpc_ares_ev_driver* ev_driver = fdn->ev_driver; const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked(); @@ -380,19 +380,12 @@ static void on_writable_locked(fd_node* fdn, grpc_error_handle error) { } grpc_ares_notify_on_event_locked(ev_driver); grpc_ares_ev_driver_unref(ev_driver); - GRPC_ERROR_UNREF(error); -} - -static void on_writable(void* arg, grpc_error_handle error) { - fd_node* fdn = static_cast<fd_node*>(arg); - (void)GRPC_ERROR_REF(error); /* ref owned by lambda */ - fdn->ev_driver->work_serializer->Run( - [fdn, error]() { on_writable_locked(fdn, error); }, DEBUG_LOCATION); } // Get the file descriptors used by the ev_driver's ares channel, register // driver_closure with these filedescriptors. -static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) { +static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { fd_node* new_list = nullptr; if (!ev_driver->shutting_down) { ares_socket_t socks[ARES_GETSOCK_MAXNUM]; @@ -404,13 +397,12 @@ static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) { fd_node* fdn = pop_fd_node_locked(&ev_driver->fds, socks[i]); // Create a new fd_node if sock[i] is not in the fd_node list. if (fdn == nullptr) { - fdn = static_cast<fd_node*>(gpr_malloc(sizeof(fd_node))); + fdn = new fd_node(ev_driver); fdn->grpc_polled_fd = ev_driver->polled_fd_factory->NewGrpcPolledFdLocked( - socks[i], ev_driver->pollset_set, ev_driver->work_serializer); + socks[i], ev_driver->pollset_set); GRPC_CARES_TRACE_LOG("request:%p new fd: %s", ev_driver->request, fdn->grpc_polled_fd->GetName()); - fdn->ev_driver = ev_driver; fdn->readable_registered = false; fdn->writable_registered = false; fdn->already_shutdown = false; @@ -466,7 +458,8 @@ static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver) { ev_driver->fds = new_list; } -void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) { +void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) { grpc_ares_notify_on_event_locked(ev_driver); // Initialize overall DNS resolution timeout alarm grpc_millis timeout = @@ -501,10 +494,9 @@ void (*grpc_ares_test_only_inject_config)(ares_channel channel) = 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<grpc_core::WorkSerializer> work_serializer, - grpc_ares_request* request) { - *ev_driver = new grpc_ares_ev_driver(); + int query_timeout_ms, grpc_ares_request* request) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(request->mu) { + *ev_driver = new grpc_ares_ev_driver(request); ares_options opts; memset(&opts, 0, sizeof(opts)); opts.flags |= ARES_FLAG_STAYOPEN; @@ -514,17 +506,15 @@ grpc_error_handle grpc_ares_ev_driver_create_locked( if (status != ARES_SUCCESS) { grpc_error_handle err = GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( "Failed to init ares channel. C-ares error: ", ares_strerror(status))); - gpr_free(*ev_driver); + delete *ev_driver; return err; } - (*ev_driver)->work_serializer = std::move(work_serializer); gpr_ref_init(&(*ev_driver)->refs, 1); (*ev_driver)->pollset_set = pollset_set; (*ev_driver)->fds = nullptr; (*ev_driver)->shutting_down = false; - (*ev_driver)->request = request; (*ev_driver)->polled_fd_factory = - grpc_core::NewGrpcPolledFdFactory((*ev_driver)->work_serializer); + grpc_core::NewGrpcPolledFdFactory(&(*ev_driver)->request->mu); (*ev_driver) ->polled_fd_factory->ConfigureAresChannelLocked((*ev_driver)->channel); (*ev_driver)->query_timeout_ms = query_timeout_ms; @@ -570,18 +560,21 @@ void grpc_cares_wrapper_address_sorting_sort(const grpc_ares_request* r, } } -static void grpc_ares_request_ref_locked(grpc_ares_request* r) { +static void grpc_ares_request_ref_locked(grpc_ares_request* r) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) { r->pending_queries++; } -static void grpc_ares_request_unref_locked(grpc_ares_request* r) { +static void grpc_ares_request_unref_locked(grpc_ares_request* r) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) { r->pending_queries--; if (r->pending_queries == 0u) { grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver); } } -void grpc_ares_complete_request_locked(grpc_ares_request* r) { +void grpc_ares_complete_request_locked(grpc_ares_request* r) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) { /* Invoke on_done callback and destroy the request */ r->ev_driver = nullptr; @@ -606,7 +599,8 @@ void grpc_ares_complete_request_locked(grpc_ares_request* r) { * qtype must outlive it. */ static grpc_ares_hostbyname_request* create_hostbyname_request_locked( grpc_ares_request* parent_request, const char* host, uint16_t port, - bool is_balancer, const char* qtype) { + bool is_balancer, const char* qtype) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_request->mu) { GRPC_CARES_TRACE_LOG( "request:%p create_hostbyname_request_locked host:%s port:%d " "is_balancer:%d qtype:%s", @@ -621,15 +615,18 @@ static grpc_ares_hostbyname_request* create_hostbyname_request_locked( return hr; } -static void destroy_hostbyname_request_locked( - grpc_ares_hostbyname_request* hr) { +static void destroy_hostbyname_request_locked(grpc_ares_hostbyname_request* hr) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(hr->parent_request->mu) { grpc_ares_request_unref_locked(hr->parent_request); gpr_free(hr->host); delete hr; } static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/, - struct hostent* hostent) { + struct hostent* hostent) + Y_ABSL_NO_THREAD_SAFETY_ANALYSIS { + // This callback is invoked from the c-ares library, so disable thread safety + // analysis. Note that we are guaranteed to be holding r->mu, though. grpc_ares_hostbyname_request* hr = static_cast<grpc_ares_hostbyname_request*>(arg); grpc_ares_request* r = hr->parent_request; @@ -702,7 +699,10 @@ static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/, } static void on_srv_query_done_locked(void* arg, int status, int /*timeouts*/, - unsigned char* abuf, int alen) { + unsigned char* abuf, + int alen) Y_ABSL_NO_THREAD_SAFETY_ANALYSIS { + // This callback is invoked from the c-ares library, so disable thread safety + // analysis. Note that we are guaranteed to be holding r->mu, though. GrpcAresQuery* q = static_cast<GrpcAresQuery*>(arg); grpc_ares_request* r = q->parent_request(); if (status == ARES_SUCCESS) { @@ -749,7 +749,10 @@ static void on_srv_query_done_locked(void* arg, int status, int /*timeouts*/, static const char g_service_config_attribute_prefix[] = "grpc_config="; static void on_txt_done_locked(void* arg, int status, int /*timeouts*/, - unsigned char* buf, int len) { + unsigned char* buf, + int len) Y_ABSL_NO_THREAD_SAFETY_ANALYSIS { + // This callback is invoked from the c-ares library, so disable thread safety + // analysis. Note that we are guaranteed to be holding r->mu, though. GrpcAresQuery* q = static_cast<GrpcAresQuery*>(arg); std::unique_ptr<GrpcAresQuery> query_deleter(q); grpc_ares_request* r = q->parent_request(); @@ -806,8 +809,7 @@ fail: void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( grpc_ares_request* r, const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, - int query_timeout_ms, - std::shared_ptr<grpc_core::WorkSerializer> work_serializer) { + int query_timeout_ms) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) { grpc_error_handle error = GRPC_ERROR_NONE; grpc_ares_hostbyname_request* hr = nullptr; /* parse name, splitting it into host and port parts */ @@ -820,7 +822,7 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( GRPC_ERROR_STR_TARGET_ADDRESS, name); goto error_cleanup; } else if (port.empty()) { - if (default_port == nullptr) { + if (default_port == nullptr || strlen(default_port) == 0) { error = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"), GRPC_ERROR_STR_TARGET_ADDRESS, name); @@ -829,8 +831,7 @@ void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( port = default_port; } error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties, - query_timeout_ms, - std::move(work_serializer), r); + query_timeout_ms, r); if (error != GRPC_ERROR_NONE) goto error_cleanup; // If dns_server is specified, use it. if (dns_server != nullptr && dns_server[0] != '\0') { @@ -912,7 +913,7 @@ static bool inner_resolve_as_ip_literal_locked( return false; } if (port->empty()) { - if (default_port == nullptr) { + if (default_port == nullptr || strlen(default_port) == 0) { gpr_log(GPR_ERROR, "No port or default port for %s while attempting to resolve as " "ip literal.", @@ -975,7 +976,7 @@ static bool inner_maybe_resolve_localhost_manually_locked( return false; } if (port->empty()) { - if (default_port == nullptr) { + if (default_port == nullptr || strlen(default_port) == 0) { gpr_log(GPR_ERROR, "No port or default port for %s during manual localhost " "resolution check.", @@ -1029,21 +1030,21 @@ static bool grpc_ares_maybe_resolve_localhost_manually_locked( } #endif /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */ -static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( +static grpc_ares_request* grpc_dns_lookup_ares_impl( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, std::unique_ptr<grpc_core::ServerAddressList>* addrs, std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs, - char** service_config_json, int query_timeout_ms, - std::shared_ptr<grpc_core::WorkSerializer> work_serializer) { + char** service_config_json, int query_timeout_ms) { grpc_ares_request* r = new grpc_ares_request(); + grpc_core::MutexLock lock(&r->mu); r->ev_driver = nullptr; r->on_done = on_done; r->addresses_out = addrs; r->balancer_addresses_out = balancer_addrs; r->service_config_json_out = service_config_json; GRPC_CARES_TRACE_LOG( - "request:%p c-ares grpc_dns_lookup_ares_locked_impl name=%s, " + "request:%p c-ares grpc_dns_lookup_ares_impl name=%s, " "default_port=%s", r, name, default_port); // Early out if the target is an ipv4 or ipv6 literal. @@ -1066,29 +1067,30 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl( } // Look up name using c-ares lib. grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked( - r, dns_server, name, default_port, interested_parties, query_timeout_ms, - std::move(work_serializer)); + r, dns_server, name, default_port, interested_parties, query_timeout_ms); return r; } -grpc_ares_request* (*grpc_dns_lookup_ares_locked)( +grpc_ares_request* (*grpc_dns_lookup_ares)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, std::unique_ptr<grpc_core::ServerAddressList>* addrs, std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs, - char** service_config_json, int query_timeout_ms, - std::shared_ptr<grpc_core::WorkSerializer> work_serializer) = - grpc_dns_lookup_ares_locked_impl; + char** service_config_json, + int query_timeout_ms) = grpc_dns_lookup_ares_impl; -static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) { +static void grpc_cancel_ares_request_impl(grpc_ares_request* r) { GPR_ASSERT(r != nullptr); + grpc_core::MutexLock lock(&r->mu); + GRPC_CARES_TRACE_LOG("request:%p grpc_cancel_ares_request ev_driver:%p", r, + r->ev_driver); if (r->ev_driver != nullptr) { grpc_ares_ev_driver_shutdown_locked(r->ev_driver); } } -void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) = - grpc_cancel_ares_request_locked_impl; +void (*grpc_cancel_ares_request)(grpc_ares_request* r) = + grpc_cancel_ares_request_impl; // ares_library_init and ares_library_cleanup are currently no-op except under // Windows. Calling them may cause race conditions when other parts of the @@ -1109,95 +1111,4 @@ grpc_error_handle grpc_ares_init(void) { return GRPC_ERROR_NONE; } void grpc_ares_cleanup(void) {} #endif // GPR_WINDOWS -/* - * grpc_resolve_address_ares related structs and functions - */ - -typedef struct grpc_resolve_address_ares_request { - /* work_serializer that queries and related callbacks run under */ - std::shared_ptr<grpc_core::WorkSerializer> work_serializer; - /** the pointer to receive the resolved addresses */ - grpc_resolved_addresses** addrs_out; - /** currently resolving addresses */ - std::unique_ptr<ServerAddressList> addresses; - /** closure to call when the resolve_address_ares request completes */ - grpc_closure* on_resolve_address_done; - /** a closure wrapping on_resolve_address_done, which should be invoked when - the grpc_dns_lookup_ares_locked operation is done. */ - grpc_closure on_dns_lookup_done_locked; - /* target name */ - const char* name; - /* default port to use if none is specified */ - const char* default_port; - /* pollset_set to be driven by */ - grpc_pollset_set* interested_parties; - /* underlying ares_request that the query is performed on */ - grpc_ares_request* ares_request = nullptr; -} grpc_resolve_address_ares_request; - -static void on_dns_lookup_done_locked(grpc_resolve_address_ares_request* r, - grpc_error_handle error) { - delete r->ares_request; - grpc_resolved_addresses** resolved_addresses = r->addrs_out; - if (r->addresses == nullptr || r->addresses->empty()) { - *resolved_addresses = nullptr; - } else { - *resolved_addresses = static_cast<grpc_resolved_addresses*>( - gpr_zalloc(sizeof(grpc_resolved_addresses))); - (*resolved_addresses)->naddrs = r->addresses->size(); - (*resolved_addresses)->addrs = - static_cast<grpc_resolved_address*>(gpr_zalloc( - sizeof(grpc_resolved_address) * (*resolved_addresses)->naddrs)); - for (size_t i = 0; i < (*resolved_addresses)->naddrs; ++i) { - memcpy(&(*resolved_addresses)->addrs[i], &(*r->addresses)[i].address(), - sizeof(grpc_resolved_address)); - } - } - grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_resolve_address_done, error); - delete r; -} - -static void on_dns_lookup_done(void* arg, grpc_error_handle error) { - grpc_resolve_address_ares_request* r = - static_cast<grpc_resolve_address_ares_request*>(arg); - (void)GRPC_ERROR_REF(error); // ref owned by lambda - r->work_serializer->Run([r, error]() { on_dns_lookup_done_locked(r, error); }, - DEBUG_LOCATION); -} - -static void grpc_resolve_address_invoke_dns_lookup_ares_locked(void* arg) { - grpc_resolve_address_ares_request* r = - static_cast<grpc_resolve_address_ares_request*>(arg); - GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done, r, - grpc_schedule_on_exec_ctx); - r->ares_request = grpc_dns_lookup_ares_locked( - nullptr /* dns_server */, r->name, r->default_port, r->interested_parties, - &r->on_dns_lookup_done_locked, &r->addresses, - nullptr /* balancer_addresses */, nullptr /* service_config_json */, - GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS, r->work_serializer); -} - -static void grpc_resolve_address_ares_impl(const char* name, - const char* default_port, - grpc_pollset_set* interested_parties, - grpc_closure* on_done, - grpc_resolved_addresses** addrs) { - grpc_resolve_address_ares_request* r = - new grpc_resolve_address_ares_request(); - r->work_serializer = std::make_shared<grpc_core::WorkSerializer>(); - r->addrs_out = addrs; - r->on_resolve_address_done = on_done; - r->name = name; - r->default_port = default_port; - r->interested_parties = interested_parties; - r->work_serializer->Run( - [r]() { grpc_resolve_address_invoke_dns_lookup_ares_locked(r); }, - DEBUG_LOCATION); -} - -void (*grpc_resolve_address_ares)( - const char* name, const char* default_port, - grpc_pollset_set* interested_parties, grpc_closure* on_done, - grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl; - #endif /* GRPC_ARES == 1 */ diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h index cfc0e2b60f..3d92548a97 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h @@ -23,11 +23,11 @@ #include <ares.h> -#include "src/core/ext/filters/client_channel/server_address.h" #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/work_serializer.h" +#include "src/core/lib/resolver/server_address.h" #define GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS 120000 @@ -45,54 +45,51 @@ extern grpc_core::TraceFlag grpc_trace_cares_resolver; typedef struct grpc_ares_ev_driver grpc_ares_ev_driver; struct grpc_ares_request { + /** synchronizes access to this request, and also to associated + * ev_driver and fd_node objects */ + grpc_core::Mutex mu; /** indicates the DNS server to use, if specified */ - struct ares_addr_port_node dns_server_addr; + struct ares_addr_port_node dns_server_addr Y_ABSL_GUARDED_BY(mu); /** following members are set in grpc_resolve_address_ares_impl */ /** closure to call when the request completes */ - grpc_closure* on_done = nullptr; + grpc_closure* on_done Y_ABSL_GUARDED_BY(mu) = nullptr; /** the pointer to receive the resolved addresses */ - std::unique_ptr<grpc_core::ServerAddressList>* addresses_out; + std::unique_ptr<grpc_core::ServerAddressList>* addresses_out + Y_ABSL_GUARDED_BY(mu); /** the pointer to receive the resolved balancer addresses */ - std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses_out; + std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses_out + Y_ABSL_GUARDED_BY(mu); /** the pointer to receive the service config in JSON */ - char** service_config_json_out = nullptr; + char** service_config_json_out Y_ABSL_GUARDED_BY(mu) = nullptr; /** the evernt driver used by this request */ - grpc_ares_ev_driver* ev_driver = nullptr; + grpc_ares_ev_driver* ev_driver Y_ABSL_GUARDED_BY(mu) = nullptr; /** number of ongoing queries */ - size_t pending_queries = 0; + size_t pending_queries Y_ABSL_GUARDED_BY(mu) = 0; /** the errors explaining query failures, appended to in query callbacks */ - grpc_error_handle error = GRPC_ERROR_NONE; + grpc_error_handle error Y_ABSL_GUARDED_BY(mu) = GRPC_ERROR_NONE; }; -/* Asynchronously resolve \a name. Use \a default_port if a port isn't - designated in \a name, otherwise use the port in \a name. grpc_ares_init() - must be called at least once before this function. \a on_done may be - called directly in this function without being scheduled with \a exec_ctx, - so it must not try to acquire locks that are being held by the caller. */ -extern void (*grpc_resolve_address_ares)(const char* name, - const char* default_port, - grpc_pollset_set* interested_parties, - grpc_closure* on_done, - grpc_resolved_addresses** addresses); - /* Asynchronously resolve \a name. It will try to resolve grpclb SRV records in addition to the normal address records. For normal address records, it uses \a default_port if a port isn't designated in \a name, otherwise it uses the port in \a name. grpc_ares_init() must be called at least once before this - function. \a on_done may be called directly in this function without being - scheduled with \a exec_ctx, so it must not try to acquire locks that are - being held by the caller. The returned grpc_ares_request object is owned - by the caller and it is safe to free after on_done is called back. */ -extern grpc_ares_request* (*grpc_dns_lookup_ares_locked)( + function. The returned grpc_ares_request object is owned by the caller and it + is safe to free after on_done is called back. + + Note on synchronization: \a as on_done might be called from another thread + ~immediately, access to the grpc_ares_request* return value must be + synchronized by the caller. TODO(apolcyn): we should remove this requirement + by changing this API to use two phase initialization - one API to create + the grpc_ares_request* and another to start the async work. */ +extern grpc_ares_request* (*grpc_dns_lookup_ares)( const char* dns_server, const char* name, const char* default_port, grpc_pollset_set* interested_parties, grpc_closure* on_done, std::unique_ptr<grpc_core::ServerAddressList>* addresses, std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses, - char** service_config_json, int query_timeout_ms, - std::shared_ptr<grpc_core::WorkSerializer> work_serializer); + char** service_config_json, int query_timeout_ms); /* Cancel the pending grpc_ares_request \a request */ -extern void (*grpc_cancel_ares_request_locked)(grpc_ares_request* request); +extern void (*grpc_cancel_ares_request)(grpc_ares_request* request); /* Initialize gRPC ares wrapper. Must be called at least once before grpc_resolve_address_ares(). */ @@ -103,10 +100,6 @@ grpc_error_handle grpc_ares_init(void); it has been called the same number of times as grpc_ares_init(). */ void grpc_ares_cleanup(void); -/** Schedules the desired callback for request completion - * and destroys the grpc_ares_request */ -void grpc_ares_complete_request_locked(grpc_ares_request* request); - /* Indicates whether or not AAAA queries should be attempted. */ /* E.g., return false if ipv6 is known to not be available. */ bool grpc_ares_query_ipv6(); diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc index f76c6a4a12..5269a06e26 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc @@ -24,10 +24,10 @@ #include <grpc/support/string_util.h> #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/socket_windows.h" +#include "src/core/lib/resolver/server_address.h" bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc index 455e3f4d23..f2b46ff452 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc @@ -1,20 +1,18 @@ -/* - * - * 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 <grpc/support/port_platform.h> @@ -23,6 +21,7 @@ #include <climits> #include <cstring> +#include "y_absl/functional/bind_front.h" #include "y_absl/strings/str_cat.h" #include <grpc/support/alloc.h> @@ -30,8 +29,6 @@ #include <grpc/support/time.h> #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/backoff/backoff.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" @@ -39,6 +36,8 @@ #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/iomgr/work_serializer.h" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/resolver/server_address.h" #define GRPC_DNS_INITIAL_CONNECT_BACKOFF_SECONDS 1 #define GRPC_DNS_RECONNECT_BACKOFF_MULTIPLIER 1.6 @@ -49,9 +48,9 @@ namespace grpc_core { namespace { -class NativeDnsResolver : public Resolver { +class NativeClientChannelDNSResolver : public Resolver { public: - explicit NativeDnsResolver(ResolverArgs args); + explicit NativeClientChannelDNSResolver(ResolverArgs args); void StartLocked() override; @@ -62,15 +61,17 @@ class NativeDnsResolver : public Resolver { void ShutdownLocked() override; private: - ~NativeDnsResolver() override; + ~NativeClientChannelDNSResolver() override; void MaybeStartResolvingLocked(); void StartResolvingLocked(); 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); + void OnResolved( + y_absl::StatusOr<std::vector<grpc_resolved_address>> addresses_or); + void OnResolvedLocked( + y_absl::StatusOr<std::vector<grpc_resolved_address>> addresses_or); /// name to resolve TString name_to_resolve_; @@ -84,7 +85,6 @@ class NativeDnsResolver : public Resolver { bool shutdown_ = false; /// are we currently resolving? bool resolving_ = false; - grpc_closure on_resolved_; /// next resolution timer bool have_next_resolution_timer_ = false; grpc_timer next_resolution_timer_; @@ -95,11 +95,12 @@ class NativeDnsResolver : public Resolver { grpc_millis last_resolution_timestamp_ = -1; /// retry backoff state BackOff backoff_; - /// currently resolving addresses - grpc_resolved_addresses* addresses_ = nullptr; + /// tracks pending resolutions + OrphanablePtr<DNSResolver::Request> dns_request_; }; -NativeDnsResolver::NativeDnsResolver(ResolverArgs args) +NativeClientChannelDNSResolver::NativeClientChannelDNSResolver( + ResolverArgs args) : name_to_resolve_(y_absl::StripPrefix(args.uri.path(), "/")), channel_args_(grpc_channel_args_copy(args.args)), work_serializer_(std::move(args.work_serializer)), @@ -120,41 +121,47 @@ NativeDnsResolver::NativeDnsResolver(ResolverArgs args) } } -NativeDnsResolver::~NativeDnsResolver() { +NativeClientChannelDNSResolver::~NativeClientChannelDNSResolver() { grpc_channel_args_destroy(channel_args_); grpc_pollset_set_destroy(interested_parties_); } -void NativeDnsResolver::StartLocked() { MaybeStartResolvingLocked(); } +void NativeClientChannelDNSResolver::StartLocked() { + MaybeStartResolvingLocked(); +} -void NativeDnsResolver::RequestReresolutionLocked() { +void NativeClientChannelDNSResolver::RequestReresolutionLocked() { if (!resolving_) { MaybeStartResolvingLocked(); } } -void NativeDnsResolver::ResetBackoffLocked() { +void NativeClientChannelDNSResolver::ResetBackoffLocked() { if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); } backoff_.Reset(); } -void NativeDnsResolver::ShutdownLocked() { +void NativeClientChannelDNSResolver::ShutdownLocked() { shutdown_ = true; if (have_next_resolution_timer_) { grpc_timer_cancel(&next_resolution_timer_); } + dns_request_.reset(); } -void NativeDnsResolver::OnNextResolution(void* arg, grpc_error_handle error) { - NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg); +void NativeClientChannelDNSResolver::OnNextResolution(void* arg, + grpc_error_handle error) { + NativeClientChannelDNSResolver* r = + static_cast<NativeClientChannelDNSResolver*>(arg); (void)GRPC_ERROR_REF(error); // ref owned by lambda r->work_serializer_->Run([r, error]() { r->OnNextResolutionLocked(error); }, DEBUG_LOCATION); } -void NativeDnsResolver::OnNextResolutionLocked(grpc_error_handle error) { +void NativeClientChannelDNSResolver::OnNextResolutionLocked( + grpc_error_handle error) { have_next_resolution_timer_ = false; if (error == GRPC_ERROR_NONE && !resolving_) { StartResolvingLocked(); @@ -163,47 +170,46 @@ void NativeDnsResolver::OnNextResolutionLocked(grpc_error_handle error) { GRPC_ERROR_UNREF(error); } -void NativeDnsResolver::OnResolved(void* arg, grpc_error_handle error) { - NativeDnsResolver* r = static_cast<NativeDnsResolver*>(arg); - (void)GRPC_ERROR_REF(error); // owned by lambda - r->work_serializer_->Run([r, error]() { r->OnResolvedLocked(error); }, - DEBUG_LOCATION); +void NativeClientChannelDNSResolver::OnResolved( + y_absl::StatusOr<std::vector<grpc_resolved_address>> addresses_or) { + work_serializer_->Run( + [this, addresses_or]() mutable { + OnResolvedLocked(std::move(addresses_or)); + }, + DEBUG_LOCATION); } -void NativeDnsResolver::OnResolvedLocked(grpc_error_handle error) { +void NativeClientChannelDNSResolver::OnResolvedLocked( + y_absl::StatusOr<std::vector<grpc_resolved_address>> addresses_or) { GPR_ASSERT(resolving_); resolving_ = false; + dns_request_.reset(); if (shutdown_) { - if (addresses_ != nullptr) { - grpc_resolved_addresses_destroy(addresses_); - } Unref(DEBUG_LOCATION, "dns-resolving"); - GRPC_ERROR_UNREF(error); return; } - if (addresses_ != nullptr) { - Result result; - for (size_t i = 0; i < addresses_->naddrs; ++i) { - result.addresses.emplace_back(&addresses_->addrs[i].addr, - addresses_->addrs[i].len, - nullptr /* args */); + if (addresses_or.ok()) { + ServerAddressList addresses; + for (auto& addr : *addresses_or) { + addresses.emplace_back(addr, nullptr /* args */); } - grpc_resolved_addresses_destroy(addresses_); + Result result; + result.addresses = std::move(addresses); result.args = grpc_channel_args_copy(channel_args_); - result_handler_->ReturnResult(std::move(result)); + result_handler_->ReportResult(std::move(result)); // Reset backoff state so that we start from the beginning when the // next request gets triggered. backoff_.Reset(); } else { + TString error_message = addresses_or.status().ToString(); gpr_log(GPR_INFO, "dns resolution failed (will retry): %s", - grpc_error_std_string(error).c_str()); + error_message.c_str()); // Return transient error. - TString error_message = - y_absl::StrCat("DNS resolution failed for service: ", name_to_resolve_); - result_handler_->ReturnError(grpc_error_set_int( - GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING(error_message.c_str(), - &error, 1), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); + Result result; + result.addresses = y_absl::UnavailableError(y_absl::StrCat( + "DNS resolution failed for ", name_to_resolve_, ": ", error_message)); + result.args = grpc_channel_args_copy(channel_args_); + result_handler_->ReportResult(std::move(result)); // Set up for retry. // InvalidateNow to avoid getting stuck re-initializing this timer // in a loop while draining the currently-held WorkSerializer. @@ -222,15 +228,15 @@ void NativeDnsResolver::OnResolvedLocked(grpc_error_handle error) { } else { gpr_log(GPR_DEBUG, "retrying immediately"); } - GRPC_CLOSURE_INIT(&on_next_resolution_, NativeDnsResolver::OnNextResolution, - this, grpc_schedule_on_exec_ctx); + GRPC_CLOSURE_INIT(&on_next_resolution_, + NativeClientChannelDNSResolver::OnNextResolution, this, + grpc_schedule_on_exec_ctx); grpc_timer_init(&next_resolution_timer_, next_try, &on_next_resolution_); } Unref(DEBUG_LOCATION, "dns-resolving"); - GRPC_ERROR_UNREF(error); } -void NativeDnsResolver::MaybeStartResolvingLocked() { +void NativeClientChannelDNSResolver::MaybeStartResolvingLocked() { // If there is an existing timer, the time it fires is the earliest time we // can start the next resolution. if (have_next_resolution_timer_) return; @@ -256,7 +262,7 @@ void NativeDnsResolver::MaybeStartResolvingLocked() { // callback as part of the type system. Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown").release(); GRPC_CLOSURE_INIT(&on_next_resolution_, - NativeDnsResolver::OnNextResolution, this, + NativeClientChannelDNSResolver::OnNextResolution, this, grpc_schedule_on_exec_ctx); grpc_timer_init(&next_resolution_timer_, ExecCtx::Get()->Now() + ms_until_next_resolution, @@ -267,7 +273,7 @@ void NativeDnsResolver::MaybeStartResolvingLocked() { StartResolvingLocked(); } -void NativeDnsResolver::StartResolvingLocked() { +void NativeClientChannelDNSResolver::StartResolvingLocked() { gpr_log(GPR_DEBUG, "Start resolving."); // TODO(roth): We currently deal with this ref manually. Once the // new closure API is done, find a way to track this ref with the timer @@ -275,11 +281,10 @@ void NativeDnsResolver::StartResolvingLocked() { Ref(DEBUG_LOCATION, "dns-resolving").release(); GPR_ASSERT(!resolving_); resolving_ = true; - addresses_ = nullptr; - GRPC_CLOSURE_INIT(&on_resolved_, NativeDnsResolver::OnResolved, this, - grpc_schedule_on_exec_ctx); - grpc_resolve_address(name_to_resolve_.c_str(), kDefaultSecurePort, - interested_parties_, &on_resolved_, &addresses_); + dns_request_ = GetDNSResolver()->ResolveName( + name_to_resolve_, kDefaultSecurePort, interested_parties_, + y_absl::bind_front(&NativeClientChannelDNSResolver::OnResolved, this)); + dns_request_->Start(); last_resolution_timestamp_ = ExecCtx::Get()->Now(); } @@ -287,7 +292,7 @@ void NativeDnsResolver::StartResolvingLocked() { // Factory // -class NativeDnsResolverFactory : public ResolverFactory { +class NativeClientChannelDNSResolverFactory : public ResolverFactory { public: bool IsValidUri(const URI& uri) const override { if (GPR_UNLIKELY(!uri.authority().empty())) { @@ -303,7 +308,7 @@ class NativeDnsResolverFactory : public ResolverFactory { OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override { if (!IsValidUri(args.uri)) return nullptr; - return MakeOrphanable<NativeDnsResolver>(std::move(args)); + return MakeOrphanable<NativeClientChannelDNSResolver>(std::move(args)); } const char* scheme() const override { return "dns"; } @@ -319,7 +324,7 @@ void grpc_resolver_dns_native_init() { if (gpr_stricmp(resolver.get(), "native") == 0) { gpr_log(GPR_DEBUG, "Using native dns resolver"); grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( - y_absl::make_unique<grpc_core::NativeDnsResolverFactory>()); + y_absl::make_unique<grpc_core::NativeClientChannelDNSResolverFactory>()); } else { grpc_core::ResolverRegistry::Builder::InitRegistry(); grpc_core::ResolverFactory* existing_factory = @@ -327,7 +332,8 @@ void grpc_resolver_dns_native_init() { if (existing_factory == nullptr) { gpr_log(GPR_DEBUG, "Using native dns resolver"); grpc_core::ResolverRegistry::Builder::RegisterResolverFactory( - y_absl::make_unique<grpc_core::NativeDnsResolverFactory>()); + y_absl::make_unique< + grpc_core::NativeClientChannelDNSResolverFactory>()); } } } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc index e28490be9e..720c69d9a7 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc @@ -30,8 +30,6 @@ #include <grpc/support/alloc.h> #include <grpc/support/string_util.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/gpr/string.h" @@ -40,6 +38,8 @@ #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" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/resolver/server_address.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" @@ -142,23 +142,23 @@ void FakeResolver::MaybeSendResultLocked() { if (!started_ || shutdown_) return; if (return_failure_) { // TODO(roth): Change resolver result generator to be able to inject - // the error to be returned. - result_handler_->ReturnError(grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver transient failure"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE)); + // the error to be returned and to be able to independently set errors + // for addresses and service config. + Result result; + result.addresses = y_absl::UnavailableError("Resolver transient failure"); + result.service_config = result.addresses.status(); + result.args = grpc_channel_args_copy(channel_args_); + result_handler_->ReportResult(std::move(result)); return_failure_ = false; } else if (has_next_result_) { Result result; result.addresses = std::move(next_result_.addresses); result.service_config = std::move(next_result_.service_config); - // TODO(roth): Use std::move() once grpc_error is converted to C++. - result.service_config_error = next_result_.service_config_error; - next_result_.service_config_error = GRPC_ERROR_NONE; // When both next_results_ and channel_args_ contain an arg with the same // name, only the one in next_results_ will be kept since next_results_ is // before channel_args_. result.args = grpc_channel_args_union(next_result_.args, channel_args_); - result_handler_->ReturnResult(std::move(result)); + result_handler_->ReportResult(std::move(result)); has_next_result_ = false; } } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h index 12718bbe89..27bd6cc1d1 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h @@ -19,10 +19,11 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/sync.h" #include "src/core/lib/iomgr/error.h" +#include "src/core/lib/resolver/resolver.h" #define GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR \ "grpc.fake_resolver.response_generator" diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc index 6d69af36e5..c6f0e666ef 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc @@ -18,12 +18,12 @@ #include <random> -#include "src/core/ext/filters/client_channel/resolver_registry.h" #include "src/core/ext/xds/xds_client.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/http/httpcli.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/resolver/resolver_registry.h" #include "src/core/lib/security/credentials/alts/check_gcp_environment.h" namespace grpc_core { @@ -61,7 +61,6 @@ class GoogleCloud2ProdResolver : public Resolver { grpc_error_handle error) = 0; RefCountedPtr<GoogleCloud2ProdResolver> resolver_; - grpc_httpcli_context context_; grpc_httpcli_response response_; grpc_closure on_done_; std::atomic<bool> on_done_called_{false}; @@ -115,7 +114,6 @@ GoogleCloud2ProdResolver::MetadataQuery::MetadataQuery( RefCountedPtr<GoogleCloud2ProdResolver> resolver, const char* path, grpc_polling_entity* pollent) : resolver_(std::move(resolver)) { - grpc_httpcli_context_init(&context_); // Start HTTP request. GRPC_CLOSURE_INIT(&on_done_, OnHttpRequestDone, this, nullptr); Ref().release(); // Ref held by callback. @@ -128,13 +126,12 @@ GoogleCloud2ProdResolver::MetadataQuery::MetadataQuery( request.http.hdr_count = 1; request.http.hdrs = &header; // TODO(ctiller): share the quota from whomever instantiates this! - grpc_httpcli_get(&context_, pollent, ResourceQuota::Default(), &request, + grpc_httpcli_get(pollent, ResourceQuota::Default(), &request, ExecCtx::Get()->Now() + 10000, // 10s timeout &on_done_, &response_); } GoogleCloud2ProdResolver::MetadataQuery::~MetadataQuery() { - grpc_httpcli_context_destroy(&context_); grpc_http_response_destroy(&response_); } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc index ddaf4cedf1..7833c10aee 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc @@ -28,13 +28,13 @@ #include <grpc/support/alloc.h> #include <grpc/support/string_util.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/gpr/string.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/resolver/server_address.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" @@ -73,7 +73,7 @@ void SockaddrResolver::StartLocked() { // TODO(roth): Use std::move() once channel args is converted to C++. result.args = channel_args_; channel_args_ = nullptr; - result_handler_->ReturnResult(std::move(result)); + result_handler_->ReportResult(std::move(result)); } // @@ -91,9 +91,9 @@ bool ParseUri(const URI& uri, // Construct addresses. bool errors_found = false; for (y_absl::string_view ith_path : y_absl::StrSplit(uri.path(), ',')) { - URI ith_uri(uri.scheme(), "", TString(ith_path), {}, ""); + auto ith_uri = URI::Create(uri.scheme(), "", TString(ith_path), {}, ""); grpc_resolved_address addr; - if (!parse(ith_uri, &addr)) { + if (!ith_uri.ok() || !parse(*ith_uri, &addr)) { errors_found = true; break; } diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc index fde42114a3..47a5f4a445 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc @@ -20,6 +20,7 @@ #include "y_absl/strings/match.h" #include "y_absl/strings/str_join.h" +#include "y_absl/strings/str_replace.h" #include "y_absl/strings/str_split.h" #include "re2/re2.h" #define XXH_INLINE_ALL @@ -27,14 +28,17 @@ #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/ext/xds/xds_listener.h" +#include "src/core/ext/xds/xds_route_config.h" #include "src/core/ext/xds/xds_routing.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/iomgr/closure.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/resolver/resolver_registry.h" +#include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/timeout_encoding.h" namespace grpc_core { @@ -45,6 +49,24 @@ const char* kXdsClusterAttribute = "xds_cluster_name"; namespace { +TString GetDefaultAuthorityInternal(const URI& uri) { + // Obtain the authority to use for the data plane connections, which is + // also used to select the right VirtualHost from the RouteConfiguration. + // We need to take the part of the URI path following the last + // "/" character or the entire path if the path contains no "/" character. + size_t pos = uri.path().find_last_of('/'); + if (pos == uri.path().npos) return uri.path(); + return uri.path().substr(pos + 1); +} + +TString GetDataPlaneAuthority(const grpc_channel_args& args, + const URI& uri) { + const char* authority = + grpc_channel_args_find_string(&args, GRPC_ARG_DEFAULT_AUTHORITY); + if (authority != nullptr) return authority; + return GetDefaultAuthorityInternal(uri); +} + // // XdsResolver // @@ -54,12 +76,15 @@ class XdsResolver : public Resolver { explicit XdsResolver(ResolverArgs args) : work_serializer_(std::move(args.work_serializer)), result_handler_(std::move(args.result_handler)), - server_name_(y_absl::StripPrefix(args.uri.path(), "/")), args_(grpc_channel_args_copy(args.args)), - interested_parties_(args.pollset_set) { + interested_parties_(args.pollset_set), + uri_(std::move(args.uri)), + data_plane_authority_(GetDataPlaneAuthority(*args.args, uri_)) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) { - gpr_log(GPR_INFO, "[xds_resolver %p] created for server name %s", this, - server_name_.c_str()); + gpr_log( + GPR_INFO, + "[xds_resolver %p] created for URI %s; data plane authority is %s", + this, uri_.ToString().c_str(), data_plane_authority_.c_str()); } } @@ -79,11 +104,11 @@ class XdsResolver : public Resolver { } private: - class ListenerWatcher : public XdsClient::ListenerWatcherInterface { + class ListenerWatcher : public XdsListenerResourceType::WatcherInterface { public: explicit ListenerWatcher(RefCountedPtr<XdsResolver> resolver) : resolver_(std::move(resolver)) {} - void OnListenerChanged(XdsApi::LdsUpdate listener) override { + void OnResourceChanged(XdsListenerResource listener) override { Ref().release(); // ref held by lambda resolver_->work_serializer_->Run( // TODO(yashykt): When we move to C++14, capture listener with @@ -117,11 +142,12 @@ class XdsResolver : public Resolver { RefCountedPtr<XdsResolver> resolver_; }; - class RouteConfigWatcher : public XdsClient::RouteConfigWatcherInterface { + class RouteConfigWatcher + : public XdsRouteConfigResourceType::WatcherInterface { public: explicit RouteConfigWatcher(RefCountedPtr<XdsResolver> resolver) : resolver_(std::move(resolver)) {} - void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override { + void OnResourceChanged(XdsRouteConfigResource route_config) override { Ref().release(); // ref held by lambda resolver_->work_serializer_->Run( // TODO(yashykt): When we move to C++14, capture route_config with @@ -250,7 +276,7 @@ class XdsResolver : public Resolver { bool operator==(const ClusterWeightState& other) const; }; - XdsApi::Route route; + XdsRouteConfigResource::Route route; RefCountedPtr<ServiceConfig> method_config; y_absl::InlinedVector<ClusterWeightState, 2> weighted_cluster_state; @@ -262,8 +288,9 @@ class XdsResolver : public Resolver { void MaybeAddCluster(const TString& name); grpc_error_handle CreateMethodConfig( - const XdsApi::Route& route, - const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight, + const XdsRouteConfigResource::Route& route, + const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* + cluster_weight, RefCountedPtr<ServiceConfig>* method_config); RefCountedPtr<XdsResolver> resolver_; @@ -272,33 +299,33 @@ class XdsResolver : public Resolver { std::vector<const grpc_channel_filter*> filters_; }; - void OnListenerUpdate(XdsApi::LdsUpdate listener); - void OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update); + void OnListenerUpdate(XdsListenerResource listener); + void OnRouteConfigUpdate(XdsRouteConfigResource rds_update); void OnError(grpc_error_handle error); void OnResourceDoesNotExist(); - grpc_error_handle CreateServiceConfig( - RefCountedPtr<ServiceConfig>* service_config); + y_absl::StatusOr<RefCountedPtr<ServiceConfig>> CreateServiceConfig(); void GenerateResult(); void MaybeRemoveUnusedClusters(); std::shared_ptr<WorkSerializer> work_serializer_; std::unique_ptr<ResultHandler> result_handler_; - TString server_name_; const grpc_channel_args* args_; grpc_pollset_set* interested_parties_; - + URI uri_; RefCountedPtr<XdsClient> xds_client_; + TString lds_resource_name_; + TString data_plane_authority_; - XdsClient::ListenerWatcherInterface* listener_watcher_ = nullptr; + ListenerWatcher* listener_watcher_ = nullptr; // This will not contain the RouteConfiguration, even if it comes with the // LDS response; instead, the relevant VirtualHost from the // RouteConfiguration will be saved in current_virtual_host_. - XdsApi::LdsUpdate current_listener_; + XdsListenerResource current_listener_; TString route_config_name_; - XdsClient::RouteConfigWatcherInterface* route_config_watcher_ = nullptr; - XdsApi::RdsUpdate::VirtualHost current_virtual_host_; + RouteConfigWatcher* route_config_watcher_ = nullptr; + XdsRouteConfigResource::VirtualHost current_virtual_host_; ClusterState::ClusterStateMap cluster_state_map_; }; @@ -336,7 +363,7 @@ class XdsResolver::XdsConfigSelector::RouteListIterator size_t Size() const override { return route_table_->size(); } - const XdsApi::Route::Matchers& GetMatchersForRoute( + const XdsRouteConfigResource::Route::Matchers& GetMatchersForRoute( size_t index) const override { return (*route_table_)[index].route.matchers; } @@ -375,7 +402,8 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector( auto& route_entry = route_table_.back(); route_entry.route = route; auto* route_action = - y_absl::get_if<XdsApi::Route::RouteAction>(&route_entry.route.action); + y_absl::get_if<XdsRouteConfigResource::Route::RouteAction>( + &route_entry.route.action); if (route_action != nullptr) { // If the route doesn't specify a timeout, set its timeout to the global // one. @@ -431,12 +459,13 @@ XdsResolver::XdsConfigSelector::~XdsConfigSelector() { } grpc_error_handle XdsResolver::XdsConfigSelector::CreateMethodConfig( - const XdsApi::Route& route, - const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight, + const XdsRouteConfigResource::Route& route, + const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* + cluster_weight, RefCountedPtr<ServiceConfig>* method_config) { std::vector<TString> fields; const auto& route_action = - y_absl::get<XdsApi::Route::RouteAction>(route.action); + y_absl::get<XdsRouteConfigResource::Route::RouteAction>(route.action); // Set retry policy if any. if (route_action.retry_policy.has_value() && !route_action.retry_policy->retry_on.Empty()) { @@ -536,9 +565,10 @@ void XdsResolver::XdsConfigSelector::MaybeAddCluster(const TString& name) { } y_absl::optional<uint64_t> HeaderHashHelper( - const XdsApi::Route::RouteAction::HashPolicy& policy, + const XdsRouteConfigResource::Route::RouteAction::HashPolicy& policy, grpc_metadata_batch* initial_metadata) { - GPR_ASSERT(policy.type == XdsApi::Route::RouteAction::HashPolicy::HEADER); + GPR_ASSERT(policy.type == + XdsRouteConfigResource::Route::RouteAction::HashPolicy::HEADER); TString value_buffer; y_absl::optional<y_absl::string_view> header_value = XdsRouting::GetHeaderValue( initial_metadata, policy.header_name, &value_buffer); @@ -568,7 +598,8 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( auto& entry = route_table_[*route_index]; // Found a route match const auto* route_action = - y_absl::get_if<XdsApi::Route::RouteAction>(&entry.route.action); + y_absl::get_if<XdsRouteConfigResource::Route::RouteAction>( + &entry.route.action); if (route_action == nullptr) { CallConfig call_config; call_config.error = @@ -615,10 +646,10 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig( for (const auto& hash_policy : route_action->hash_policies) { y_absl::optional<uint64_t> new_hash; switch (hash_policy.type) { - case XdsApi::Route::RouteAction::HashPolicy::HEADER: + case XdsRouteConfigResource::Route::RouteAction::HashPolicy::HEADER: new_hash = HeaderHashHelper(hash_policy, args.initial_metadata); break; - case XdsApi::Route::RouteAction::HashPolicy::CHANNEL_ID: + case XdsRouteConfigResource::Route::RouteAction::HashPolicy::CHANNEL_ID: new_hash = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(resolver_.get())); break; @@ -677,14 +708,61 @@ void XdsResolver::StartLocked() { "Failed to create xds client -- channel will remain in " "TRANSIENT_FAILURE: %s", grpc_error_std_string(error).c_str()); - result_handler_->ReturnError(error); + TString error_message; + grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION, &error_message); + Result result; + result.service_config = y_absl::UnavailableError( + y_absl::StrCat("Failed to create XdsClient: ", error_message)); + result_handler_->ReportResult(std::move(result)); + GRPC_ERROR_UNREF(error); return; } + TString resource_name_fragment(y_absl::StripPrefix(uri_.path(), "/")); + if (!uri_.authority().empty()) { + // target_uri.authority is set case + const auto* authority_config = + xds_client_->bootstrap().LookupAuthority(uri_.authority()); + if (authority_config == nullptr) { + Result result; + result.service_config = y_absl::UnavailableError( + y_absl::StrCat("Invalid target URI -- authority not found for %s.", + uri_.authority().c_str())); + result_handler_->ReportResult(std::move(result)); + return; + } + TString name_template = + authority_config->client_listener_resource_name_template; + if (name_template.empty()) { + name_template = y_absl::StrCat("xdstp://", uri_.authority(), + "/envoy.config.listener.v3.Listener/%s"); + } + lds_resource_name_ = y_absl::StrReplaceAll( + name_template, + {{"%s", URI::PercentEncodePath(resource_name_fragment)}}); + } else { + // target_uri.authority not set + y_absl::string_view name_template = + xds_client_->bootstrap() + .client_default_listener_resource_name_template(); + if (name_template.empty()) { + name_template = "%s"; + } + if (y_absl::StartsWith(name_template, "xdstp:")) { + resource_name_fragment = URI::PercentEncodePath(resource_name_fragment); + } + lds_resource_name_ = + y_absl::StrReplaceAll(name_template, {{"%s", resource_name_fragment}}); + } + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) { + gpr_log(GPR_INFO, "[xds_resolver %p] Started with lds_resource_name %s.", + this, lds_resource_name_.c_str()); + } grpc_pollset_set_add_pollset_set(xds_client_->interested_parties(), interested_parties_); auto watcher = MakeRefCounted<ListenerWatcher>(Ref()); listener_watcher_ = watcher.get(); - xds_client_->WatchListenerData(server_name_, std::move(watcher)); + XdsListenerResourceType::StartWatch(xds_client_.get(), lds_resource_name_, + std::move(watcher)); } void XdsResolver::ShutdownLocked() { @@ -693,12 +771,14 @@ void XdsResolver::ShutdownLocked() { } if (xds_client_ != nullptr) { if (listener_watcher_ != nullptr) { - xds_client_->CancelListenerDataWatch(server_name_, listener_watcher_, - /*delay_unsubscription=*/false); + XdsListenerResourceType::CancelWatch( + xds_client_.get(), lds_resource_name_, listener_watcher_, + /*delay_unsubscription=*/false); } if (route_config_watcher_ != nullptr) { - xds_client_->CancelRouteConfigDataWatch( - server_name_, route_config_watcher_, /*delay_unsubscription=*/false); + XdsRouteConfigResourceType::CancelWatch( + xds_client_.get(), route_config_name_, route_config_watcher_, + /*delay_unsubscription=*/false); } grpc_pollset_set_del_pollset_set(xds_client_->interested_parties(), interested_parties_); @@ -706,7 +786,7 @@ void XdsResolver::ShutdownLocked() { } } -void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) { +void XdsResolver::OnListenerUpdate(XdsListenerResource listener) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) { gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data", this); } @@ -716,8 +796,8 @@ void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) { 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_, + XdsRouteConfigResourceType::CancelWatch( + xds_client_.get(), route_config_name_, route_config_watcher_, /*delay_unsubscription=*/ !listener.http_connection_manager.route_config_name.empty()); route_config_watcher_ = nullptr; @@ -728,7 +808,8 @@ void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) { current_virtual_host_.routes.clear(); auto watcher = MakeRefCounted<RouteConfigWatcher>(Ref()); route_config_watcher_ = watcher.get(); - xds_client_->WatchRouteConfigData(route_config_name_, std::move(watcher)); + XdsRouteConfigResourceType::StartWatch( + xds_client_.get(), route_config_name_, std::move(watcher)); } } current_listener_ = std::move(listener); @@ -748,7 +829,7 @@ namespace { class VirtualHostListIterator : public XdsRouting::VirtualHostListIterator { public: explicit VirtualHostListIterator( - const std::vector<XdsApi::RdsUpdate::VirtualHost>* virtual_hosts) + const std::vector<XdsRouteConfigResource::VirtualHost>* virtual_hosts) : virtual_hosts_(virtual_hosts) {} size_t Size() const override { return virtual_hosts_->size(); } @@ -759,11 +840,11 @@ class VirtualHostListIterator : public XdsRouting::VirtualHostListIterator { } private: - const std::vector<XdsApi::RdsUpdate::VirtualHost>* virtual_hosts_; + const std::vector<XdsRouteConfigResource::VirtualHost>* virtual_hosts_; }; } // namespace -void XdsResolver::OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update) { +void XdsResolver::OnRouteConfigUpdate(XdsRouteConfigResource rds_update) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) { gpr_log(GPR_INFO, "[xds_resolver %p] received updated route config", this); } @@ -772,10 +853,11 @@ void XdsResolver::OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update) { } // Find the relevant VirtualHost from the RouteConfiguration. auto vhost_index = XdsRouting::FindVirtualHostForDomain( - VirtualHostListIterator(&rds_update.virtual_hosts), server_name_); + VirtualHostListIterator(&rds_update.virtual_hosts), + data_plane_authority_); if (!vhost_index.has_value()) { OnError(GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("could not find VirtualHost for ", server_name_, + y_absl::StrCat("could not find VirtualHost for ", data_plane_authority_, " in RouteConfiguration"))); return; } @@ -795,8 +877,9 @@ void XdsResolver::OnError(grpc_error_handle error) { Result result; grpc_arg new_arg = xds_client_->MakeChannelArg(); result.args = grpc_channel_args_copy_and_add(args_, &new_arg, 1); - result.service_config_error = error; - result_handler_->ReturnResult(std::move(result)); + result.service_config = grpc_error_to_absl_status(error); + result_handler_->ReportResult(std::move(result)); + GRPC_ERROR_UNREF(error); } void XdsResolver::OnResourceDoesNotExist() { @@ -809,15 +892,15 @@ void XdsResolver::OnResourceDoesNotExist() { } current_virtual_host_.routes.clear(); Result result; - result.service_config = - ServiceConfig::Create(args_, "{}", &result.service_config_error); - GPR_ASSERT(result.service_config != nullptr); + grpc_error_handle error = GRPC_ERROR_NONE; + result.service_config = ServiceConfig::Create(args_, "{}", &error); + GPR_ASSERT(*result.service_config != nullptr); result.args = grpc_channel_args_copy(args_); - result_handler_->ReturnResult(std::move(result)); + result_handler_->ReportResult(std::move(result)); } -grpc_error_handle XdsResolver::CreateServiceConfig( - RefCountedPtr<ServiceConfig>* service_config) { +y_absl::StatusOr<RefCountedPtr<ServiceConfig>> +XdsResolver::CreateServiceConfig() { std::vector<TString> clusters; for (const auto& cluster : cluster_state_map_) { clusters.push_back( @@ -844,8 +927,13 @@ grpc_error_handle XdsResolver::CreateServiceConfig( "}"); TString json = y_absl::StrJoin(config_parts, ""); grpc_error_handle error = GRPC_ERROR_NONE; - *service_config = ServiceConfig::Create(args_, json.c_str(), &error); - return error; + y_absl::StatusOr<RefCountedPtr<ServiceConfig>> result = + ServiceConfig::Create(args_, json.c_str(), &error); + if (error != GRPC_ERROR_NONE) { + result = grpc_error_to_absl_status(error); + GRPC_ERROR_UNREF(error); + } + return result; } void XdsResolver::GenerateResult() { @@ -860,15 +948,12 @@ void XdsResolver::GenerateResult() { return; } Result result; - error = CreateServiceConfig(&result.service_config); - if (error != GRPC_ERROR_NONE) { - OnError(grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_UNAVAILABLE)); - return; - } + result.service_config = CreateServiceConfig(); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) { gpr_log(GPR_INFO, "[xds_resolver %p] generated service config: %s", this, - result.service_config->json_string().c_str()); + result.service_config.ok() + ? (*result.service_config)->json_string().c_str() + : result.service_config.status().ToString().c_str()); } grpc_arg new_args[] = { xds_client_->MakeChannelArg(), @@ -876,7 +961,7 @@ void XdsResolver::GenerateResult() { }; result.args = grpc_channel_args_copy_and_add(args_, new_args, GPR_ARRAY_SIZE(new_args)); - result_handler_->ReturnResult(std::move(result)); + result_handler_->ReportResult(std::move(result)); } void XdsResolver::MaybeRemoveUnusedClusters() { @@ -903,13 +988,18 @@ void XdsResolver::MaybeRemoveUnusedClusters() { class XdsResolverFactory : public ResolverFactory { public: bool IsValidUri(const URI& uri) const override { - if (GPR_UNLIKELY(!uri.authority().empty())) { - gpr_log(GPR_ERROR, "URI authority not supported"); + if (uri.path().empty() || uri.path().back() == '/') { + gpr_log(GPR_ERROR, + "URI path does not contain valid data plane authority"); return false; } return true; } + TString GetDefaultAuthority(const URI& uri) const override { + return GetDefaultAuthorityInternal(uri); + } + OrphanablePtr<Resolver> CreateResolver(ResolverArgs args) const override { if (!IsValidUri(args.uri)) return nullptr; return MakeOrphanable<XdsResolver>(std::move(args)); diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.cc index db49ed8a8b..ab2f46d55b 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.cc @@ -31,12 +31,12 @@ #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/resolver/server_address.h" #include "src/core/lib/uri/uri_parser.h" // As per the retry design, we do not allow more than 5 retry attempts. diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.h index e0f88f0401..7c75fc2440 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.h @@ -23,13 +23,13 @@ #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/service_config/service_config_parser.h" #include "src/core/lib/channel/status_util.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis #include "src/core/lib/json/json.h" +#include "src/core/lib/resolver/resolver.h" +#include "src/core/lib/service_config/service_config_parser.h" namespace grpc_core { namespace internal { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc index 60d4d49b38..c33ada16fa 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc @@ -22,26 +22,24 @@ #include "y_absl/status/statusor.h" #include "y_absl/strings/strip.h" +#include <grpc/status.h> #include <grpc/support/log.h> #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/service_config/service_config.h" -#include "src/core/ext/service_config/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/service_config/service_config.h" +#include "src/core/lib/service_config/service_config_call_data.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" // @@ -396,10 +394,8 @@ class RetryFilter::CallData { void MaybeSwitchToFastPath(); // Returns true if the call should be retried. - // If server_pushback_md is non-null, sets *server_pushback_ms. bool ShouldRetry(y_absl::optional<grpc_status_code> status, bool is_lb_drop, - grpc_mdelem* server_pushback_md, - grpc_millis* server_pushback_ms); + y_absl::optional<grpc_millis> server_pushback_ms); // Abandons the call attempt. Unrefs any deferred batches. void Abandon(); @@ -420,7 +416,6 @@ class RetryFilter::CallData { // BatchData.batch.payload points to this. grpc_transport_stream_op_batch_payload batch_payload_; // For send_initial_metadata. - grpc_linked_mdelem retry_attempts_metadata_; grpc_metadata_batch send_initial_metadata_{calld_->arena_}; // For send_message. // TODO(roth): Restructure this to eliminate use of ManualConstructor. @@ -509,8 +504,8 @@ class RetryFilter::CallData { void RetryCommit(CallAttempt* call_attempt); // Starts a timer to retry after appropriate back-off. - // If server_pushback_ms is -1, retry_backoff_ is used. - void StartRetryTimer(grpc_millis server_pushback_ms); + // If server_pushback_ms is nullopt, retry_backoff_ is used. + void StartRetryTimer(y_absl::optional<grpc_millis> server_pushback_ms); static void OnRetryTimer(void* arg, grpc_error_handle error); static void OnRetryTimerLocked(void* arg, grpc_error_handle error); @@ -1065,7 +1060,7 @@ void RetryFilter::CallData::CallAttempt::CancelFromSurface( bool RetryFilter::CallData::CallAttempt::ShouldRetry( y_absl::optional<grpc_status_code> status, bool is_lb_drop, - grpc_mdelem* server_pushback_md, grpc_millis* server_pushback_ms) { + y_absl::optional<grpc_millis> server_pushback_ms) { // LB drops always inhibit retries. if (is_lb_drop) return false; // TODO(roth): Handle transparent retries here. @@ -1131,10 +1126,8 @@ bool RetryFilter::CallData::CallAttempt::ShouldRetry( return false; } // Check server push-back. - 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 (server_pushback_ms.has_value()) { + if (*server_pushback_ms < 0) { if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { gpr_log(GPR_INFO, "chand=%p calld=%p attempt=%p: not retrying due to server " @@ -1146,10 +1139,10 @@ bool RetryFilter::CallData::CallAttempt::ShouldRetry( if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { gpr_log( GPR_INFO, - "chand=%p calld=%p attempt=%p: server push-back: retry in %u ms", - calld_->chand_, calld_, this, ms); + "chand=%p calld=%p attempt=%p: server push-back: retry in %" PRIu64 + " ms", + calld_->chand_, calld_, this, *server_pushback_ms); } - *server_pushback_ms = static_cast<grpc_millis>(ms); } } // Check with call dispatch controller. @@ -1236,11 +1229,11 @@ void RetryFilter::CallData::CallAttempt::OnPerAttemptRecvTimerLocked( // Check whether we should retry. if (call_attempt->ShouldRetry( /*status=*/y_absl::nullopt, /*is_lb_drop=*/false, - /*server_pushback_md=*/nullptr, /*server_pushback_ms=*/nullptr)) { + /*server_pushback_ms=*/y_absl::nullopt)) { // Mark current attempt as abandoned. call_attempt->Abandon(); // We are retrying. Start backoff timer. - calld->StartRetryTimer(/*server_pushback_ms=*/-1); + calld->StartRetryTimer(/*server_pushback_ms=*/y_absl::nullopt); } else { // Not retrying, so commit the call. calld->RetryCommit(call_attempt); @@ -1534,11 +1527,12 @@ void RetryFilter::CallData::CallAttempt::BatchData::RecvMessageReady( namespace { -// Sets *status, *server_pushback_md, and *is_lb_drop based on md_batch +// Sets *status, *server_pushback_ms, 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) { + y_absl::optional<grpc_millis>* server_pushback_ms, + bool* is_lb_drop) { if (error != GRPC_ERROR_NONE) { grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); intptr_t value = 0; @@ -1547,13 +1541,8 @@ void GetCallStatus(grpc_millis deadline, grpc_metadata_batch* md_batch, *is_lb_drop = true; } } else { - GPR_ASSERT(md_batch->legacy_index()->named.grpc_status != nullptr); - *status = grpc_get_status_code_from_metadata( - md_batch->legacy_index()->named.grpc_status->md); - if (md_batch->legacy_index()->named.grpc_retry_pushback_ms != nullptr) { - *server_pushback_md = - &md_batch->legacy_index()->named.grpc_retry_pushback_ms->md; - } + *status = *md_batch->get(GrpcStatusMetadata()); + *server_pushback_ms = md_batch->get(GrpcRetryPushbackMsMetadata()); } GRPC_ERROR_UNREF(error); } @@ -1685,12 +1674,12 @@ void RetryFilter::CallData::CallAttempt::BatchData::RecvTrailingMetadataReady( call_attempt->MaybeCancelPerAttemptRecvTimer(); // Get the call's status and check for server pushback metadata. grpc_status_code status = GRPC_STATUS_OK; - grpc_mdelem* server_pushback_md = nullptr; + y_absl::optional<grpc_millis> server_pushback_ms; 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); + &server_pushback_ms, &is_lb_drop); if (GRPC_TRACE_FLAG_ENABLED(grpc_retry_trace)) { gpr_log( GPR_INFO, @@ -1699,9 +1688,7 @@ void RetryFilter::CallData::CallAttempt::BatchData::RecvTrailingMetadataReady( is_lb_drop); } // Check if we should retry. - grpc_millis server_pushback_ms = -1; - if (call_attempt->ShouldRetry(status, is_lb_drop, server_pushback_md, - &server_pushback_ms)) { + if (call_attempt->ShouldRetry(status, is_lb_drop, server_pushback_ms)) { // Start retry timer. calld->StartRetryTimer(server_pushback_ms); // Cancel call attempt. @@ -1893,35 +1880,19 @@ void RetryFilter::CallData::CallAttempt::BatchData::OnCompleteForCancelOp( 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. - grpc_metadata_batch_copy(&calld->send_initial_metadata_, - &call_attempt_->send_initial_metadata_); - if (GPR_UNLIKELY(call_attempt_->send_initial_metadata_.legacy_index() - ->named.grpc_previous_rpc_attempts != nullptr)) { - call_attempt_->send_initial_metadata_.Remove( - GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS); - } + call_attempt_->send_initial_metadata_ = calld->send_initial_metadata_.Copy(); 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_->retry_attempts_metadata_, 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_->send_initial_metadata_.Set(GrpcPreviousRpcAttemptsMetadata(), + calld->num_attempts_completed_); + } else { + call_attempt_->send_initial_metadata_.Remove( + GrpcPreviousRpcAttemptsMetadata()); } call_attempt_->started_send_initial_metadata_ = true; batch_.send_initial_metadata = true; @@ -1958,8 +1929,8 @@ void RetryFilter::CallData::CallAttempt::BatchData:: // 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. - grpc_metadata_batch_copy(&calld->send_trailing_metadata_, - &call_attempt_->send_trailing_metadata_); + call_attempt_->send_trailing_metadata_ = + calld->send_trailing_metadata_.Copy(); call_attempt_->started_send_trailing_metadata_ = true; batch_.send_trailing_metadata = true; batch_.payload->send_trailing_metadata.send_trailing_metadata = @@ -2274,7 +2245,7 @@ void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) { seen_send_initial_metadata_ = true; grpc_metadata_batch* send_initial_metadata = batch->payload->send_initial_metadata.send_initial_metadata; - grpc_metadata_batch_copy(send_initial_metadata, &send_initial_metadata_); + send_initial_metadata_ = send_initial_metadata->Copy(); send_initial_metadata_flags_ = batch->payload->send_initial_metadata.send_initial_metadata_flags; peer_string_ = batch->payload->send_initial_metadata.peer_string; @@ -2290,7 +2261,7 @@ void RetryFilter::CallData::MaybeCacheSendOpsForBatch(PendingBatch* pending) { seen_send_trailing_metadata_ = true; grpc_metadata_batch* send_trailing_metadata = batch->payload->send_trailing_metadata.send_trailing_metadata; - grpc_metadata_batch_copy(send_trailing_metadata, &send_trailing_metadata_); + send_trailing_metadata_ = send_trailing_metadata->Copy(); } } @@ -2512,13 +2483,15 @@ void RetryFilter::CallData::RetryCommit(CallAttempt* call_attempt) { } } -void RetryFilter::CallData::StartRetryTimer(grpc_millis server_pushback_ms) { +void RetryFilter::CallData::StartRetryTimer( + y_absl::optional<grpc_millis> server_pushback_ms) { // Reset call attempt. call_attempt_.reset(DEBUG_LOCATION, "StartRetryTimer"); // Compute backoff delay. grpc_millis next_attempt_time; - if (server_pushback_ms >= 0) { - next_attempt_time = ExecCtx::Get()->Now() + server_pushback_ms; + if (server_pushback_ms.has_value()) { + GPR_ASSERT(*server_pushback_ms >= 0); + next_attempt_time = ExecCtx::Get()->Now() + *server_pushback_ms; retry_backoff_.Reset(); } else { next_attempt_time = retry_backoff_.NextAttemptTime(); diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.cc index 4de87f03cd..ba7e042137 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.cc @@ -31,12 +31,12 @@ #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/resolver/server_address.h" #include "src/core/lib/uri/uri_parser.h" // As per the retry design, we do not allow more than 5 retry attempts. diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.h index 486e870eb0..b74d9a3a65 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.h @@ -22,9 +22,9 @@ #include <memory> #include "src/core/ext/filters/client_channel/retry_throttle.h" -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/channel/status_util.h" #include "src/core/lib/iomgr/exec_ctx.h" // for grpc_millis +#include "src/core/lib/service_config/service_config_parser.h" namespace grpc_core { namespace internal { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc index 1905429960..d540ae2e87 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc @@ -19,11 +19,11 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/service_config/service_config_call_data.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" +#include "src/core/lib/service_config/service_config_call_data.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc index 1d9078cce2..782629ffe6 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc @@ -26,6 +26,7 @@ #include "y_absl/strings/str_format.h" +#include <grpc/status.h> #include <grpc/support/alloc.h> #include <grpc/support/string_util.h> @@ -50,7 +51,6 @@ #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" #include "src/core/lib/transport/error_utils.h" -#include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/uri/uri_parser.h" // Strong and weak refs. @@ -141,14 +141,14 @@ SubchannelCall::SubchannelCall(Args args, grpc_error_handle* error) deadline_(args.deadline) { grpc_call_stack* callstk = SUBCHANNEL_CALL_TO_CALL_STACK(this); const grpc_call_element_args call_args = { - callstk, /* call_stack */ - nullptr, /* server_transport_data */ - args.context, /* context */ - args.path, /* path */ - args.start_time, /* start_time */ - args.deadline, /* deadline */ - args.arena, /* arena */ - args.call_combiner /* call_combiner */ + callstk, /* call_stack */ + nullptr, /* server_transport_data */ + args.context, /* context */ + args.path.c_slice(), /* path */ + args.start_time, /* start_time */ + args.deadline, /* deadline */ + args.arena, /* arena */ + args.call_combiner /* call_combiner */ }; *error = grpc_call_stack_init(connected_subchannel_->channel_stack(), 1, SubchannelCall::Destroy, this, &call_args); @@ -252,12 +252,7 @@ void GetCallStatus(grpc_status_code* status, grpc_millis deadline, if (error != GRPC_ERROR_NONE) { grpc_error_get_status(error, deadline, status, nullptr, nullptr, nullptr); } else { - if (md_batch->legacy_index()->named.grpc_status != nullptr) { - *status = grpc_get_status_code_from_metadata( - md_batch->legacy_index()->named.grpc_status->md); - } else { - *status = GRPC_STATUS_UNKNOWN; - } + *status = md_batch->get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN); } GRPC_ERROR_UNREF(error); } @@ -969,7 +964,8 @@ void ConnectionDestroy(void* arg, grpc_error_handle /*error*/) { bool Subchannel::PublishTransportLocked() { // Construct channel stack. - grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); + grpc_channel_stack_builder* builder = + grpc_channel_stack_builder_create("subchannel"); grpc_channel_stack_builder_set_channel_arguments( builder, connecting_result_.channel_args); grpc_channel_stack_builder_set_transport(builder, diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.h b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.h index 7fdbe0f1ec..b5c795663d 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.h +++ b/contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.h @@ -27,15 +27,14 @@ #include "src/core/lib/backoff/backoff.h" #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" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/transport/connectivity_state.h" -#include "src/core/lib/transport/metadata.h" namespace grpc_core { @@ -75,7 +74,7 @@ class SubchannelCall { struct Args { RefCountedPtr<ConnectedSubchannel> connected_subchannel; grpc_polling_entity* pollent; - grpc_slice path; + Slice path; gpr_cycle_counter start_time; grpc_millis deadline; Arena* arena; diff --git a/contrib/libs/grpc/src/core/ext/filters/fault_injection/fault_injection_filter.cc b/contrib/libs/grpc/src/core/ext/filters/fault_injection/fault_injection_filter.cc index a8b11a26e6..39812221be 100644 --- a/contrib/libs/grpc/src/core/ext/filters/fault_injection/fault_injection_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/fault_injection/fault_injection_filter.cc @@ -22,16 +22,17 @@ #include "y_absl/strings/numbers.h" +#include <grpc/status.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include "src/core/ext/filters/fault_injection/service_config_parser.h" -#include "src/core/ext/service_config/service_config_call_data.h" #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/status_util.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/service_config/service_config_call_data.h" #include "src/core/lib/transport/status_conversion.h" namespace grpc_core { @@ -45,31 +46,11 @@ static_assert( std::is_trivially_destructible<std::atomic<uint32_t>>::value, "the active fault counter needs to have a trivially destructible type"); -inline int GetMetadatumValueInt(grpc_mdelem md) { - int res; - if (y_absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) { - return res; - } else { - return -1; - } -} - -inline uint32_t GetMetadatumValueUnsignedInt(grpc_mdelem md) { - uint32_t res; - if (y_absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) { - return res; - } else { - return -1; - } -} - -inline int64_t GetMetadatumValueInt64(grpc_mdelem md) { - int64_t res; - if (y_absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md)), &res)) { - return res; - } else { - return -1; - } +template <typename T> +auto AsInt(y_absl::string_view s) -> y_absl::optional<T> { + T x; + if (y_absl::SimpleAtoi(s, &x)) return x; + return y_absl::nullopt; } inline bool UnderFraction(const uint32_t numerator, @@ -346,41 +327,49 @@ void CallData::DecideWhetherToInjectFaults( *fi_policy_); } }; - initial_metadata->ForEach([&](grpc_mdelem md) { - y_absl::string_view key = StringViewFromSlice(GRPC_MDKEY(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) { + TString buffer; + if (!fi_policy_->abort_code_header.empty() && + (copied_policy == nullptr || + copied_policy->abort_code == GRPC_STATUS_OK)) { + auto value = initial_metadata->GetStringValue( + fi_policy_->abort_code_header, &buffer); + if (value.has_value()) { maybe_copy_policy_func(); - grpc_status_code_from_int(GetMetadatumValueInt(md), - &copied_policy->abort_code); + grpc_status_code_from_int( + AsInt<int>(*value).value_or(GRPC_STATUS_UNKNOWN), + &copied_policy->abort_code); } - if (!fi_policy_->abort_percentage_header.empty() && - key == fi_policy_->abort_percentage_header) { + } + if (!fi_policy_->abort_percentage_header.empty()) { + auto value = initial_metadata->GetStringValue( + fi_policy_->abort_percentage_header, &buffer); + if (value.has_value()) { maybe_copy_policy_func(); copied_policy->abort_percentage_numerator = - std::min(GetMetadatumValueUnsignedInt(md), + std::min(AsInt<uint32_t>(*value).value_or(-1), fi_policy_->abort_percentage_numerator); } - if (!fi_policy_->delay_header.empty() && - (copied_policy == nullptr || copied_policy->delay == 0) && - key == fi_policy_->delay_header) { + } + if (!fi_policy_->delay_header.empty() && + (copied_policy == nullptr || copied_policy->delay == 0)) { + auto value = + initial_metadata->GetStringValue(fi_policy_->delay_header, &buffer); + if (value.has_value()) { maybe_copy_policy_func(); copied_policy->delay = static_cast<grpc_millis>( - std::max(GetMetadatumValueInt64(md), int64_t(0))); + std::max(AsInt<int64_t>(*value).value_or(0), int64_t(0))); } - if (!fi_policy_->delay_percentage_header.empty() && - key == fi_policy_->delay_percentage_header) { + } + if (!fi_policy_->delay_percentage_header.empty()) { + auto value = initial_metadata->GetStringValue( + fi_policy_->delay_percentage_header, &buffer); + if (value.has_value()) { maybe_copy_policy_func(); copied_policy->delay_percentage_numerator = - std::min(GetMetadatumValueUnsignedInt(md), + std::min(AsInt<uint32_t>(*value).value_or(-1), fi_policy_->delay_percentage_numerator); } - }); + } if (copied_policy != nullptr) fi_policy_ = copied_policy; } // Roll the dice diff --git a/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc b/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc index a5075fe66f..9af70bcfa6 100644 --- a/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc +++ b/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc @@ -122,14 +122,12 @@ ParseFaultInjectionPolicy(const Json::Array& policies_json_array, } } // 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")); - } - } + static_assert( + std::is_unsigned<decltype(fault_injection_policy.max_faults)>::value, + "maxFaults should be unsigned"); + ParseJsonObjectField(json_object, "maxFaults", + &fault_injection_policy.max_faults, &sub_error_list, + false); if (!sub_error_list.empty()) { error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( y_absl::StrCat("failed to parse faultInjectionPolicy index ", i), diff --git a/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.h b/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.h index e9b692bfcc..140923f08b 100644 --- a/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.h +++ b/contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.h @@ -21,8 +21,8 @@ #include <vector> -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/service_config/service_config_parser.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc b/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc index c1b1e0bed4..d20af49bbc 100644 --- a/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc @@ -23,6 +23,7 @@ #include <string.h> #include <util/generic/string.h> +#include <util/string/cast.h> #include <vector> #include "y_absl/strings/str_cat.h" @@ -39,7 +40,6 @@ #include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/transport_impl.h" @@ -75,10 +75,6 @@ struct call_data { ~call_data() { GRPC_ERROR_UNREF(recv_initial_metadata_error); } grpc_core::CallCombiner* call_combiner; - // State for handling send_initial_metadata ops. - grpc_linked_mdelem method; - grpc_linked_mdelem scheme; - grpc_linked_mdelem content_type; // State for handling recv_initial_metadata ops. grpc_metadata_batch* recv_initial_metadata; grpc_error_handle recv_initial_metadata_error = GRPC_ERROR_NONE; @@ -102,7 +98,7 @@ struct call_data { }; struct channel_data { - grpc_mdelem static_scheme; + grpc_core::HttpSchemeMetadata::ValueType static_scheme; grpc_core::Slice user_agent; size_t max_payload_size_for_get; }; @@ -110,30 +106,27 @@ struct channel_data { static grpc_error_handle client_filter_incoming_metadata( grpc_metadata_batch* b) { - if (b->legacy_index()->named.status != nullptr) { + if (auto* status = b->get_pointer(grpc_core::HttpStatusMetadata())) { /* If both gRPC status and HTTP status are provided in the response, we * should prefer the gRPC status code, as mentioned in * https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. */ - if (b->legacy_index()->named.grpc_status != nullptr || - grpc_mdelem_static_value_eq(b->legacy_index()->named.status->md, - GRPC_MDELEM_STATUS_200)) { - b->Remove(GRPC_BATCH_STATUS); + const grpc_status_code* grpc_status = + b->get_pointer(grpc_core::GrpcStatusMetadata()); + if (grpc_status != nullptr || *status == 200) { + b->Remove(grpc_core::HttpStatusMetadata()); } else { - char* val = grpc_dump_slice( - GRPC_MDVALUE(b->legacy_index()->named.status->md), GPR_DUMP_ASCII); TString msg = - y_absl::StrCat("Received http2 header with status: ", val); + y_absl::StrCat("Received http2 header with status: ", *status); grpc_error_handle e = grpc_error_set_str( grpc_error_set_int( grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Received http2 :status header with non-200 OK status"), - GRPC_ERROR_STR_VALUE, val), + GRPC_ERROR_STR_VALUE, ToString(*status)), GRPC_ERROR_INT_GRPC_STATUS, - grpc_http2_status_to_grpc_status(atoi(val))), + grpc_http2_status_to_grpc_status(*status)), GRPC_ERROR_STR_GRPC_MESSAGE, msg); - gpr_free(val); return e; } } @@ -144,38 +137,7 @@ static grpc_error_handle client_filter_incoming_metadata( grpc_core::PermissivePercentDecodeSlice(std::move(*grpc_message)); } - if (b->legacy_index()->named.content_type != nullptr) { - if (!grpc_mdelem_static_value_eq( - b->legacy_index()->named.content_type->md, - GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) { - if (grpc_slice_buf_start_eq( - GRPC_MDVALUE(b->legacy_index()->named.content_type->md), - EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) && - (GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->legacy_index() - ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == - '+' || - GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->legacy_index() - ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == - ';')) { - /* Although the C implementation doesn't (currently) generate them, - any custom +-suffix is explicitly valid. */ - /* TODO(klempner): We should consider preallocating common values such - as +proto or +json, or at least stashing them if we see them. */ - /* TODO(klempner): Should we be surfacing this to application code? */ - } else { - /* TODO(klempner): We're currently allowing this, but we shouldn't - see it without a proxy so log for now. */ - char* val = grpc_dump_slice( - GRPC_MDVALUE(b->legacy_index()->named.content_type->md), - GPR_DUMP_ASCII); - gpr_log(GPR_INFO, "Unexpected content-type '%s'", val); - gpr_free(val); - } - } - b->Remove(GRPC_BATCH_CONTENT_TYPE); - } + b->Remove(grpc_core::ContentTypeMetadata()); return GRPC_ERROR_NONE; } @@ -306,53 +268,41 @@ 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_handle update_path_for_get( - grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { +static void update_path_for_get(grpc_call_element* elem, + grpc_transport_stream_op_batch* batch) { + grpc_metadata_batch* b = + batch->payload->send_initial_metadata.send_initial_metadata; call_data* calld = static_cast<call_data*>(elem->call_data); - grpc_slice path_slice = - GRPC_MDVALUE(batch->payload->send_initial_metadata.send_initial_metadata - ->legacy_index() - ->named.path->md); + const grpc_core::Slice& path_slice = + *b->get_pointer(grpc_core::HttpPathMetadata()); /* sum up individual component's lengths and allocate enough memory to * hold combined path+query */ - size_t estimated_len = GRPC_SLICE_LENGTH(path_slice); + size_t estimated_len = path_slice.size(); estimated_len++; /* for the '?' */ estimated_len += grpc_base64_estimate_encoded_size( batch->payload->send_message.send_message->length(), false /* multi_line */); - grpc_core::UnmanagedMemorySlice path_with_query_slice(estimated_len); + grpc_core::MutableSlice path_with_query_slice = + grpc_core::MutableSlice::CreateUninitialized(estimated_len); /* memcopy individual pieces into this slice */ - char* write_ptr = - reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_with_query_slice); - char* original_path = - reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_slice); - memcpy(write_ptr, original_path, GRPC_SLICE_LENGTH(path_slice)); - write_ptr += GRPC_SLICE_LENGTH(path_slice); + uint8_t* write_ptr = path_with_query_slice.begin(); + const uint8_t* original_path = path_slice.data(); + memcpy(write_ptr, original_path, path_slice.size()); + write_ptr += path_slice.size(); *write_ptr++ = '?'; char* payload_bytes = slice_buffer_to_string(calld->send_message_cache->cache_buffer()); - grpc_base64_encode_core(write_ptr, payload_bytes, + grpc_base64_encode_core(reinterpret_cast<char*>(write_ptr), payload_bytes, batch->payload->send_message.send_message->length(), true /* url_safe */, false /* multi_line */); gpr_free(payload_bytes); - /* remove trailing unused memory and add trailing 0 to terminate string */ - char* t = - reinterpret_cast<char*> GRPC_SLICE_START_PTR(path_with_query_slice) + - GRPC_SLICE_LENGTH(path_slice); + char* t = reinterpret_cast<char*>(path_with_query_slice.begin()) + + path_slice.size(); /* safe to use strlen since base64_encode will always add '\0' */ - path_with_query_slice = grpc_slice_sub_no_ref( - path_with_query_slice, 0, GRPC_SLICE_LENGTH(path_slice) + strlen(t)); /* substitute previous path with the new path+query */ - grpc_mdelem mdelem_path_and_query = - grpc_mdelem_from_slices(GRPC_MDSTR_PATH, path_with_query_slice); - grpc_metadata_batch* b = - batch->payload->send_initial_metadata.send_initial_metadata; - return b->Substitute(b->legacy_index()->named.path, mdelem_path_and_query); -} - -static void remove_if_present(grpc_metadata_batch* batch, - grpc_metadata_batch_callouts_index idx) { - batch->Remove(idx); + b->Set(grpc_core::HttpPathMetadata(), + grpc_core::Slice(path_with_query_slice.TakeSubSlice( + 0, path_slice.size() + strlen(t)))); } static void http_client_start_transport_stream_op_batch( @@ -388,7 +338,8 @@ static void http_client_start_transport_stream_op_batch( // cacheable, and the operation contains both initial metadata and send // message, and the payload is below the size threshold, and all the data // for this request is immediately available. - grpc_mdelem method = GRPC_MDELEM_METHOD_POST; + grpc_core::HttpMethodMetadata::ValueType method = + grpc_core::HttpMethodMetadata::kPost; if (batch->send_message && (batch->payload->send_initial_metadata.send_initial_metadata_flags & GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) && @@ -408,9 +359,8 @@ static void http_client_start_transport_stream_op_batch( // If all the data has been read, then we can use GET. if (calld->send_message_bytes_read == calld->send_message_caching_stream->length()) { - method = GRPC_MDELEM_METHOD_GET; - error = update_path_for_get(elem, batch); - if (error != GRPC_ERROR_NONE) goto done; + method = grpc_core::HttpMethodMetadata::kGet; + update_path_for_get(elem, batch); batch->send_message = false; calld->send_message_caching_stream->Orphan(); } else { @@ -425,36 +375,20 @@ static void http_client_start_transport_stream_op_batch( } else if (batch->payload->send_initial_metadata .send_initial_metadata_flags & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST) { - method = GRPC_MDELEM_METHOD_PUT; + method = grpc_core::HttpMethodMetadata::kPut; } - remove_if_present( - batch->payload->send_initial_metadata.send_initial_metadata, - GRPC_BATCH_METHOD); - remove_if_present( - batch->payload->send_initial_metadata.send_initial_metadata, - GRPC_BATCH_SCHEME); - remove_if_present( - batch->payload->send_initial_metadata.send_initial_metadata, - GRPC_BATCH_CONTENT_TYPE); - /* Send : prefixed headers, which have to be before any application layer headers. */ - error = grpc_metadata_batch_add_head( - batch->payload->send_initial_metadata.send_initial_metadata, - &calld->method, method, GRPC_BATCH_METHOD); - if (error != GRPC_ERROR_NONE) goto done; - error = grpc_metadata_batch_add_head( - batch->payload->send_initial_metadata.send_initial_metadata, - &calld->scheme, channeld->static_scheme, GRPC_BATCH_SCHEME); - if (error != GRPC_ERROR_NONE) goto done; + batch->payload->send_initial_metadata.send_initial_metadata->Set( + grpc_core::HttpMethodMetadata(), method); + batch->payload->send_initial_metadata.send_initial_metadata->Set( + grpc_core::HttpSchemeMetadata(), channeld->static_scheme); batch->payload->send_initial_metadata.send_initial_metadata->Set( grpc_core::TeMetadata(), grpc_core::TeMetadata::kTrailers); - error = grpc_metadata_batch_add_tail( - batch->payload->send_initial_metadata.send_initial_metadata, - &calld->content_type, GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC, - GRPC_BATCH_CONTENT_TYPE); - if (error != GRPC_ERROR_NONE) goto done; + batch->payload->send_initial_metadata.send_initial_metadata->Set( + grpc_core::ContentTypeMetadata(), + grpc_core::ContentTypeMetadata::kApplicationGrpc); batch->payload->send_initial_metadata.send_initial_metadata->Set( grpc_core::UserAgentMetadata(), channeld->user_agent.Ref()); } @@ -483,25 +417,21 @@ static void http_client_destroy_call_elem( calld->~call_data(); } -static grpc_mdelem scheme_from_args(const grpc_channel_args* args) { - unsigned i; - size_t j; - grpc_mdelem valid_schemes[] = {GRPC_MDELEM_SCHEME_HTTP, - GRPC_MDELEM_SCHEME_HTTPS}; +static grpc_core::HttpSchemeMetadata::ValueType scheme_from_args( + const grpc_channel_args* args) { if (args != nullptr) { - for (i = 0; i < args->num_args; ++i) { + for (size_t i = 0; i < args->num_args; ++i) { if (args->args[i].type == GRPC_ARG_STRING && - strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME) == 0) { - for (j = 0; j < GPR_ARRAY_SIZE(valid_schemes); j++) { - if (0 == grpc_slice_str_cmp(GRPC_MDVALUE(valid_schemes[j]), - args->args[i].value.string)) { - return valid_schemes[j]; - } - } + 0 == strcmp(args->args[i].key, GRPC_ARG_HTTP2_SCHEME)) { + grpc_core::HttpSchemeMetadata::ValueType scheme = + grpc_core::HttpSchemeMetadata::Parse( + args->args[i].value.string, + [](y_absl::string_view, const grpc_core::Slice&) {}); + if (scheme != grpc_core::HttpSchemeMetadata::kInvalid) return scheme; } } } - return GRPC_MDELEM_SCHEME_HTTP; + return grpc_core::HttpSchemeMetadata::kHttp; } static size_t max_payload_size_from_args(const grpc_channel_args* args) { diff --git a/contrib/libs/grpc/src/core/ext/filters/http/client_authority_filter.cc b/contrib/libs/grpc/src/core/ext/filters/http/client_authority_filter.cc index 1915ebdab1..e46765009c 100644 --- a/contrib/libs/grpc/src/core/ext/filters/http/client_authority_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/http/client_authority_filter.cc @@ -36,39 +36,27 @@ #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel_stack_type.h" -#include "src/core/lib/transport/static_metadata.h" namespace { struct call_data { - grpc_linked_mdelem authority_storage; grpc_core::CallCombiner* call_combiner; }; struct channel_data { - grpc_core::ManagedMemorySlice default_authority; - grpc_mdelem default_authority_mdelem; + grpc_core::Slice default_authority; }; void client_authority_start_transport_stream_op_batch( grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { channel_data* chand = static_cast<channel_data*>(elem->channel_data); - call_data* calld = static_cast<call_data*>(elem->call_data); // Handle send_initial_metadata. // If the initial metadata doesn't already contain :authority, add it. if (batch->send_initial_metadata && - batch->payload->send_initial_metadata.send_initial_metadata - ->legacy_index() - ->named.authority == nullptr) { - 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); - if (error != GRPC_ERROR_NONE) { - grpc_transport_stream_op_batch_finish_with_failure(batch, error, - calld->call_combiner); - return; - } + batch->payload->send_initial_metadata.send_initial_metadata->get_pointer( + grpc_core::HttpAuthorityMetadata()) == nullptr) { + batch->payload->send_initial_metadata.send_initial_metadata->Set( + grpc_core::HttpAuthorityMetadata(), chand->default_authority.Ref()); } // Pass control down the stack. grpc_call_next_op(elem, batch); @@ -90,7 +78,7 @@ void client_authority_destroy_call_elem( /* Constructor for channel_data */ grpc_error_handle client_authority_init_channel_elem( grpc_channel_element* elem, grpc_channel_element_args* args) { - channel_data* chand = static_cast<channel_data*>(elem->channel_data); + channel_data* chand = new (elem->channel_data) channel_data; const grpc_arg* default_authority_arg = grpc_channel_args_find(args->channel_args, GRPC_ARG_DEFAULT_AUTHORITY); if (default_authority_arg == nullptr) { @@ -105,18 +93,14 @@ grpc_error_handle client_authority_init_channel_elem( "GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string"); } chand->default_authority = - grpc_core::ManagedMemorySlice(default_authority_str); - chand->default_authority_mdelem = grpc_mdelem_create( - GRPC_MDSTR_AUTHORITY, chand->default_authority, nullptr); + grpc_core::Slice::FromCopiedString(default_authority_str); GPR_ASSERT(!args->is_last); return GRPC_ERROR_NONE; } /* Destructor for channel data */ void client_authority_destroy_channel_elem(grpc_channel_element* elem) { - channel_data* chand = static_cast<channel_data*>(elem->channel_data); - grpc_slice_unref_internal(chand->default_authority); - GRPC_MDELEM_UNREF(chand->default_authority_mdelem); + static_cast<channel_data*>(elem->channel_data)->~channel_data(); } } // namespace diff --git a/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_compress_filter.cc b/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_compress_filter.cc index 9493044a4b..5fa5877dac 100644 --- a/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_compress_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_compress_filter.cc @@ -31,8 +31,6 @@ #include <grpc/support/log.h> #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/compression/algorithm_metadata.h" -#include "src/core/lib/compression/compression_args.h" #include "src/core/lib/compression/compression_internal.h" #include "src/core/lib/compression/message_compress.h" #include "src/core/lib/gpr/string.h" @@ -41,7 +39,6 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/call.h" -#include "src/core/lib/transport/static_metadata.h" namespace { @@ -49,15 +46,15 @@ class ChannelData { public: explicit ChannelData(grpc_channel_element_args* args) { // Get the enabled and the default algorithms from channel args. - enabled_compression_algorithms_bitset_ = - grpc_channel_args_compression_algorithm_get_states(args->channel_args); + enabled_compression_algorithms_ = + grpc_core::CompressionAlgorithmSet::FromChannelArgs(args->channel_args); default_compression_algorithm_ = - grpc_channel_args_get_channel_default_compression_algorithm( - args->channel_args); + grpc_core::DefaultCompressionAlgorithmFromChannelArgs( + args->channel_args) + .value_or(GRPC_COMPRESS_NONE); // Make sure the default is enabled. - if (size_t(default_compression_algorithm_) >= 32 || - !grpc_core::GetBit(enabled_compression_algorithms_bitset_, - default_compression_algorithm_)) { + if (!enabled_compression_algorithms_.IsSet( + default_compression_algorithm_)) { const char* name; if (!grpc_compression_algorithm_name(default_compression_algorithm_, &name)) { @@ -68,12 +65,6 @@ class ChannelData { name); default_compression_algorithm_ = GRPC_COMPRESS_NONE; } - enabled_message_compression_algorithms_bitset_ = - grpc_compression_bitset_to_message_bitset( - enabled_compression_algorithms_bitset_); - enabled_stream_compression_algorithms_bitset_ = - grpc_compression_bitset_to_stream_bitset( - enabled_compression_algorithms_bitset_); GPR_ASSERT(!args->is_last); } @@ -81,27 +72,15 @@ class ChannelData { return default_compression_algorithm_; } - uint32_t enabled_compression_algorithms_bitset() const { - return enabled_compression_algorithms_bitset_; - } - - uint32_t enabled_message_compression_algorithms_bitset() const { - return enabled_message_compression_algorithms_bitset_; - } - - uint32_t enabled_stream_compression_algorithms_bitset() const { - return enabled_stream_compression_algorithms_bitset_; + grpc_core::CompressionAlgorithmSet enabled_compression_algorithms() const { + return enabled_compression_algorithms_; } private: /** The default, channel-level, compression algorithm */ grpc_compression_algorithm default_compression_algorithm_; - /** Bitset of enabled compression algorithms */ - uint32_t enabled_compression_algorithms_bitset_; - /** Bitset of enabled message compression algorithms */ - uint32_t enabled_message_compression_algorithms_bitset_; - /** Bitset of enabled stream compression algorithms */ - uint32_t enabled_stream_compression_algorithms_bitset_; + /** Enabled compression algorithms */ + grpc_core::CompressionAlgorithmSet enabled_compression_algorithms_; }; class CallData { @@ -111,12 +90,9 @@ class CallData { ChannelData* channeld = static_cast<ChannelData*>(elem->channel_data); // The call's message compression algorithm is set to channel's default // setting. It can be overridden later by initial metadata. - if (GPR_LIKELY( - grpc_core::GetBit(channeld->enabled_compression_algorithms_bitset(), - channeld->default_compression_algorithm()))) { - message_compression_algorithm_ = - grpc_compression_algorithm_to_message_compression_algorithm( - channeld->default_compression_algorithm()); + if (GPR_LIKELY(channeld->enabled_compression_algorithms().IsSet( + channeld->default_compression_algorithm()))) { + compression_algorithm_ = channeld->default_compression_algorithm(); } GRPC_CLOSURE_INIT(&start_send_message_batch_in_call_combiner_, StartSendMessageBatch, elem, grpc_schedule_on_exec_ctx); @@ -136,8 +112,8 @@ class CallData { bool SkipMessageCompression(); void InitializeState(grpc_call_element* elem); - grpc_error_handle ProcessSendInitialMetadata( - grpc_call_element* elem, grpc_metadata_batch* initial_metadata); + void 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_handle unused); @@ -152,8 +128,7 @@ class CallData { 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_compression_algorithm compression_algorithm_ = GRPC_COMPRESS_NONE; grpc_error_handle cancel_error_ = GRPC_ERROR_NONE; grpc_transport_stream_op_batch* send_message_batch_ = nullptr; bool seen_initial_metadata_ = false; @@ -163,10 +138,6 @@ class CallData { /* The fields below are only initialized when we compress the payload. * Keep them at the bottom of the struct, so they don't pollute the * cache-lines. */ - grpc_linked_mdelem message_compression_algorithm_storage_; - grpc_linked_mdelem stream_compression_algorithm_storage_; - grpc_linked_mdelem accept_encoding_storage_; - grpc_linked_mdelem accept_stream_encoding_storage_; grpc_slice_buffer slices_; /**< Buffers up input slices to be compressed */ // Allocate space for the replacement stream std::aligned_storage<sizeof(grpc_core::SliceBufferByteStream), @@ -188,44 +159,7 @@ bool CallData::SkipMessageCompression() { } // If this call doesn't have any message compression algorithm set, skip // message compression. - return message_compression_algorithm_ == GRPC_MESSAGE_COMPRESS_NONE; -} - -// Determines the compression algorithm from the initial metadata and the -// channel's default setting. -grpc_compression_algorithm FindCompressionAlgorithm( - grpc_metadata_batch* initial_metadata, ChannelData* channeld) { - if (initial_metadata->legacy_index()->named.grpc_internal_encoding_request == - nullptr) { - return channeld->default_compression_algorithm(); - } - grpc_compression_algorithm compression_algorithm; - // Parse the compression algorithm from the initial metadata. - grpc_mdelem md = initial_metadata->legacy_index() - ->named.grpc_internal_encoding_request->md; - GPR_ASSERT(grpc_compression_algorithm_parse(GRPC_MDVALUE(md), - &compression_algorithm)); - // Remove this metadata since it's an internal one (i.e., it won't be - // transmitted out). - initial_metadata->Remove(GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST); - // Check if that algorithm is enabled. Note that GRPC_COMPRESS_NONE is always - // enabled. - // TODO(juanlishen): Maybe use channel default or abort() if the algorithm - // from the initial metadata is disabled. - if (GPR_LIKELY( - grpc_core::GetBit(channeld->enabled_compression_algorithms_bitset(), - compression_algorithm))) { - return compression_algorithm; - } - const char* algorithm_name; - GPR_ASSERT( - grpc_compression_algorithm_name(compression_algorithm, &algorithm_name)); - gpr_log(GPR_ERROR, - "Invalid compression algorithm from initial metadata: '%s' " - "(previously disabled). " - "Will not compress.", - algorithm_name); - return GRPC_COMPRESS_NONE; + return compression_algorithm_ == GRPC_COMPRESS_NONE; } void CallData::InitializeState(grpc_call_element* elem) { @@ -238,53 +172,28 @@ void CallData::InitializeState(grpc_call_element* elem) { grpc_schedule_on_exec_ctx); } -grpc_error_handle CallData::ProcessSendInitialMetadata( +void CallData::ProcessSendInitialMetadata( grpc_call_element* elem, grpc_metadata_batch* initial_metadata) { ChannelData* channeld = static_cast<ChannelData*>(elem->channel_data); // Find the compression algorithm. - grpc_compression_algorithm compression_algorithm = - FindCompressionAlgorithm(initial_metadata, channeld); - // Note that at most one of the following algorithms can be set. - message_compression_algorithm_ = - grpc_compression_algorithm_to_message_compression_algorithm( - compression_algorithm); - grpc_stream_compression_algorithm stream_compression_algorithm = - grpc_compression_algorithm_to_stream_compression_algorithm( - compression_algorithm); - // Hint compression algorithm. - grpc_error_handle error = GRPC_ERROR_NONE; - if (message_compression_algorithm_ != GRPC_MESSAGE_COMPRESS_NONE) { - InitializeState(elem); - error = grpc_metadata_batch_add_tail( - initial_metadata, &message_compression_algorithm_storage_, - grpc_message_compression_encoding_mdelem( - message_compression_algorithm_), - GRPC_BATCH_GRPC_ENCODING); - } else if (stream_compression_algorithm != GRPC_STREAM_COMPRESS_NONE) { - InitializeState(elem); - error = grpc_metadata_batch_add_tail( - initial_metadata, &stream_compression_algorithm_storage_, - grpc_stream_compression_encoding_mdelem(stream_compression_algorithm), - GRPC_BATCH_CONTENT_ENCODING); + compression_algorithm_ = + initial_metadata->Take(grpc_core::GrpcInternalEncodingRequest()) + .value_or(channeld->default_compression_algorithm()); + switch (compression_algorithm_) { + case GRPC_COMPRESS_NONE: + break; + case GRPC_COMPRESS_DEFLATE: + case GRPC_COMPRESS_GZIP: + InitializeState(elem); + initial_metadata->Set(grpc_core::GrpcEncodingMetadata(), + compression_algorithm_); + break; + case GRPC_COMPRESS_ALGORITHMS_COUNT: + abort(); } - if (error != GRPC_ERROR_NONE) return error; // Convey supported compression algorithms. - error = grpc_metadata_batch_add_tail( - initial_metadata, &accept_encoding_storage_, - GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS( - channeld->enabled_message_compression_algorithms_bitset()), - GRPC_BATCH_GRPC_ACCEPT_ENCODING); - if (error != GRPC_ERROR_NONE) return error; - // Do not overwrite accept-encoding header if it already presents (e.g., added - // by some proxy). - if (!initial_metadata->legacy_index()->named.accept_encoding) { - error = grpc_metadata_batch_add_tail( - initial_metadata, &accept_stream_encoding_storage_, - GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS( - channeld->enabled_stream_compression_algorithms_bitset()), - GRPC_BATCH_ACCEPT_ENCODING); - } - return error; + initial_metadata->Set(grpc_core::GrpcAcceptEncodingMetadata(), + channeld->enabled_compression_algorithms()); } void CallData::SendMessageOnComplete(void* calld_arg, grpc_error_handle error) { @@ -304,15 +213,13 @@ void CallData::SendMessageBatchContinue(grpc_call_element* elem) { } void CallData::FinishSendMessage(grpc_call_element* elem) { - GPR_DEBUG_ASSERT(message_compression_algorithm_ != - GRPC_MESSAGE_COMPRESS_NONE); + GPR_DEBUG_ASSERT(compression_algorithm_ != GRPC_COMPRESS_NONE); // Compress the data if appropriate. grpc_slice_buffer tmp; grpc_slice_buffer_init(&tmp); uint32_t send_flags = send_message_batch_->payload->send_message.send_message->flags(); - bool did_compress = - grpc_msg_compress(message_compression_algorithm_, &slices_, &tmp); + bool did_compress = grpc_msg_compress(compression_algorithm_, &slices_, &tmp); if (did_compress) { if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) { const char* algo_name; @@ -320,8 +227,8 @@ void CallData::FinishSendMessage(grpc_call_element* elem) { const size_t after_size = tmp.length; const float savings_ratio = 1.0f - static_cast<float>(after_size) / static_cast<float>(before_size); - GPR_ASSERT(grpc_message_compression_algorithm_name( - message_compression_algorithm_, &algo_name)); + GPR_ASSERT( + grpc_compression_algorithm_name(compression_algorithm_, &algo_name)); gpr_log(GPR_INFO, "Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR " bytes (%.2f%% savings)", @@ -332,8 +239,8 @@ void CallData::FinishSendMessage(grpc_call_element* elem) { } else { if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) { const char* algo_name; - GPR_ASSERT(grpc_message_compression_algorithm_name( - message_compression_algorithm_, &algo_name)); + GPR_ASSERT( + grpc_compression_algorithm_name(compression_algorithm_, &algo_name)); gpr_log(GPR_INFO, "Algorithm '%s' enabled but decided not to compress. Input size: " "%" PRIuPTR, @@ -465,13 +372,8 @@ void CallData::CompressStartTransportStreamOpBatch( // Handle send_initial_metadata. if (batch->send_initial_metadata) { GPR_ASSERT(!seen_initial_metadata_); - grpc_error_handle error = ProcessSendInitialMetadata( + 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, - call_combiner_); - return; - } seen_initial_metadata_ = true; // If we had previously received a batch containing a send_message op, // handle it now. Note that we need to re-enter the call combiner diff --git a/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_decompress_filter.cc b/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_decompress_filter.cc index 0fc6831a81..d309abec1d 100644 --- a/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_decompress_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_decompress_filter.cc @@ -33,8 +33,6 @@ #include "src/core/ext/filters/message_size/message_size_filter.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/compression/algorithm_metadata.h" -#include "src/core/lib/compression/compression_args.h" #include "src/core/lib/compression/compression_internal.h" #include "src/core/lib/compression/message_compress.h" #include "src/core/lib/gpr/string.h" @@ -114,7 +112,7 @@ class CallData { // Fields for handling recv_message_ready callback bool seen_recv_message_ready_ = false; int max_recv_message_length_; - grpc_message_compression_algorithm algorithm_ = GRPC_MESSAGE_COMPRESS_NONE; + grpc_compression_algorithm algorithm_ = GRPC_COMPRESS_NONE; grpc_closure on_recv_message_ready_; grpc_closure* original_recv_message_ready_ = nullptr; grpc_closure on_recv_message_next_done_; @@ -133,30 +131,12 @@ class CallData { grpc_error_handle on_recv_trailing_metadata_ready_error_ = GRPC_ERROR_NONE; }; -grpc_message_compression_algorithm DecodeMessageCompressionAlgorithm( - grpc_mdelem md) { - grpc_message_compression_algorithm algorithm = - grpc_message_compression_algorithm_from_slice(GRPC_MDVALUE(md)); - if (algorithm == GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT) { - char* md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md)); - gpr_log(GPR_ERROR, - "Invalid incoming message compression algorithm: '%s'. " - "Interpreting incoming data as uncompressed.", - md_c_str); - gpr_free(md_c_str); - return GRPC_MESSAGE_COMPRESS_NONE; - } - return algorithm; -} - void CallData::OnRecvInitialMetadataReady(void* arg, grpc_error_handle error) { CallData* calld = static_cast<CallData*>(arg); if (error == GRPC_ERROR_NONE) { - grpc_linked_mdelem* grpc_encoding = - calld->recv_initial_metadata_->legacy_index()->named.grpc_encoding; - if (grpc_encoding != nullptr) { - calld->algorithm_ = DecodeMessageCompressionAlgorithm(grpc_encoding->md); - } + calld->algorithm_ = + calld->recv_initial_metadata_->get(GrpcEncodingMetadata()) + .value_or(GRPC_COMPRESS_NONE); } calld->MaybeResumeOnRecvMessageReady(); calld->MaybeResumeOnRecvTrailingMetadataReady(); @@ -184,7 +164,7 @@ void CallData::OnRecvMessageReady(void* arg, grpc_error_handle error) { "OnRecvInitialMetadataReady"); return; } - if (calld->algorithm_ != GRPC_MESSAGE_COMPRESS_NONE) { + if (calld->algorithm_ != GRPC_COMPRESS_NONE) { // recv_message can be NULL if trailing metadata is received instead of // message, or it's possible that the message was not compressed. if (*calld->recv_message_ == nullptr || diff --git a/contrib/libs/grpc/src/core/ext/filters/http/server/http_server_filter.cc b/contrib/libs/grpc/src/core/ext/filters/http/server/http_server_filter.cc index 1fd26386ae..5e5edda447 100644 --- a/contrib/libs/grpc/src/core/ext/filters/http/server/http_server_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/http/server/http_server_filter.cc @@ -32,10 +32,6 @@ #include "src/core/lib/slice/percent_encoding.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/transport/static_metadata.h" - -#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_handle err); @@ -67,10 +63,6 @@ struct call_data { grpc_core::CallCombiner* call_combiner; - // Outgoing headers to add to send_initial_metadata. - grpc_linked_mdelem status; - grpc_linked_mdelem content_type; - // If we see the recv_message contents in the GET query string, we // store it here. grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> read_stream; @@ -121,63 +113,37 @@ static void hs_add_error(const char* error_name, grpc_error_handle* cumulative, *cumulative = grpc_error_add_child(*cumulative, new_err); } -// Metadata equality within this filter leverages the fact that the sender was -// likely using the gRPC chttp2 transport, in which case the encoder would emit -// indexed values, in which case the local hpack parser would intern the -// relevant metadata, allowing a simple pointer comparison. -// -// That said, if the header was transmitted sans indexing/encoding, we still -// need to do the right thing. -// -// Assumptions: -// 1) The keys for a and b_static must match -// 2) b_static must be a statically allocated metadata object. -// 3) It is assumed that the remote end is indexing, but not necessary. -// TODO(arjunroy): Revisit this method when grpc_mdelem is strongly typed. -static bool md_strict_equal(grpc_mdelem a, grpc_mdelem b_static) { - // Hpack encoder on the remote side should emit indexed values, in which case - // hpack parser on this end should pick up interned values, in which case the - // pointer comparison alone is enough. - // - if (GPR_LIKELY(GRPC_MDELEM_IS_INTERNED(a))) { - return a.payload == b_static.payload; - } else { - return grpc_slice_eq_static_interned(GRPC_MDVALUE(a), - GRPC_MDVALUE(b_static)); - } -} - static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, grpc_metadata_batch* b) { call_data* calld = static_cast<call_data*>(elem->call_data); grpc_error_handle error = GRPC_ERROR_NONE; static const char* error_name = "Failed processing incoming headers"; - if (b->legacy_index()->named.method != nullptr) { - if (md_strict_equal(b->legacy_index()->named.method->md, - GRPC_MDELEM_METHOD_POST)) { - *calld->recv_initial_metadata_flags &= - ~(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | - GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); - } else if (md_strict_equal(b->legacy_index()->named.method->md, - GRPC_MDELEM_METHOD_PUT)) { - *calld->recv_initial_metadata_flags &= - ~GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; - *calld->recv_initial_metadata_flags |= - GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; - } else if (md_strict_equal(b->legacy_index()->named.method->md, - GRPC_MDELEM_METHOD_GET)) { - *calld->recv_initial_metadata_flags |= - GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; - *calld->recv_initial_metadata_flags &= - ~GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; - } else { - hs_add_error(error_name, &error, - grpc_attach_md_to_error( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->legacy_index()->named.method->md)); + auto method = b->get(grpc_core::HttpMethodMetadata()); + if (method.has_value()) { + switch (*method) { + case grpc_core::HttpMethodMetadata::kPost: + *calld->recv_initial_metadata_flags &= + ~(GRPC_INITIAL_METADATA_CACHEABLE_REQUEST | + GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST); + break; + case grpc_core::HttpMethodMetadata::kPut: + *calld->recv_initial_metadata_flags &= + ~GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; + *calld->recv_initial_metadata_flags |= + GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + break; + case grpc_core::HttpMethodMetadata::kGet: + *calld->recv_initial_metadata_flags |= + GRPC_INITIAL_METADATA_CACHEABLE_REQUEST; + *calld->recv_initial_metadata_flags &= + ~GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST; + break; + case grpc_core::HttpMethodMetadata::kInvalid: + hs_add_error(error_name, &error, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad method header")); + break; } - b->Remove(GRPC_BATCH_METHOD); } else { hs_add_error(error_name, &error, grpc_error_set_str( @@ -198,19 +164,12 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad te header")); } - if (b->legacy_index()->named.scheme != nullptr) { - if (!md_strict_equal(b->legacy_index()->named.scheme->md, - GRPC_MDELEM_SCHEME_HTTP) && - !md_strict_equal(b->legacy_index()->named.scheme->md, - GRPC_MDELEM_SCHEME_HTTPS) && - !grpc_mdelem_static_value_eq(b->legacy_index()->named.scheme->md, - GRPC_MDELEM_SCHEME_GRPC)) { + auto scheme = b->Take(grpc_core::HttpSchemeMetadata()); + if (scheme.has_value()) { + if (*scheme == grpc_core::HttpSchemeMetadata::kInvalid) { hs_add_error(error_name, &error, - grpc_attach_md_to_error( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad header"), - b->legacy_index()->named.scheme->md)); + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Bad :scheme header")); } - b->Remove(GRPC_BATCH_SCHEME); } else { hs_add_error(error_name, &error, grpc_error_set_str( @@ -218,40 +177,10 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_ERROR_STR_KEY, ":scheme")); } - if (b->legacy_index()->named.content_type != nullptr) { - if (!grpc_mdelem_static_value_eq( - b->legacy_index()->named.content_type->md, - GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC)) { - if (grpc_slice_buf_start_eq( - GRPC_MDVALUE(b->legacy_index()->named.content_type->md), - EXPECTED_CONTENT_TYPE, EXPECTED_CONTENT_TYPE_LENGTH) && - (GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->legacy_index() - ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == - '+' || - GRPC_SLICE_START_PTR(GRPC_MDVALUE( - b->legacy_index() - ->named.content_type->md))[EXPECTED_CONTENT_TYPE_LENGTH] == - ';')) { - /* Although the C implementation doesn't (currently) generate them, - any custom +-suffix is explicitly valid. */ - /* TODO(klempner): We should consider preallocating common values such - as +proto or +json, or at least stashing them if we see them. */ - /* TODO(klempner): Should we be surfacing this to application code? */ - } else { - /* TODO(klempner): We're currently allowing this, but we shouldn't - see it without a proxy so log for now. */ - char* val = grpc_dump_slice( - GRPC_MDVALUE(b->legacy_index()->named.content_type->md), - GPR_DUMP_ASCII); - gpr_log(GPR_INFO, "Unexpected content-type '%s'", val); - gpr_free(val); - } - } - b->Remove(GRPC_BATCH_CONTENT_TYPE); - } + b->Remove(grpc_core::ContentTypeMetadata()); - if (b->legacy_index()->named.path == nullptr) { + grpc_core::Slice* path_slice = b->get_pointer(grpc_core::HttpPathMetadata()); + if (path_slice == nullptr) { hs_add_error(error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), @@ -260,25 +189,18 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, GRPC_INITIAL_METADATA_CACHEABLE_REQUEST) { /* We have a cacheable request made with GET verb. The path contains the * query parameter which is base64 encoded request payload. */ - const char k_query_separator = '?'; - grpc_slice path_slice = GRPC_MDVALUE(b->legacy_index()->named.path->md); - uint8_t* path_ptr = GRPC_SLICE_START_PTR(path_slice); - size_t path_length = GRPC_SLICE_LENGTH(path_slice); + static const char kQuerySeparator = '?'; /* offset of the character '?' */ - size_t offset = 0; - for (offset = 0; offset < path_length && *path_ptr != k_query_separator; - path_ptr++, offset++) { - } - if (offset < path_length) { - grpc_slice query_slice = - grpc_slice_sub(path_slice, offset + 1, path_length); + auto it = + std::find(path_slice->begin(), path_slice->end(), kQuerySeparator); + if (it != path_slice->end()) { + const auto query_start = it - path_slice->begin() + 1; + auto query_slice = path_slice->RefSubSlice( + query_start, path_slice->size() - query_start); /* substitute path metadata with just the path (not query) */ - grpc_mdelem mdelem_path_without_query = grpc_mdelem_from_slices( - GRPC_MDSTR_PATH, grpc_slice_sub(path_slice, 0, offset)); - - (void)b->Substitute(b->legacy_index()->named.path, - mdelem_path_without_query); + auto path_without_query = path_slice->TakeSubSlice(0, query_start - 1); + *path_slice = std::move(path_without_query); /* decode payload from query and add to the slice buffer to be returned */ const int k_url_safe = 1; @@ -287,25 +209,24 @@ static grpc_error_handle hs_filter_incoming_metadata(grpc_call_element* elem, grpc_slice_buffer_add( &read_slice_buffer, grpc_base64_decode_with_len( - reinterpret_cast<const char*> GRPC_SLICE_START_PTR(query_slice), - GRPC_SLICE_LENGTH(query_slice), k_url_safe)); + reinterpret_cast<const char*>(query_slice.begin()), + query_slice.size(), k_url_safe)); calld->read_stream.Init(&read_slice_buffer, 0); grpc_slice_buffer_destroy_internal(&read_slice_buffer); calld->have_read_stream = true; - grpc_slice_unref_internal(query_slice); } else { gpr_log(GPR_ERROR, "GET request without QUERY"); } } - if (b->legacy_index()->named.authority == nullptr) { + if (b->get_pointer(grpc_core::HttpAuthorityMetadata()) == nullptr) { y_absl::optional<grpc_core::Slice> host = b->Take(grpc_core::HostMetadata()); if (host.has_value()) { - b->Append(":authority", std::move(*host)); + b->Set(grpc_core::HttpAuthorityMetadata(), std::move(*host)); } } - if (b->legacy_index()->named.authority == nullptr) { + if (b->get_pointer(grpc_core::HttpAuthorityMetadata()) == nullptr) { hs_add_error(error_name, &error, grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("Missing header"), @@ -410,17 +331,11 @@ static grpc_error_handle hs_mutate_op(grpc_call_element* elem, if (op->send_initial_metadata) { grpc_error_handle error = GRPC_ERROR_NONE; static const char* error_name = "Failed sending initial metadata"; - hs_add_error( - error_name, &error, - grpc_metadata_batch_add_head( - op->payload->send_initial_metadata.send_initial_metadata, - &calld->status, GRPC_MDELEM_STATUS_200, GRPC_BATCH_STATUS)); - hs_add_error(error_name, &error, - grpc_metadata_batch_add_tail( - op->payload->send_initial_metadata.send_initial_metadata, - &calld->content_type, - GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC, - GRPC_BATCH_CONTENT_TYPE)); + op->payload->send_initial_metadata.send_initial_metadata->Set( + grpc_core::HttpStatusMetadata(), 200); + op->payload->send_initial_metadata.send_initial_metadata->Set( + grpc_core::ContentTypeMetadata(), + grpc_core::ContentTypeMetadata::kApplicationGrpc); hs_add_error(error_name, &error, hs_filter_outgoing_metadata( op->payload->send_initial_metadata.send_initial_metadata)); diff --git a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc index b9479e3c83..ed8778a54c 100644 --- a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc @@ -27,13 +27,13 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> -#include "src/core/ext/service_config/service_config_call_data.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/channel_stack_builder.h" #include "src/core/lib/config/core_configuration.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/service_config/service_config_call_data.h" #include "src/core/lib/surface/call.h" static void recv_message_ready(void* user_data, grpc_error_handle error); diff --git a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h index b196534394..ec011f5049 100644 --- a/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h +++ b/contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h @@ -19,8 +19,8 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/service_config/service_config_parser.h" extern const grpc_channel_filter grpc_message_size_filter; diff --git a/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.cc b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.cc new file mode 100644 index 0000000000..1435a049e2 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.cc @@ -0,0 +1,157 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/filters/rbac/rbac_filter.h" + +#include "src/core/ext/filters/rbac/rbac_service_config_parser.h" +#include "src/core/lib/security/authorization/grpc_authorization_engine.h" +#include "src/core/lib/service_config/service_config_call_data.h" +#include "src/core/lib/transport/metadata_batch.h" + +namespace grpc_core { + +// +// RbacFilter::CallData +// + +// CallData + +grpc_error_handle RbacFilter::CallData::Init( + grpc_call_element* elem, const grpc_call_element_args* args) { + new (elem->call_data) CallData(elem, *args); + return GRPC_ERROR_NONE; +} + +void RbacFilter::CallData::Destroy(grpc_call_element* elem, + const grpc_call_final_info* /*final_info*/, + grpc_closure* /*then_schedule_closure*/) { + auto* calld = static_cast<CallData*>(elem->call_data); + calld->~CallData(); +} + +void RbacFilter::CallData::StartTransportStreamOpBatch( + grpc_call_element* elem, grpc_transport_stream_op_batch* op) { + CallData* calld = static_cast<CallData*>(elem->call_data); + if (op->recv_initial_metadata) { + calld->recv_initial_metadata_ = + op->payload->recv_initial_metadata.recv_initial_metadata; + calld->original_recv_initial_metadata_ready_ = + op->payload->recv_initial_metadata.recv_initial_metadata_ready; + op->payload->recv_initial_metadata.recv_initial_metadata_ready = + &calld->recv_initial_metadata_ready_; + } + // Chain to the next filter. + grpc_call_next_op(elem, op); +} + +RbacFilter::CallData::CallData(grpc_call_element* elem, + const grpc_call_element_args& args) + : call_context_(args.context) { + GRPC_CLOSURE_INIT(&recv_initial_metadata_ready_, RecvInitialMetadataReady, + elem, grpc_schedule_on_exec_ctx); +} + +void RbacFilter::CallData::RecvInitialMetadataReady(void* user_data, + grpc_error_handle error) { + grpc_call_element* elem = static_cast<grpc_call_element*>(user_data); + CallData* calld = static_cast<CallData*>(elem->call_data); + if (error == GRPC_ERROR_NONE) { + // Fetch and apply the rbac policy from the service config. + auto* service_config_call_data = static_cast<ServiceConfigCallData*>( + calld->call_context_[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value); + auto* method_params = static_cast<RbacMethodParsedConfig*>( + service_config_call_data->GetMethodParsedConfig( + RbacServiceConfigParser::ParserIndex())); + if (method_params == nullptr) { + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No RBAC policy found."); + } else { + RbacFilter* chand = static_cast<RbacFilter*>(elem->channel_data); + auto* authorization_engine = + method_params->authorization_engine(chand->index_); + if (authorization_engine + ->Evaluate(EvaluateArgs(calld->recv_initial_metadata_, + &chand->per_channel_evaluate_args_)) + .type == AuthorizationEngine::Decision::Type::kDeny) { + error = + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unauthorized RPC rejected"); + } + } + if (error != GRPC_ERROR_NONE) { + error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_PERMISSION_DENIED); + } + } else { + GRPC_ERROR_REF(error); + } + grpc_closure* closure = calld->original_recv_initial_metadata_ready_; + calld->original_recv_initial_metadata_ready_ = nullptr; + Closure::Run(DEBUG_LOCATION, closure, error); +} + +// +// RbacFilter +// + +const grpc_channel_filter RbacFilter::kFilterVtable = { + RbacFilter::CallData::StartTransportStreamOpBatch, + grpc_channel_next_op, + sizeof(RbacFilter::CallData), + RbacFilter::CallData::Init, + grpc_call_stack_ignore_set_pollset_or_pollset_set, + RbacFilter::CallData::Destroy, + sizeof(RbacFilter), + RbacFilter::Init, + RbacFilter::Destroy, + grpc_channel_next_get_info, + "rbac_filter", +}; + +RbacFilter::RbacFilter(size_t index, + EvaluateArgs::PerChannelArgs per_channel_evaluate_args) + : index_(index), + per_channel_evaluate_args_(std::move(per_channel_evaluate_args)) {} + +grpc_error_handle RbacFilter::Init(grpc_channel_element* elem, + grpc_channel_element_args* args) { + GPR_ASSERT(elem->filter == &kFilterVtable); + auto* auth_context = grpc_find_auth_context_in_args(args->channel_args); + if (auth_context == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No auth context found"); + } + if (args->optional_transport == nullptr) { + // This should never happen since the transport is always set on the server + // side. + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No transport configured"); + } + new (elem->channel_data) RbacFilter( + grpc_channel_stack_filter_instance_number(args->channel_stack, elem), + EvaluateArgs::PerChannelArgs( + auth_context, grpc_transport_get_endpoint(args->optional_transport))); + return GRPC_ERROR_NONE; +} + +void RbacFilter::Destroy(grpc_channel_element* elem) { + auto* chand = static_cast<RbacFilter*>(elem->channel_data); + chand->~RbacFilter(); +} + +void RbacFilterInit(void) { RbacServiceConfigParser::Register(); } + +void RbacFilterShutdown(void) {} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.h b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.h new file mode 100644 index 0000000000..beedcf0360 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.h @@ -0,0 +1,74 @@ +// +// 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_RBAC_RBAC_FILTER_H +#define GRPC_CORE_EXT_FILTERS_RBAC_RBAC_FILTER_H + +#include <grpc/support/port_platform.h> + +#include "src/core/lib/channel/channel_stack.h" +#include "src/core/lib/security/authorization/evaluate_args.h" + +namespace grpc_core { + +// Filter used when xDS server config fetcher provides a configuration with an +// HTTP RBAC filter. Also serves as the type for channel data for the filter. +class RbacFilter { + public: + // This channel filter is intended to be used by connections on xDS enabled + // servers configured with RBAC. The RBAC filter fetches the RBAC policy from + // the method config of service config returned by the ServerConfigSelector, + // and enforces the RBAC policy. + static const grpc_channel_filter kFilterVtable; + + private: + 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* op); + + private: + CallData(grpc_call_element* elem, const grpc_call_element_args& args); + static void RecvInitialMetadataReady(void* user_data, + grpc_error_handle error); + + grpc_call_context_element* call_context_; + // State for keeping track of recv_initial_metadata + grpc_metadata_batch* recv_initial_metadata_ = nullptr; + grpc_closure* original_recv_initial_metadata_ready_ = nullptr; + grpc_closure recv_initial_metadata_ready_; + }; + + RbacFilter(size_t index, + EvaluateArgs::PerChannelArgs per_channel_evaluate_args); + static grpc_error_handle Init(grpc_channel_element* elem, + grpc_channel_element_args* args); + static void Destroy(grpc_channel_element* elem); + + // The index of this filter instance among instances of the same filter. + size_t index_; + // Per channel args used for authorization. + EvaluateArgs::PerChannelArgs per_channel_evaluate_args_; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_FILTERS_RBAC_RBAC_FILTER_H diff --git a/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.cc b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.cc new file mode 100644 index 0000000000..67d826a4e1 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.cc @@ -0,0 +1,605 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/filters/rbac/rbac_service_config_parser.h" + +#include "y_absl/strings/str_format.h" + +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/json/json_util.h" +#include "src/core/lib/transport/error_utils.h" + +namespace grpc_core { + +namespace { + +size_t g_rbac_parser_index; + +TString ParseRegexMatcher(const Json::Object& regex_matcher_json, + std::vector<grpc_error_handle>* error_list) { + TString regex; + ParseJsonObjectField(regex_matcher_json, "regex", ®ex, error_list); + return regex; +} + +y_absl::StatusOr<HeaderMatcher> ParseHeaderMatcher( + const Json::Object& header_matcher_json, + std::vector<grpc_error_handle>* error_list) { + TString name; + ParseJsonObjectField(header_matcher_json, "name", &name, error_list); + TString match; + HeaderMatcher::Type type = HeaderMatcher::Type(); + const Json::Object* inner_json; + int64_t start = 0; + int64_t end = 0; + bool present_match = false; + bool invert_match = false; + ParseJsonObjectField(header_matcher_json, "invertMatch", &invert_match, + error_list, /*required=*/false); + if (ParseJsonObjectField(header_matcher_json, "exactMatch", &match, + error_list, /*required=*/false)) { + type = HeaderMatcher::Type::kExact; + } else if (ParseJsonObjectField(header_matcher_json, "safeRegexMatch", + &inner_json, error_list, + /*required=*/false)) { + type = HeaderMatcher::Type::kSafeRegex; + std::vector<grpc_error_handle> safe_regex_matcher_error_list; + match = ParseRegexMatcher(*inner_json, &safe_regex_matcher_error_list); + if (!safe_regex_matcher_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR( + "safeRegexMatch", &safe_regex_matcher_error_list)); + } + } else if (ParseJsonObjectField(header_matcher_json, "rangeMatch", + &inner_json, error_list, + /*required=*/false)) { + type = HeaderMatcher::Type::kRange; + std::vector<grpc_error_handle> range_error_list; + ParseJsonObjectField(*inner_json, "start", &start, &range_error_list); + ParseJsonObjectField(*inner_json, "end", &end, &range_error_list); + if (!range_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("rangeMatch", &range_error_list)); + } + } else if (ParseJsonObjectField(header_matcher_json, "presentMatch", + &present_match, error_list, + /*required=*/false)) { + type = HeaderMatcher::Type::kPresent; + } else if (ParseJsonObjectField(header_matcher_json, "prefixMatch", &match, + error_list, /*required=*/false)) { + type = HeaderMatcher::Type::kPrefix; + } else if (ParseJsonObjectField(header_matcher_json, "suffixMatch", &match, + error_list, /*required=*/false)) { + type = HeaderMatcher::Type::kSuffix; + } else if (ParseJsonObjectField(header_matcher_json, "containsMatch", &match, + error_list, /*required=*/false)) { + type = HeaderMatcher::Type::kContains; + } else { + return y_absl::InvalidArgumentError("No valid matcher found"); + } + return HeaderMatcher::Create(name, type, match, start, end, present_match, + invert_match); +} + +y_absl::StatusOr<StringMatcher> ParseStringMatcher( + const Json::Object& string_matcher_json, + std::vector<grpc_error_handle>* error_list) { + TString match; + StringMatcher::Type type = StringMatcher::Type(); + const Json::Object* inner_json; + bool ignore_case = false; + ParseJsonObjectField(string_matcher_json, "ignoreCase", &ignore_case, + error_list, /*required=*/false); + if (ParseJsonObjectField(string_matcher_json, "exact", &match, error_list, + /*required=*/false)) { + type = StringMatcher::Type::kExact; + } else if (ParseJsonObjectField(string_matcher_json, "prefix", &match, + error_list, /*required=*/false)) { + type = StringMatcher::Type::kPrefix; + } else if (ParseJsonObjectField(string_matcher_json, "suffix", &match, + error_list, /*required=*/false)) { + type = StringMatcher::Type::kSuffix; + } else if (ParseJsonObjectField(string_matcher_json, "safeRegex", &inner_json, + error_list, /*required=*/false)) { + type = StringMatcher::Type::kSafeRegex; + std::vector<grpc_error_handle> safe_regex_matcher_error_list; + match = ParseRegexMatcher(*inner_json, &safe_regex_matcher_error_list); + if (!safe_regex_matcher_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR( + "safeRegex", &safe_regex_matcher_error_list)); + } + } else if (ParseJsonObjectField(string_matcher_json, "contains", &match, + error_list, /*required=*/false)) { + type = StringMatcher::Type::kContains; + } else { + return y_absl::InvalidArgumentError("No valid matcher found"); + } + return StringMatcher::Create(type, match, ignore_case); +} + +y_absl::StatusOr<StringMatcher> ParsePathMatcher( + const Json::Object& path_matcher_json, + std::vector<grpc_error_handle>* error_list) { + const Json::Object* string_matcher_json; + if (ParseJsonObjectField(path_matcher_json, "path", &string_matcher_json, + error_list)) { + std::vector<grpc_error_handle> sub_error_list; + auto matcher = ParseStringMatcher(*string_matcher_json, &sub_error_list); + if (!sub_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("path", &sub_error_list)); + } + return matcher; + } + return y_absl::InvalidArgumentError("No path found"); +} + +Rbac::CidrRange ParseCidrRange(const Json::Object& cidr_range_json, + std::vector<grpc_error_handle>* error_list) { + TString address_prefix; + ParseJsonObjectField(cidr_range_json, "addressPrefix", &address_prefix, + error_list); + const Json::Object* uint32_json; + uint32_t prefix_len = 0; // default value + if (ParseJsonObjectField(cidr_range_json, "prefixLen", &uint32_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> sub_error_list; + ParseJsonObjectField(*uint32_json, "value", &prefix_len, &sub_error_list); + if (!sub_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("prefixLen", &sub_error_list)); + } + } + return Rbac::CidrRange(std::move(address_prefix), prefix_len); +} + +Rbac::Permission ParsePermission(const Json::Object& permission_json, + std::vector<grpc_error_handle>* error_list) { + auto parse_permission_set = [](const Json::Object& permission_set_json, + std::vector<grpc_error_handle>* error_list) { + const Json::Array* rules_json; + std::vector<std::unique_ptr<Rbac::Permission>> permissions; + if (ParseJsonObjectField(permission_set_json, "rules", &rules_json, + error_list)) { + for (size_t i = 0; i < rules_json->size(); ++i) { + const Json::Object* permission_json; + if (!ExtractJsonType((*rules_json)[i], + y_absl::StrFormat("rules[%d]", i).c_str(), + &permission_json, error_list)) { + continue; + } + std::vector<grpc_error_handle> permission_error_list; + permissions.emplace_back(y_absl::make_unique<Rbac::Permission>( + ParsePermission(*permission_json, &permission_error_list))); + if (!permission_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrFormat("rules[%d]", i), &permission_error_list)); + } + } + } + return permissions; + }; + Rbac::Permission permission; + const Json::Object* inner_json; + bool any; + int port; + if (ParseJsonObjectField(permission_json, "andRules", &inner_json, error_list, + /*required=*/false)) { + std::vector<grpc_error_handle> and_rules_error_list; + permission = Rbac::Permission::MakeAndPermission( + parse_permission_set(*inner_json, &and_rules_error_list)); + if (!and_rules_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("andRules", &and_rules_error_list)); + } + } else if (ParseJsonObjectField(permission_json, "orRules", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> or_rules_error_list; + permission = Rbac::Permission::MakeOrPermission( + parse_permission_set(*inner_json, &or_rules_error_list)); + if (!or_rules_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("orRules", &or_rules_error_list)); + } + } else if (ParseJsonObjectField(permission_json, "any", &any, error_list, + /*required=*/false) && + any) { + permission = Rbac::Permission::MakeAnyPermission(); + } else if (ParseJsonObjectField(permission_json, "header", &inner_json, + error_list, + /*required=*/false)) { + std::vector<grpc_error_handle> header_error_list; + auto matcher = ParseHeaderMatcher(*inner_json, &header_error_list); + if (matcher.ok()) { + permission = Rbac::Permission::MakeHeaderPermission(*matcher); + } else { + header_error_list.push_back(absl_status_to_grpc_error(matcher.status())); + } + if (!header_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("header", &header_error_list)); + } + } else if (ParseJsonObjectField(permission_json, "urlPath", &inner_json, + error_list, + /*required=*/false)) { + std::vector<grpc_error_handle> url_path_error_list; + auto matcher = ParsePathMatcher(*inner_json, &url_path_error_list); + if (matcher.ok()) { + permission = Rbac::Permission::MakePathPermission(*matcher); + } else { + url_path_error_list.push_back( + absl_status_to_grpc_error(matcher.status())); + } + if (!url_path_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("urlPath", &url_path_error_list)); + } + } else if (ParseJsonObjectField(permission_json, "destinationIp", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> destination_ip_error_list; + permission = Rbac::Permission::MakeDestIpPermission( + ParseCidrRange(*inner_json, &destination_ip_error_list)); + if (!destination_ip_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR( + "destinationIp", &destination_ip_error_list)); + } + } else if (ParseJsonObjectField(permission_json, "destinationPort", &port, + error_list, /*required=*/false)) { + permission = Rbac::Permission::MakeDestPortPermission(port); + } else if (ParseJsonObjectField(permission_json, "metadata", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> metadata_error_list; + bool invert = false; + ParseJsonObjectField(*inner_json, "invert", &invert, &metadata_error_list, + /*required=*/false); + if (metadata_error_list.empty()) { + permission = Rbac::Permission::MakeMetadataPermission(invert); + } else { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("metadata", &metadata_error_list)); + } + } else if (ParseJsonObjectField(permission_json, "notRule", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> not_rule_error_list; + permission = Rbac::Permission::MakeNotPermission( + ParsePermission(*inner_json, ¬_rule_error_list)); + if (!not_rule_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("notRule", ¬_rule_error_list)); + } + } else if (ParseJsonObjectField(permission_json, "requestedServerName", + &inner_json, error_list, + /*required=*/false)) { + std::vector<grpc_error_handle> req_server_name_error_list; + auto matcher = ParseStringMatcher(*inner_json, &req_server_name_error_list); + if (matcher.ok()) { + permission = Rbac::Permission::MakeReqServerNamePermission(*matcher); + } else { + req_server_name_error_list.push_back( + absl_status_to_grpc_error(matcher.status())); + } + if (!req_server_name_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR( + "requestedServerName", &req_server_name_error_list)); + } + } else { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid rule found")); + } + return permission; +} + +Rbac::Principal ParsePrincipal(const Json::Object& principal_json, + std::vector<grpc_error_handle>* error_list) { + auto parse_principal_set = [](const Json::Object& principal_set_json, + std::vector<grpc_error_handle>* error_list) { + const Json::Array* rules_json; + std::vector<std::unique_ptr<Rbac::Principal>> principals; + if (ParseJsonObjectField(principal_set_json, "ids", &rules_json, + error_list)) { + for (size_t i = 0; i < rules_json->size(); ++i) { + const Json::Object* principal_json; + if (!ExtractJsonType((*rules_json)[i], + y_absl::StrFormat("ids[%d]", i).c_str(), + &principal_json, error_list)) { + continue; + } + std::vector<grpc_error_handle> principal_error_list; + principals.emplace_back(y_absl::make_unique<Rbac::Principal>( + ParsePrincipal(*principal_json, &principal_error_list))); + if (!principal_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrFormat("ids[%d]", i), &principal_error_list)); + } + } + } + return principals; + }; + Rbac::Principal principal; + const Json::Object* inner_json; + bool any; + if (ParseJsonObjectField(principal_json, "andIds", &inner_json, error_list, + /*required=*/false)) { + std::vector<grpc_error_handle> and_rules_error_list; + principal = Rbac::Principal::MakeAndPrincipal( + parse_principal_set(*inner_json, &and_rules_error_list)); + if (!and_rules_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("andIds", &and_rules_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "orIds", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> or_rules_error_list; + principal = Rbac::Principal::MakeOrPrincipal( + parse_principal_set(*inner_json, &or_rules_error_list)); + if (!or_rules_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("orIds", &or_rules_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "any", &any, error_list, + /*required=*/false) && + any) { + principal = Rbac::Principal::MakeAnyPrincipal(); + } else if (ParseJsonObjectField(principal_json, "authenticated", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> authenticated_error_list; + const Json::Object* principal_name_json; + if (ParseJsonObjectField(*inner_json, "principalName", &principal_name_json, + &authenticated_error_list, /*required=*/false)) { + std::vector<grpc_error_handle> principal_name_error_list; + auto matcher = + ParseStringMatcher(*principal_name_json, &principal_name_error_list); + if (matcher.ok()) { + principal = Rbac::Principal::MakeAuthenticatedPrincipal(*matcher); + } else { + principal_name_error_list.push_back( + absl_status_to_grpc_error(matcher.status())); + } + if (!principal_name_error_list.empty()) { + authenticated_error_list.push_back(GRPC_ERROR_CREATE_FROM_VECTOR( + "principalName", &principal_name_error_list)); + } + } else if (authenticated_error_list.empty()) { + // No principalName found. Match for all users. + principal = Rbac::Principal::MakeAnyPrincipal(); + } else { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR( + "authenticated", &authenticated_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "sourceIp", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> source_ip_error_list; + principal = Rbac::Principal::MakeSourceIpPrincipal( + ParseCidrRange(*inner_json, &source_ip_error_list)); + if (!source_ip_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("sourceIp", &source_ip_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "directRemoteIp", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> direct_remote_ip_error_list; + principal = Rbac::Principal::MakeDirectRemoteIpPrincipal( + ParseCidrRange(*inner_json, &direct_remote_ip_error_list)); + if (!direct_remote_ip_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR( + "directRemoteIp", &direct_remote_ip_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "remoteIp", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> remote_ip_error_list; + principal = Rbac::Principal::MakeRemoteIpPrincipal( + ParseCidrRange(*inner_json, &remote_ip_error_list)); + if (!remote_ip_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("remoteIp", &remote_ip_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "header", &inner_json, + error_list, + /*required=*/false)) { + std::vector<grpc_error_handle> header_error_list; + auto matcher = ParseHeaderMatcher(*inner_json, &header_error_list); + if (matcher.ok()) { + principal = Rbac::Principal::MakeHeaderPrincipal(*matcher); + } else { + header_error_list.push_back(absl_status_to_grpc_error(matcher.status())); + } + if (!header_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("header", &header_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "urlPath", &inner_json, + error_list, + /*required=*/false)) { + std::vector<grpc_error_handle> url_path_error_list; + auto matcher = ParsePathMatcher(*inner_json, &url_path_error_list); + if (matcher.ok()) { + principal = Rbac::Principal::MakePathPrincipal(*matcher); + } else { + url_path_error_list.push_back( + absl_status_to_grpc_error(matcher.status())); + } + if (!url_path_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("urlPath", &url_path_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "metadata", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> metadata_error_list; + bool invert = false; + ParseJsonObjectField(*inner_json, "invert", &invert, &metadata_error_list, + /*required=*/false); + if (metadata_error_list.empty()) { + principal = Rbac::Principal::MakeMetadataPrincipal(invert); + } else { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("metadata", &metadata_error_list)); + } + } else if (ParseJsonObjectField(principal_json, "notId", &inner_json, + error_list, /*required=*/false)) { + std::vector<grpc_error_handle> not_rule_error_list; + principal = Rbac::Principal::MakeNotPrincipal( + ParsePrincipal(*inner_json, ¬_rule_error_list)); + if (!not_rule_error_list.empty()) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_VECTOR("notId", ¬_rule_error_list)); + } + } else { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid id found")); + } + return principal; +} + +Rbac::Policy ParsePolicy(const Json::Object& policy_json, + std::vector<grpc_error_handle>* error_list) { + Rbac::Policy policy; + const Json::Array* permissions_json_array; + std::vector<std::unique_ptr<Rbac::Permission>> permissions; + if (ParseJsonObjectField(policy_json, "permissions", &permissions_json_array, + error_list)) { + for (size_t i = 0; i < permissions_json_array->size(); ++i) { + const Json::Object* permission_json; + if (!ExtractJsonType((*permissions_json_array)[i], + y_absl::StrFormat("permissions[%d]", i), + &permission_json, error_list)) { + continue; + } + std::vector<grpc_error_handle> permission_error_list; + permissions.emplace_back(y_absl::make_unique<Rbac::Permission>( + ParsePermission(*permission_json, &permission_error_list))); + if (!permission_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrFormat("permissions[%d]", i), &permission_error_list)); + } + } + } + const Json::Array* principals_json_array; + std::vector<std::unique_ptr<Rbac::Principal>> principals; + if (ParseJsonObjectField(policy_json, "principals", &principals_json_array, + error_list)) { + for (size_t i = 0; i < principals_json_array->size(); ++i) { + const Json::Object* principal_json; + if (!ExtractJsonType((*principals_json_array)[i], + y_absl::StrFormat("principals[%d]", i), + &principal_json, error_list)) { + continue; + } + std::vector<grpc_error_handle> principal_error_list; + principals.emplace_back(y_absl::make_unique<Rbac::Principal>( + ParsePrincipal(*principal_json, &principal_error_list))); + if (!principal_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrFormat("principals[%d]", i), &principal_error_list)); + } + } + } + policy.permissions = + Rbac::Permission::MakeOrPermission(std::move(permissions)); + policy.principals = Rbac::Principal::MakeOrPrincipal(std::move(principals)); + return policy; +} + +Rbac ParseRbac(const Json::Object& rbac_json, + std::vector<grpc_error_handle>* error_list) { + Rbac rbac; + const Json::Object* rules_json; + if (!ParseJsonObjectField(rbac_json, "rules", &rules_json, error_list, + /*required=*/false)) { + // No enforcing to be applied. An empty deny policy with an empty map is + // equivalent to no enforcing. + return Rbac(Rbac::Action::kDeny, {}); + } + int action; + if (ParseJsonObjectField(*rules_json, "action", &action, error_list)) { + if (action > 1) { + error_list->push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unknown action")); + } + } + rbac.action = static_cast<Rbac::Action>(action); + const Json::Object* policies_json; + if (ParseJsonObjectField(*rules_json, "policies", &policies_json, error_list, + /*required=*/false)) { + for (const auto& entry : *policies_json) { + std::vector<grpc_error_handle> policy_error_list; + rbac.policies.emplace( + entry.first, + ParsePolicy(entry.second.object_value(), &policy_error_list)); + if (!policy_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrFormat("policies key:'%s'", entry.first.c_str()), + &policy_error_list)); + } + } + } + return rbac; +} + +std::vector<Rbac> ParseRbacArray(const Json::Array& policies_json_array, + std::vector<grpc_error_handle>* error_list) { + std::vector<Rbac> policies; + for (size_t i = 0; i < policies_json_array.size(); ++i) { + const Json::Object* rbac_json; + if (!ExtractJsonType(policies_json_array[i], + y_absl::StrFormat("rbacPolicy[%d]", i), &rbac_json, + error_list)) { + continue; + } + std::vector<grpc_error_handle> rbac_policy_error_list; + policies.emplace_back(ParseRbac(*rbac_json, &rbac_policy_error_list)); + if (!rbac_policy_error_list.empty()) { + error_list->push_back(GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrFormat("rbacPolicy[%d]", i), &rbac_policy_error_list)); + } + } + return policies; +} + +} // namespace + +std::unique_ptr<ServiceConfigParser::ParsedConfig> +RbacServiceConfigParser::ParsePerMethodParams(const grpc_channel_args* args, + const Json& json, + grpc_error_handle* error) { + GPR_DEBUG_ASSERT(error != nullptr && *error == GRPC_ERROR_NONE); + // Only parse rbac policy if the channel arg is present + if (!grpc_channel_args_find_bool(args, GRPC_ARG_PARSE_RBAC_METHOD_CONFIG, + false)) { + return nullptr; + } + std::vector<Rbac> rbac_policies; + std::vector<grpc_error_handle> error_list; + const Json::Array* policies_json_array; + if (ParseJsonObjectField(json.object_value(), "rbacPolicy", + &policies_json_array, &error_list)) { + rbac_policies = ParseRbacArray(*policies_json_array, &error_list); + } + *error = GRPC_ERROR_CREATE_FROM_VECTOR("Rbac parser", &error_list); + if (*error != GRPC_ERROR_NONE || rbac_policies.empty()) { + return nullptr; + } + return y_absl::make_unique<RbacMethodParsedConfig>(std::move(rbac_policies)); +} + +void RbacServiceConfigParser::Register() { + g_rbac_parser_index = ServiceConfigParser::RegisterParser( + y_absl::make_unique<RbacServiceConfigParser>()); +} + +size_t RbacServiceConfigParser::ParserIndex() { return g_rbac_parser_index; } + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.h b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.h new file mode 100644 index 0000000000..96fbec636b --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.h @@ -0,0 +1,70 @@ +// +// 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_RBAC_RBAC_SERVICE_CONFIG_PARSER_H +#define GRPC_CORE_EXT_FILTERS_RBAC_RBAC_SERVICE_CONFIG_PARSER_H + +#include <grpc/support/port_platform.h> + +#include <vector> + +#include "src/core/lib/security/authorization/grpc_authorization_engine.h" +#include "src/core/lib/service_config/service_config_parser.h" + +namespace grpc_core { + +// Channel arg key for enabling parsing RBAC via method config. +#define GRPC_ARG_PARSE_RBAC_METHOD_CONFIG \ + "grpc.internal.parse_rbac_method_config" + +class RbacMethodParsedConfig : public ServiceConfigParser::ParsedConfig { + public: + explicit RbacMethodParsedConfig(std::vector<Rbac> rbac_policies) { + for (auto& rbac_policy : rbac_policies) { + authorization_engines_.emplace_back(std::move(rbac_policy)); + } + } + + // Returns the authorization engine for a rbac policy at a certain index. For + // a connection on the server, multiple RBAC policies might be active. The + // RBAC filter uses this method to get the RBAC policy configured for a + // instance at a particular instance. + const GrpcAuthorizationEngine* authorization_engine(int index) const { + if (static_cast<size_t>(index) >= authorization_engines_.size()) { + return nullptr; + } + return &authorization_engines_[index]; + } + + private: + std::vector<GrpcAuthorizationEngine> authorization_engines_; +}; + +class RbacServiceConfigParser : public ServiceConfigParser::Parser { + public: + // Parses the per-method service config for rbac filter. + std::unique_ptr<ServiceConfigParser::ParsedConfig> ParsePerMethodParams( + const grpc_channel_args* args, const Json& json, + grpc_error_handle* error) override; + // Returns the parser index for RbacServiceConfigParser. + static size_t ParserIndex(); + // Registers RbacServiceConfigParser to ServiceConfigParser. + static void Register(); +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_FILTERS_RBAC_RBAC_SERVICE_CONFIG_PARSER_H diff --git a/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector.h b/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector.h index afef9fed9c..070e8bafab 100644 --- a/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector.h +++ b/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector.h @@ -21,7 +21,8 @@ #include "y_absl/status/statusor.h" -#include "src/core/ext/service_config/service_config.h" +#include "src/core/lib/gprpp/dual_ref_counted.h" +#include "src/core/lib/service_config/service_config.h" #include "src/core/lib/transport/metadata_batch.h" namespace grpc_core { @@ -45,7 +46,7 @@ class ServerConfigSelector : public RefCounted<ServerConfigSelector> { // ServerConfigSelectorProvider allows for subscribers to watch for updates on // ServerConfigSelector. It is propagated via channel args. class ServerConfigSelectorProvider - : public RefCounted<ServerConfigSelectorProvider> { + : public DualRefCounted<ServerConfigSelectorProvider> { public: class ServerConfigSelectorWatcher { public: diff --git a/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc b/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc index 89dfc5890b..60c7f2d2a5 100644 --- a/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc +++ b/contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc @@ -21,7 +21,7 @@ #include "src/core/ext/filters/server_config_selector/server_config_selector_filter.h" #include "src/core/ext/filters/server_config_selector/server_config_selector.h" -#include "src/core/ext/service_config/service_config_call_data.h" +#include "src/core/lib/service_config/service_config_call_data.h" #include "src/core/lib/transport/error_utils.h" namespace grpc_core { @@ -36,7 +36,7 @@ class ChannelData { y_absl::StatusOr<RefCountedPtr<ServerConfigSelector>> config_selector() { MutexLock lock(&mu_); - return config_selector_; + return config_selector_.value(); } private: @@ -60,8 +60,8 @@ class ChannelData { RefCountedPtr<ServerConfigSelectorProvider> server_config_selector_provider_; Mutex mu_; - y_absl::StatusOr<RefCountedPtr<ServerConfigSelector>> config_selector_ - Y_ABSL_GUARDED_BY(mu_); + y_absl::optional<y_absl::StatusOr<RefCountedPtr<ServerConfigSelector>>> + config_selector_ Y_ABSL_GUARDED_BY(mu_); }; class CallData { @@ -103,7 +103,7 @@ class CallData { grpc_error_handle ChannelData::Init(grpc_channel_element* elem, grpc_channel_element_args* args) { - GPR_ASSERT(elem->filter = &kServerConfigSelectorFilter); + GPR_ASSERT(elem->filter == &kServerConfigSelectorFilter); RefCountedPtr<ServerConfigSelectorProvider> server_config_selector_provider = ServerConfigSelectorProvider::GetFromChannelArgs(*args->channel_args); if (server_config_selector_provider == nullptr) { @@ -127,8 +127,13 @@ ChannelData::ChannelData( GPR_ASSERT(server_config_selector_provider_ != nullptr); auto server_config_selector_watcher = y_absl::make_unique<ServerConfigSelectorWatcher>(this); - config_selector_ = server_config_selector_provider_->Watch( + auto config_selector = server_config_selector_provider_->Watch( std::move(server_config_selector_watcher)); + MutexLock lock(&mu_); + // It's possible for the watcher to have already updated config_selector_ + if (!config_selector_.has_value()) { + config_selector_ = std::move(config_selector); + } } ChannelData::~ChannelData() { server_config_selector_provider_->CancelWatch(); } diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc b/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc index 69cd4744cc..7f195cc593 100644 --- a/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc +++ b/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc @@ -50,6 +50,7 @@ #include "src/core/ext/transport/binder/wire_format/binder.h" #include "src/core/ext/transport/binder/wire_format/binder_android.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/transport.h" #include "src/cpp/client/create_channel_internal.h" @@ -122,6 +123,12 @@ bool InitializeBinderChannelJavaClass(void* jni_env_void) { static_cast<JNIEnv*>(jni_env_void)) != nullptr; } +bool InitializeBinderChannelJavaClass( + void* jni_env_void, std::function<void*(TString)> class_finder) { + return grpc_binder::FindNativeConnectionHelper( + static_cast<JNIEnv*>(jni_env_void), class_finder) != nullptr; +} + } // namespace experimental } // namespace grpc @@ -162,6 +169,16 @@ bool InitializeBinderChannelJavaClass(void* jni_env_void) { return {}; } +bool InitializeBinderChannelJavaClass( + void* jni_env_void, std::function<void*(TString)> class_finder) { + gpr_log(GPR_ERROR, + "This APK is compiled with Android API level = %d, which is not " + "supported. See port_platform.h for supported versions.", + __ANDROID_API__); + GPR_ASSERT(0); + return {}; +} + } // namespace experimental } // namespace grpc diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc b/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc index 63449dbcb5..4a6d609484 100644 --- a/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc +++ b/contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc @@ -25,6 +25,7 @@ #include "src/core/ext/transport/binder/transport/binder_transport.h" #include "src/core/ext/transport/binder/wire_format/binder.h" #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/config/core_configuration.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" @@ -53,6 +54,9 @@ grpc_channel* CreateDirectBinderChannelImplForTesting( grpc_arg default_authority_arg = grpc_channel_arg_string_create( const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), const_cast<char*>("binder.authority")); + args = grpc_core::CoreConfiguration::Get() + .channel_args_preconditioning() + .PreconditionChannelArgs(args); grpc_channel_args* final_args = grpc_channel_args_copy_and_add(args, &default_authority_arg, 1); grpc_error_handle error = GRPC_ERROR_NONE; @@ -61,6 +65,7 @@ grpc_channel* CreateDirectBinderChannelImplForTesting( GRPC_CLIENT_DIRECT_CHANNEL, transport, &error); // TODO(mingcl): Handle error properly GPR_ASSERT(error == GRPC_ERROR_NONE); + grpc_channel_args_destroy(args); grpc_channel_args_destroy(final_args); return channel; } @@ -70,6 +75,10 @@ grpc_channel* CreateClientBinderChannelImpl(const grpc_channel_args* args) { gpr_once_init(&g_factory_once, FactoryInit); + args = grpc_core::CoreConfiguration::Get() + .channel_args_preconditioning() + .PreconditionChannelArgs(args); + // Set channel factory argument grpc_arg channel_factory_arg = grpc_core::ClientChannelFactory::CreateChannelArg(g_factory); @@ -85,6 +94,8 @@ grpc_channel* CreateClientBinderChannelImpl(const grpc_channel_args* args) { // Clean up. grpc_channel_args_destroy(new_args); + grpc_channel_args_destroy(args); + if (channel == nullptr) { intptr_t integer; grpc_status_code status = GRPC_STATUS_INTERNAL; diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.cc b/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.cc index 16d6ae121f..afa2da01db 100644 --- a/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.cc +++ b/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.cc @@ -25,12 +25,20 @@ namespace grpc_binder { jclass FindNativeConnectionHelper(JNIEnv* env) { - auto do_find = [env]() { - jclass cl = env->FindClass("io/grpc/binder/cpp/NativeConnectionHelper"); + return FindNativeConnectionHelper( + env, [env](TString cl) { return env->FindClass(cl.c_str()); }); +} + +jclass FindNativeConnectionHelper( + JNIEnv* env, std::function<void*(TString)> class_finder) { + auto do_find = [env, class_finder]() { + jclass cl = static_cast<jclass>( + class_finder("io/grpc/binder/cpp/NativeConnectionHelper")); if (cl == nullptr) { return cl; } jclass global_cl = static_cast<jclass>(env->NewGlobalRef(cl)); + env->DeleteLocalRef(cl); GPR_ASSERT(global_cl != nullptr); return global_cl; }; diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.h b/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.h index e8bab42b04..f5414be613 100644 --- a/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.h +++ b/contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.h @@ -21,6 +21,9 @@ #error #include <jni.h> +#include <functional> +#include <util/generic/string.h> + #include "y_absl/strings/string_view.h" namespace grpc_binder { @@ -31,6 +34,9 @@ namespace grpc_binder { // JNI_OnLoad) so subsequent BinderTransport code can find Java class jclass FindNativeConnectionHelper(JNIEnv* env); +jclass FindNativeConnectionHelper( + JNIEnv* env, std::function<void*(TString)> class_finder); + // Calls Java method NativeConnectionHelper.tryEstablishConnection void TryEstablishConnection(JNIEnv* env, jobject application, y_absl::string_view pkg, y_absl::string_view cls, diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/server/binder_server.cc b/contrib/libs/grpc/src/core/ext/transport/binder/server/binder_server.cc index 9d42d844cf..45ba081903 100644 --- a/contrib/libs/grpc/src/core/ext/transport/binder/server/binder_server.cc +++ b/contrib/libs/grpc/src/core/ext/transport/binder/server/binder_server.cc @@ -196,7 +196,9 @@ class BinderServerListener : public Server::ListenerInterface { return status; } gpr_log(GPR_INFO, "BinderTransport client protocol version = %d", version); - // TODO(waynetu): Check supported version. + // TODO(mingcl): Make sure we only give client a version that is not newer + // than the version they specify. For now, we always tell client that we + // only support version=1. std::unique_ptr<grpc_binder::Binder> client_binder{}; status = parcel->ReadBinder(&client_binder); if (!status.ok()) { diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc b/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc index 465fc9b0bd..1f4ca9a697 100644 --- a/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc +++ b/contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc @@ -40,8 +40,6 @@ #include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/error_utils.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/transport/transport.h" #ifndef NDEBUG @@ -124,7 +122,12 @@ static void AssignMetadata(grpc_metadata_batch* mb, const grpc_binder::Metadata& md) { mb->Clear(); for (auto& p : md) { - mb->Append(p.first, grpc_core::Slice::FromCopiedString(p.second)); + mb->Append(p.first, grpc_core::Slice::FromCopiedString(p.second), + [&](y_absl::string_view error, const grpc_core::Slice&) { + gpr_log( + GPR_DEBUG, "Failed to parse metadata: %s", + y_absl::StrCat("key=", p.first, " error=", error).c_str()); + }); } } @@ -168,10 +171,10 @@ static bool ContainsAuthorityAndPath(const grpc_binder::Metadata& metadata) { bool has_authority = false; bool has_path = false; for (const auto& kv : metadata) { - if (kv.first == grpc_core::StringViewFromSlice(GRPC_MDSTR_AUTHORITY)) { + if (kv.first == ":authority") { has_authority = true; } - if (kv.first == grpc_core::StringViewFromSlice(GRPC_MDSTR_PATH)) { + if (kv.first == ":path") { has_path = true; } } @@ -289,14 +292,9 @@ static void recv_trailing_metadata_locked(void* arg, // TODO(b/192208695): See if we can avoid to manually put status // code into the header gpr_log(GPR_INFO, "status = %d", args->status); - grpc_linked_mdelem* glm = static_cast<grpc_linked_mdelem*>( - gbs->arena->Alloc(sizeof(grpc_linked_mdelem))); - glm->md = grpc_get_reffed_status_elem(args->status); - GPR_ASSERT(gbs->recv_trailing_metadata->LinkTail(glm) == - GRPC_ERROR_NONE); - gpr_log(GPR_INFO, "trailing_metadata = %p", - gbs->recv_trailing_metadata); - gpr_log(GPR_INFO, "glm = %p", glm); + gbs->recv_trailing_metadata->Set( + grpc_core::GrpcStatusMetadata(), + static_cast<grpc_status_code>(args->status)); } return GRPC_ERROR_NONE; }(); @@ -327,27 +325,27 @@ class MetadataEncoder { MetadataEncoder(bool is_client, Transaction* tx, Metadata* init_md) : is_client_(is_client), tx_(tx), init_md_(init_md) {} - void Encode(grpc_mdelem md) { - y_absl::string_view key = grpc_core::StringViewFromSlice(GRPC_MDKEY(md)); - y_absl::string_view value = grpc_core::StringViewFromSlice(GRPC_MDVALUE(md)); - gpr_log(GPR_INFO, "send metadata key-value %s", - y_absl::StrCat(key, " ", value).c_str()); - if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_PATH)) { - // TODO(b/192208403): Figure out if it is correct to simply drop '/' - // prefix and treat it as rpc method name - GPR_ASSERT(value[0] == '/'); - TString path = TString(value).substr(1); - - // Only client send method ref. - GPR_ASSERT(is_client_); - tx_->SetMethodRef(path); - } else if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_STATUS)) { - int status = grpc_get_status_code_from_metadata(md); - gpr_log(GPR_INFO, "send trailing metadata status = %d", status); - tx_->SetStatus(status); - } else { - init_md_->emplace_back(TString(key), TString(value)); - } + void Encode(const grpc_core::Slice& key_slice, + const grpc_core::Slice& value_slice) { + y_absl::string_view key = key_slice.as_string_view(); + y_absl::string_view value = value_slice.as_string_view(); + init_md_->emplace_back(TString(key), TString(value)); + } + + void Encode(grpc_core::HttpPathMetadata, const grpc_core::Slice& value) { + // TODO(b/192208403): Figure out if it is correct to simply drop '/' + // prefix and treat it as rpc method name + GPR_ASSERT(value[0] == '/'); + TString path = TString(value.as_string_view().substr(1)); + + // Only client send method ref. + GPR_ASSERT(is_client_); + tx_->SetMethodRef(path); + } + + void Encode(grpc_core::GrpcStatusMetadata, grpc_status_code status) { + gpr_log(GPR_INFO, "send trailing metadata status = %d", status); + tx_->SetStatus(status); } template <typename Trait> @@ -455,7 +453,6 @@ static void perform_stream_op_locked(void* stream_op, message_data += TString(reinterpret_cast<char*>(p), len); grpc_slice_unref_internal(message_slice); } - gpr_log(GPR_INFO, "message_data = %s", message_data.c_str()); tx.SetData(message_data); // TODO(b/192369787): Are we supposed to reset here to avoid // use-after-free issue in call.cc? diff --git a/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc b/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc index 7a0ddfac96..cdc362e202 100644 --- a/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc +++ b/contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc @@ -44,6 +44,8 @@ namespace grpc_binder { namespace { +const int32_t kWireFormatVersion = 1; + y_absl::StatusOr<Metadata> parse_metadata(ReadableParcel* reader) { int num_header; RETURN_IF_ERROR(reader->ReadInt32(&num_header)); @@ -116,9 +118,8 @@ void WireReaderImpl::SendSetupTransport(Binder* binder) { gpr_log(GPR_INFO, "prepare transaction = %d", binder->PrepareTransaction().ok()); WritableParcel* writable_parcel = binder->GetWritableParcel(); - int32_t version = 77; gpr_log(GPR_INFO, "write int32 = %d", - writable_parcel->WriteInt32(version).ok()); + writable_parcel->WriteInt32(kWireFormatVersion).ok()); // The lifetime of the transaction receiver is the same as the wire writer's. // The transaction receiver is responsible for not calling the on-transact // callback when it's dead. @@ -196,7 +197,15 @@ y_absl::Status WireReaderImpl::ProcessTransaction(transaction_code_t code, int version; RETURN_IF_ERROR(parcel->ReadInt32(&version)); - gpr_log(GPR_INFO, "version = %d", version); + gpr_log(GPR_INFO, "The other end respond with version = %d", version); + // We only support this single lowest possible version, so server must + // respond that version too. + if (version != kWireFormatVersion) { + gpr_log(GPR_ERROR, + "The other end respond with version = %d, but we requested " + "version %d, trying to continue anyway", + version, kWireFormatVersion); + } std::unique_ptr<Binder> binder{}; RETURN_IF_ERROR(parcel->ReadBinder(&binder)); if (!binder) { diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create.cc index 66129d92b3..575a2b12bb 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create.cc @@ -23,9 +23,9 @@ #include <grpc/support/string_util.h> #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/channel/channel_args.h" +#include "src/core/lib/resolver/resolver_registry.h" #include "src/core/lib/resource_quota/api.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/channel.h" diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc index c5fb03b82b..9f42561669 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc @@ -23,11 +23,11 @@ #include <grpc/support/string_util.h> #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/resolver/resolver_registry.h" #include "src/core/lib/resource_quota/api.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/security_connector/security_connector.h" diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc index 893d683bbe..1f48b6eb9a 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc @@ -55,6 +55,7 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" +#include "src/core/lib/transport/error_utils.h" #include "src/core/lib/uri/uri_parser.h" namespace grpc_core { @@ -160,6 +161,7 @@ class Chttp2ServerListener : public Server::ListenerInterface { private: static void OnClose(void* arg, grpc_error_handle error); + static void OnDrainGraceTimeExpiry(void* arg, grpc_error_handle error); RefCountedPtr<Chttp2ServerListener> listener_; Mutex mu_ Y_ABSL_ACQUIRED_AFTER(&listener_->mu_); @@ -170,6 +172,10 @@ class Chttp2ServerListener : public Server::ListenerInterface { // created. grpc_chttp2_transport* transport_ Y_ABSL_GUARDED_BY(&mu_) = nullptr; grpc_closure on_close_; + grpc_timer drain_grace_timer_; + grpc_closure on_drain_grace_time_expiry_; + bool drain_grace_timer_expiry_callback_pending_ Y_ABSL_GUARDED_BY(&mu_) = + false; bool shutdown_ Y_ABSL_GUARDED_BY(&mu_) = false; }; @@ -221,10 +227,9 @@ class Chttp2ServerListener : public Server::ListenerInterface { Chttp2ServerArgsModifier const args_modifier_; ConfigFetcherWatcher* config_fetcher_watcher_ = nullptr; grpc_channel_args* args_; - Mutex connection_manager_mu_; - RefCountedPtr<grpc_server_config_fetcher::ConnectionManager> - connection_manager_ Y_ABSL_GUARDED_BY(connection_manager_mu_); Mutex mu_; + RefCountedPtr<grpc_server_config_fetcher::ConnectionManager> + connection_manager_ Y_ABSL_GUARDED_BY(mu_); // Signals whether grpc_tcp_server_start() has been called. bool started_ Y_ABSL_GUARDED_BY(mu_) = false; // Signals whether grpc_tcp_server_start() has completed. @@ -250,13 +255,31 @@ void Chttp2ServerListener::ConfigFetcherWatcher::UpdateConnectionManager( connection_manager) { RefCountedPtr<grpc_server_config_fetcher::ConnectionManager> connection_manager_to_destroy; + class GracefulShutdownExistingConnections { + public: + ~GracefulShutdownExistingConnections() { + // Send GOAWAYs on the transports so that they get disconnected when + // existing RPCs finish, and so that no new RPC is started on them. + for (auto& connection : connections_) { + connection.first->SendGoAway(); + } + } + + void set_connections( + std::map<ActiveConnection*, OrphanablePtr<ActiveConnection>> + connections) { + GPR_ASSERT(connections_.empty()); + connections_ = std::move(connections); + } + + private: + std::map<ActiveConnection*, OrphanablePtr<ActiveConnection>> connections_; + } connections_to_shutdown; { - MutexLock lock(&listener_->connection_manager_mu_); + MutexLock lock(&listener_->mu_); connection_manager_to_destroy = listener_->connection_manager_; listener_->connection_manager_ = std::move(connection_manager); - } - { - MutexLock lock(&listener_->mu_); + connections_to_shutdown.set_connections(std::move(listener_->connections_)); if (listener_->shutdown_) { return; } @@ -525,7 +548,21 @@ void Chttp2ServerListener::ActiveConnection::SendGoAway() { grpc_chttp2_transport* transport = nullptr; { MutexLock lock(&mu_); - transport = transport_; + if (transport_ != nullptr && !shutdown_) { + transport = transport_; + Ref().release(); // Ref held by OnDrainGraceTimeExpiry + GRPC_CLOSURE_INIT(&on_drain_grace_time_expiry_, OnDrainGraceTimeExpiry, + this, nullptr); + grpc_timer_init(&drain_grace_timer_, + ExecCtx::Get()->Now() + + grpc_channel_args_find_integer( + listener_->args_, + GRPC_ARG_SERVER_CONFIG_CHANGE_DRAIN_GRACE_TIME_MS, + {10 * 60 * GPR_MS_PER_SEC, 0, INT_MAX}), + &on_drain_grace_time_expiry_); + drain_grace_timer_expiry_callback_pending_ = true; + shutdown_ = true; + } } if (transport != nullptr) { grpc_transport_op* op = grpc_make_transport_op(nullptr); @@ -565,11 +602,35 @@ void Chttp2ServerListener::ActiveConnection::OnClose( connection = std::move(it->second); self->listener_->connections_.erase(it); } + self->shutdown_ = true; + } + // Cancel the drain_grace_timer_ if needed. + if (self->drain_grace_timer_expiry_callback_pending_) { + grpc_timer_cancel(&self->drain_grace_timer_); } } self->Unref(); } +void Chttp2ServerListener::ActiveConnection::OnDrainGraceTimeExpiry( + void* arg, grpc_error_handle error) { + ActiveConnection* self = static_cast<ActiveConnection*>(arg); + // If the drain_grace_timer_ was not cancelled, disconnect the transport + // immediately. + if (error == GRPC_ERROR_NONE) { + grpc_chttp2_transport* transport = nullptr; + { + MutexLock lock(&self->mu_); + transport = self->transport_; + } + grpc_transport_op* op = grpc_make_transport_op(nullptr); + op->disconnect_with_error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Drain grace time expired. Closing connection immediately."); + grpc_transport_perform_op(&transport->base, op); + } + self->Unref(); +} + // // Chttp2ServerListener // @@ -700,7 +761,7 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp, RefCountedPtr<grpc_server_config_fetcher::ConnectionManager> connection_manager; { - MutexLock lock(&self->connection_manager_mu_); + MutexLock lock(&self->mu_); connection_manager = self->connection_manager_; } auto endpoint_cleanup = [&](grpc_error_handle error) { @@ -751,8 +812,10 @@ void Chttp2ServerListener::OnAccept(void* arg, grpc_endpoint* tcp, RefCountedPtr<Chttp2ServerListener> listener_ref; { MutexLock lock(&self->mu_); - // Shutdown the the connection if listener's stopped serving. - if (!self->shutdown_ && self->is_serving_) { + // Shutdown the the connection if listener's stopped serving or if the + // connection manager has changed. + if (!self->shutdown_ && self->is_serving_ && + connection_manager == self->connection_manager_) { // 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 @@ -825,7 +888,7 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr, args_modifier); } *port_num = -1; - grpc_resolved_addresses* resolved = nullptr; + y_absl::StatusOr<std::vector<grpc_resolved_address>> resolved_or; std::vector<grpc_error_handle> error_list; TString parsed_addr = URI::PercentDecode(addr); y_absl::string_view parsed_addr_unprefixed{parsed_addr}; @@ -833,26 +896,26 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr, grpc_error_handle error = [&]() { grpc_error_handle error = GRPC_ERROR_NONE; if (y_absl::ConsumePrefix(&parsed_addr_unprefixed, kUnixUriPrefix)) { - error = - grpc_resolve_unix_domain_address(parsed_addr_unprefixed, &resolved); + resolved_or = grpc_resolve_unix_domain_address(parsed_addr_unprefixed); } else if (y_absl::ConsumePrefix(&parsed_addr_unprefixed, kUnixAbstractUriPrefix)) { - error = grpc_resolve_unix_abstract_domain_address(parsed_addr_unprefixed, - &resolved); + resolved_or = + grpc_resolve_unix_abstract_domain_address(parsed_addr_unprefixed); } else { - error = grpc_blocking_resolve_address(parsed_addr.c_str(), "https", - &resolved); + resolved_or = GetDNSResolver()->ResolveNameBlocking(parsed_addr, "https"); + } + if (!resolved_or.ok()) { + return absl_status_to_grpc_error(resolved_or.status()); } - if (error != GRPC_ERROR_NONE) return error; // Create a listener for each resolved address. - for (size_t i = 0; i < resolved->naddrs; i++) { + for (auto& addr : *resolved_or) { // If address has a wildcard port (0), use the same port as a previous // listener. - if (*port_num != -1 && grpc_sockaddr_get_port(&resolved->addrs[i]) == 0) { - grpc_sockaddr_set_port(&resolved->addrs[i], *port_num); + if (*port_num != -1 && grpc_sockaddr_get_port(&addr) == 0) { + grpc_sockaddr_set_port(&addr, *port_num); } int port_temp = -1; - error = Chttp2ServerListener::Create(server, &resolved->addrs[i], + error = Chttp2ServerListener::Create(server, &addr, grpc_channel_args_copy(args), args_modifier, &port_temp); if (error != GRPC_ERROR_NONE) { @@ -865,17 +928,17 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr, } } } - if (error_list.size() == resolved->naddrs) { + if (error_list.size() == resolved_or->size()) { TString msg = y_absl::StrFormat("No address added out of total %" PRIuPTR " resolved", - resolved->naddrs); + resolved_or->size()); return GRPC_ERROR_CREATE_REFERENCING_FROM_COPIED_STRING( msg.c_str(), error_list.data(), error_list.size()); } else if (!error_list.empty()) { TString msg = y_absl::StrFormat( "Only %" PRIuPTR " addresses added out of total %" PRIuPTR " resolved", - resolved->naddrs - error_list.size(), resolved->naddrs); + resolved_or->size() - error_list.size(), resolved_or->size()); 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_std_string(error).c_str()); @@ -888,9 +951,6 @@ grpc_error_handle Chttp2ServerAddPort(Server* server, const char* addr, GRPC_ERROR_UNREF(error); } grpc_channel_args_destroy(args); - if (resolved != nullptr) { - grpc_resolved_addresses_destroy(resolved); - } if (error != GRPC_ERROR_NONE) *port_num = 0; return error; } diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc index ac13d73d3b..eacf695e13 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc @@ -21,7 +21,6 @@ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gprpp/global_config.h" -#include "src/core/lib/transport/metadata.h" GPR_GLOBAL_CONFIG_DEFINE_BOOL( grpc_experimental_disable_flow_control, false, diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index 19ff7482cc..1a4af28b6a 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -27,6 +27,7 @@ #include "y_absl/strings/str_format.h" #include <grpc/slice_buffer.h> +#include <grpc/status.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> @@ -36,7 +37,6 @@ #include "src/core/ext/transport/chttp2/transport/internal.h" #include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/compression/stream_compression.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" @@ -52,7 +52,6 @@ #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/transport/error_utils.h" #include "src/core/lib/transport/http2_errors.h" -#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/timeout_encoding.h" #include "src/core/lib/transport/transport.h" @@ -649,10 +648,6 @@ grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t, : t(t), refcount(refcount), reffer(this), - stream_reservation(t->memory_owner.MakeReservation( - grpc_core::kResourceQuotaCallSize)), // TODO(ctiller): sizeof(*this), - // or better, move allocation to - // memory quota. initial_metadata_buffer(arena), trailing_metadata_buffer(arena) { if (server_data) { @@ -692,13 +687,6 @@ grpc_chttp2_stream::~grpc_chttp2_stream() { grpc_slice_buffer_destroy_internal(&unprocessed_incoming_frames_buffer); grpc_slice_buffer_destroy_internal(&frame_storage); - if (stream_compression_method != GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS) { - grpc_slice_buffer_destroy_internal(&compressed_data_buffer); - } - if (stream_decompression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS) { - grpc_slice_buffer_destroy_internal(&decompressed_data_buffer); - } for (int i = 0; i < STREAM_LIST_COUNT; i++) { if (GPR_UNLIKELY(included[i])) { @@ -743,18 +731,6 @@ static void destroy_stream(grpc_transport* gt, grpc_stream* gs, GPR_TIMER_SCOPE("destroy_stream", 0); grpc_chttp2_transport* t = reinterpret_cast<grpc_chttp2_transport*>(gt); grpc_chttp2_stream* s = reinterpret_cast<grpc_chttp2_stream*>(gs); - if (s->stream_compression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS && - s->stream_compression_ctx != nullptr) { - grpc_stream_compression_context_destroy(s->stream_compression_ctx); - s->stream_compression_ctx = nullptr; - } - if (s->stream_decompression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS && - s->stream_decompression_ctx != nullptr) { - grpc_stream_compression_context_destroy(s->stream_decompression_ctx); - s->stream_decompression_ctx = nullptr; - } s->destroy_stream_arg = then_schedule_closure; t->combiner->Run( @@ -1219,37 +1195,49 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t, write_state_name(t->write_state)); } if (error != GRPC_ERROR_NONE) { - if (closure->error_data.error == GRPC_ERROR_NONE) { - closure->error_data.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + grpc_error_handle cl_err = + grpc_core::internal::StatusMoveFromHeapPtr(closure->error_data.error); +#else + grpc_error_handle cl_err = + reinterpret_cast<grpc_error_handle>(closure->error_data.error); +#endif + if (cl_err == GRPC_ERROR_NONE) { + cl_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Error in HTTP transport completing operation"); - closure->error_data.error = - grpc_error_set_str(closure->error_data.error, - GRPC_ERROR_STR_TARGET_ADDRESS, t->peer_string); + cl_err = grpc_error_set_str(cl_err, GRPC_ERROR_STR_TARGET_ADDRESS, + t->peer_string); } - closure->error_data.error = - grpc_error_add_child(closure->error_data.error, error); + cl_err = grpc_error_add_child(cl_err, error); +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + closure->error_data.error = grpc_core::internal::StatusAllocHeapPtr(cl_err); +#else + closure->error_data.error = reinterpret_cast<intptr_t>(cl_err); +#endif } if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) { if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) || !(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) { // Using GRPC_CLOSURE_SCHED instead of GRPC_CLOSURE_RUN to avoid running // closures earlier than when it is safe to do so. - grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, - closure->error_data.error); +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + grpc_error_handle run_error = + grpc_core::internal::StatusMoveFromHeapPtr(closure->error_data.error); +#else + grpc_error_handle run_error = + reinterpret_cast<grpc_error_handle>(closure->error_data.error); +#endif + closure->error_data.error = 0; + grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure, run_error); } else { - grpc_closure_list_append(&t->run_after_write, closure, - closure->error_data.error); + grpc_closure_list_append(&t->run_after_write, closure); } } } static bool contains_non_ok_status(grpc_metadata_batch* batch) { - if (batch->legacy_index()->named.grpc_status != nullptr) { - return !grpc_mdelem_static_value_eq( - batch->legacy_index()->named.grpc_status->md, - GRPC_MDELEM_GRPC_STATUS_0); - } - return false; + return batch->get(grpc_core::GrpcStatusMetadata()).value_or(GRPC_STATUS_OK) != + GRPC_STATUS_OK; } static void maybe_become_writable_due_to_send_msg(grpc_chttp2_transport* t, @@ -1342,13 +1330,10 @@ static void complete_fetch_locked(void* gs, grpc_error_handle error) { static void log_metadata(const grpc_metadata_batch* md_batch, uint32_t id, bool is_client, bool is_initial) { - md_batch->ForEach([=](grpc_mdelem md) { - char* key = grpc_slice_to_c_string(GRPC_MDKEY(md)); - char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md)); - gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL", - is_client ? "CLI" : "SVR", key, value); - gpr_free(key); - gpr_free(value); + const TString prefix = y_absl::StrCat( + "HTTP:", id, is_initial ? ":HDR" : ":TRL", is_client ? ":CLI:" : ":SVR:"); + md_batch->Log([&prefix](y_absl::string_view key, y_absl::string_view value) { + gpr_log(GPR_INFO, "%s", y_absl::StrCat(prefix, key, ": ", value).c_str()); }); } @@ -1386,7 +1371,7 @@ static void perform_stream_op_locked(void* stream_op, // This batch has send ops. Use final_data as a barrier until enqueue time; // the initial counter is dropped at the end of this function. on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT; - on_complete->error_data.error = GRPC_ERROR_NONE; + on_complete->error_data.error = 0; } if (op->cancel_stream) { @@ -1402,23 +1387,6 @@ static void perform_stream_op_locked(void* stream_op, GPR_ASSERT(s->send_initial_metadata_finished == nullptr); on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE; - // Identify stream compression - if (op_payload->send_initial_metadata.send_initial_metadata->legacy_index() - ->named.content_encoding == nullptr || - grpc_stream_compression_method_parse( - GRPC_MDVALUE( - op_payload->send_initial_metadata.send_initial_metadata - ->legacy_index() - ->named.content_encoding->md), - true, &s->stream_compression_method) == 0) { - s->stream_compression_method = GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS; - } - if (s->stream_compression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS) { - s->uncompressed_data_size = 0; - s->stream_compression_ctx = nullptr; - grpc_slice_buffer_init(&s->compressed_data_buffer); - } s->send_initial_metadata_finished = add_closure_barrier(on_complete); s->send_initial_metadata = op_payload->send_initial_metadata.send_initial_metadata; @@ -1874,48 +1842,10 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_chttp2_transport* /*t*/, if (s->unprocessed_incoming_frames_buffer.length == 0) { grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer, &s->frame_storage); - s->unprocessed_incoming_frames_decompressed = false; - } - if (!s->unprocessed_incoming_frames_decompressed && - s->stream_decompression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS) { - GPR_ASSERT(s->decompressed_data_buffer.length == 0); - bool end_of_context; - if (!s->stream_decompression_ctx) { - s->stream_decompression_ctx = - grpc_stream_compression_context_create( - s->stream_decompression_method); - } - if (!grpc_stream_decompress( - s->stream_decompression_ctx, - &s->unprocessed_incoming_frames_buffer, - &s->decompressed_data_buffer, nullptr, - GRPC_HEADER_SIZE_IN_BYTES - s->decompressed_header_bytes, - &end_of_context)) { - grpc_slice_buffer_reset_and_unref_internal(&s->frame_storage); - grpc_slice_buffer_reset_and_unref_internal( - &s->unprocessed_incoming_frames_buffer); - error = GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Stream decompression error."); - } else { - s->decompressed_header_bytes += s->decompressed_data_buffer.length; - if (s->decompressed_header_bytes == GRPC_HEADER_SIZE_IN_BYTES) { - s->decompressed_header_bytes = 0; - } - error = grpc_deframe_unprocessed_incoming_frames( - &s->data_parser, s, &s->decompressed_data_buffer, nullptr, - s->recv_message); - if (end_of_context) { - grpc_stream_compression_context_destroy( - s->stream_decompression_ctx); - s->stream_decompression_ctx = nullptr; - } - } - } else { - error = grpc_deframe_unprocessed_incoming_frames( - &s->data_parser, s, &s->unprocessed_incoming_frames_buffer, - nullptr, s->recv_message); } + error = grpc_deframe_unprocessed_incoming_frames( + &s->data_parser, s, &s->unprocessed_incoming_frames_buffer, nullptr, + s->recv_message); if (error != GRPC_ERROR_NONE) { s->seen_error = true; grpc_slice_buffer_reset_and_unref_internal(&s->frame_storage); @@ -1963,42 +1893,12 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t, !s->seen_error && s->recv_trailing_metadata_finished != nullptr) { // Maybe some SYNC_FLUSH data is left in frame_storage. Consume them and // maybe decompress the next 5 bytes in the stream. - if (s->stream_decompression_method == - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS) { - grpc_slice_buffer_move_first( - &s->frame_storage, - std::min(s->frame_storage.length, - size_t(GRPC_HEADER_SIZE_IN_BYTES)), - &s->unprocessed_incoming_frames_buffer); - if (s->unprocessed_incoming_frames_buffer.length > 0) { - s->unprocessed_incoming_frames_decompressed = true; - pending_data = true; - } - } else { - bool end_of_context; - if (!s->stream_decompression_ctx) { - s->stream_decompression_ctx = grpc_stream_compression_context_create( - s->stream_decompression_method); - } - if (!grpc_stream_decompress( - s->stream_decompression_ctx, &s->frame_storage, - &s->unprocessed_incoming_frames_buffer, nullptr, - GRPC_HEADER_SIZE_IN_BYTES, &end_of_context)) { - grpc_slice_buffer_reset_and_unref_internal(&s->frame_storage); - grpc_slice_buffer_reset_and_unref_internal( - &s->unprocessed_incoming_frames_buffer); - s->seen_error = true; - } else { - if (s->unprocessed_incoming_frames_buffer.length > 0) { - s->unprocessed_incoming_frames_decompressed = true; - pending_data = true; - } - if (end_of_context) { - grpc_stream_compression_context_destroy( - s->stream_decompression_ctx); - s->stream_decompression_ctx = nullptr; - } - } + grpc_slice_buffer_move_first( + &s->frame_storage, + std::min(s->frame_storage.length, size_t(GRPC_HEADER_SIZE_IN_BYTES)), + &s->unprocessed_incoming_frames_buffer); + if (s->unprocessed_incoming_frames_buffer.length > 0) { + pending_data = true; } } if (s->read_closed && s->frame_storage.length == 0 && !pending_data && @@ -2095,12 +1995,7 @@ void grpc_chttp2_fake_status(grpc_chttp2_transport* t, grpc_chttp2_stream* s, // about the metadata yet if (s->published_metadata[1] == GRPC_METADATA_NOT_PUBLISHED || s->recv_trailing_metadata_finished != nullptr) { - char status_string[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa(status, status_string); - GRPC_LOG_IF_ERROR("add_status", - s->trailing_metadata_buffer.ReplaceOrAppend( - GRPC_MDSTR_GRPC_STATUS, - grpc_core::UnmanagedMemorySlice(status_string))); + s->trailing_metadata_buffer.Set(grpc_core::GrpcStatusMetadata(), status); if (!message.empty()) { s->trailing_metadata_buffer.Set( grpc_core::GrpcMessageMetadata(), @@ -2989,7 +2884,6 @@ void Chttp2IncomingByteStream::NextLocked(void* arg, if (s->frame_storage.length > 0) { grpc_slice_buffer_swap(&s->frame_storage, &s->unprocessed_incoming_frames_buffer); - s->unprocessed_incoming_frames_decompressed = false; ExecCtx::Run(DEBUG_LOCATION, bs->next_action_.on_complete, GRPC_ERROR_NONE); } else if (s->byte_stream_error != GRPC_ERROR_NONE) { ExecCtx::Run(DEBUG_LOCATION, bs->next_action_.on_complete, @@ -3035,45 +2929,10 @@ bool Chttp2IncomingByteStream::Next(size_t max_size_hint, } } -void Chttp2IncomingByteStream::MaybeCreateStreamDecompressionCtx() { - GPR_DEBUG_ASSERT(stream_->stream_decompression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS); - if (!stream_->stream_decompression_ctx) { - stream_->stream_decompression_ctx = grpc_stream_compression_context_create( - stream_->stream_decompression_method); - } -} - grpc_error_handle Chttp2IncomingByteStream::Pull(grpc_slice* slice) { GPR_TIMER_SCOPE("incoming_byte_stream_pull", 0); grpc_error_handle error; if (stream_->unprocessed_incoming_frames_buffer.length > 0) { - if (!stream_->unprocessed_incoming_frames_decompressed && - stream_->stream_decompression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS) { - bool end_of_context; - MaybeCreateStreamDecompressionCtx(); - if (!grpc_stream_decompress(stream_->stream_decompression_ctx, - &stream_->unprocessed_incoming_frames_buffer, - &stream_->decompressed_data_buffer, nullptr, - MAX_SIZE_T, &end_of_context)) { - error = - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error."); - return error; - } - GPR_ASSERT(stream_->unprocessed_incoming_frames_buffer.length == 0); - grpc_slice_buffer_swap(&stream_->unprocessed_incoming_frames_buffer, - &stream_->decompressed_data_buffer); - stream_->unprocessed_incoming_frames_decompressed = true; - if (end_of_context) { - grpc_stream_compression_context_destroy( - stream_->stream_decompression_ctx); - stream_->stream_decompression_ctx = nullptr; - } - if (stream_->unprocessed_incoming_frames_buffer.length == 0) { - *slice = grpc_empty_slice(); - } - } error = grpc_deframe_unprocessed_incoming_frames( &stream_->data_parser, stream_, &stream_->unprocessed_incoming_frames_buffer, slice, nullptr); diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_data.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_data.cc index 4b35a04e0a..0a2197505a 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_data.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_data.cc @@ -290,7 +290,6 @@ grpc_error_handle grpc_chttp2_data_parser_parse(void* /*parser*/, grpc_slice_buffer_add(&s->unprocessed_incoming_frames_buffer, slice); grpc_core::ExecCtx::Run(DEBUG_LOCATION, s->on_next, GRPC_ERROR_NONE); s->on_next = nullptr; - s->unprocessed_incoming_frames_decompressed = false; } else { grpc_slice_ref_internal(slice); grpc_slice_buffer_add(&s->frame_storage, slice); diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.cc index 47f6743e8f..b7a42ef185 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.cc @@ -23,30 +23,31 @@ #include <assert.h> #include <string.h> +#include <cstdint> + +#include "src/core/ext/transport/chttp2/transport/hpack_constants.h" +#include "src/core/ext/transport/chttp2/transport/hpack_encoder_table.h" + /* This is here for grpc_is_binary_header * TODO(murgatroid99): Remove this */ #include <grpc/grpc.h> +#include <grpc/slice.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include "src/core/ext/transport/chttp2/transport/bin_encoder.h" -#include "src/core/ext/transport/chttp2/transport/hpack_utils.h" #include "src/core/ext/transport/chttp2/transport/varint.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/validate_metadata.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/timeout_encoding.h" namespace grpc_core { namespace { -/* don't consider adding anything bigger than this to the hpack table */ -constexpr size_t kMaxDecoderSpaceUsage = 512; constexpr size_t kDataFrameHeaderSize = 9; } /* namespace */ @@ -134,19 +135,23 @@ void HPackCompressor::Framer::EnsureSpace(size_t need_bytes) { prefix_ = BeginFrame(); } -void HPackCompressor::Framer::Add(grpc_slice slice) { - const size_t len = GRPC_SLICE_LENGTH(slice); - if (len == 0) return; - const size_t remaining = max_frame_size_ - CurrentFrameSize(); - if (len <= remaining) { - stats_->header_bytes += len; - grpc_slice_buffer_add(output_, slice); - } else { - stats_->header_bytes += remaining; - grpc_slice_buffer_add(output_, grpc_slice_split_head(&slice, remaining)); - FinishFrame(false); - prefix_ = BeginFrame(); - Add(slice); +void HPackCompressor::Framer::Add(Slice slice) { + while (true) { + const size_t len = slice.length(); + if (len == 0) return; + const size_t remaining = max_frame_size_ - CurrentFrameSize(); + if (len <= remaining) { + stats_->header_bytes += len; + grpc_slice_buffer_add(output_, slice.TakeCSlice()); + return; + } else { + stats_->header_bytes += remaining; + Slice tail = slice.Split(remaining); + grpc_slice_buffer_add(output_, slice.TakeCSlice()); + slice = std::move(tail); + FinishFrame(false); + prefix_ = BeginFrame(); + } } } @@ -156,37 +161,6 @@ uint8_t* HPackCompressor::Framer::AddTiny(size_t len) { return grpc_slice_buffer_tiny_add(output_, len); } -// Add a key to the dynamic table. Both key and value will be added to table at -// the decoder. -void HPackCompressor::AddKeyWithIndex(grpc_slice_refcount* key_ref, - uint32_t new_index, uint32_t key_hash) { - key_index_.Insert(KeySliceRef(key_ref, key_hash), new_index); -} - -/* add an element to the decoder table */ -void HPackCompressor::AddElemWithIndex(grpc_mdelem elem, uint32_t new_index, - uint32_t elem_hash, uint32_t key_hash) { - GPR_DEBUG_ASSERT(GRPC_MDELEM_IS_INTERNED(elem)); - elem_index_.Insert(KeyElem(elem, elem_hash), new_index); - AddKeyWithIndex(GRPC_MDKEY(elem).refcount, new_index, key_hash); -} - -void HPackCompressor::AddElem(grpc_mdelem elem, size_t elem_size, - uint32_t elem_hash, uint32_t key_hash) { - uint32_t new_index = table_.AllocateIndex(elem_size); - if (new_index != 0) { - AddElemWithIndex(elem, new_index, elem_hash, key_hash); - } -} - -void HPackCompressor::AddKey(grpc_mdelem elem, size_t elem_size, - uint32_t key_hash) { - uint32_t new_index = table_.AllocateIndex(elem_size); - if (new_index != 0) { - AddKeyWithIndex(GRPC_MDKEY(elem).refcount, new_index, key_hash); - } -} - void HPackCompressor::Framer::EmitIndexed(uint32_t elem_index) { GRPC_STATS_INC_HPACK_SEND_INDEXED(); VarintWriter<1> w(elem_index); @@ -195,35 +169,33 @@ void HPackCompressor::Framer::EmitIndexed(uint32_t elem_index) { struct WireValue { WireValue(uint8_t huffman_prefix, bool insert_null_before_wire_value, - const grpc_slice& slice) - : data(slice), + Slice slice) + : data(std::move(slice)), huffman_prefix(huffman_prefix), insert_null_before_wire_value(insert_null_before_wire_value), - length(GRPC_SLICE_LENGTH(slice) + - (insert_null_before_wire_value ? 1 : 0)) {} - // While wire_value is const from the POV of hpack encoder code, actually - // adding it to a slice buffer will possibly split the slice. - const grpc_slice data; + length(data.length() + (insert_null_before_wire_value ? 1 : 0)) {} + Slice data; const uint8_t huffman_prefix; const bool insert_null_before_wire_value; const size_t length; }; -static WireValue GetWireValue(const grpc_slice& value, bool true_binary_enabled, +static WireValue GetWireValue(Slice value, bool true_binary_enabled, bool is_bin_hdr) { if (is_bin_hdr) { if (true_binary_enabled) { GRPC_STATS_INC_HPACK_SEND_BINARY(); - return WireValue(0x00, true, grpc_slice_ref_internal(value)); + return WireValue(0x00, true, std::move(value)); } else { GRPC_STATS_INC_HPACK_SEND_BINARY_BASE64(); return WireValue(0x80, false, - grpc_chttp2_base64_encode_and_huffman_compress(value)); + Slice(grpc_chttp2_base64_encode_and_huffman_compress( + value.c_slice()))); } } else { /* TODO(ctiller): opportunistically compress non-binary headers */ GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(); - return WireValue(0x00, false, grpc_slice_ref_internal(value)); + return WireValue(0x00, false, std::move(value)); } } @@ -238,38 +210,11 @@ struct UnsureIfInterned { } }; -class StringValue { - public: - template <typename MetadataKeyType> - StringValue(MetadataKeyType, grpc_mdelem elem, bool use_true_binary_metadata) - : wire_value_(GetWireValue(GRPC_MDVALUE(elem), use_true_binary_metadata, - MetadataKeyType::IsBinary(GRPC_MDKEY(elem)))), - len_val_(wire_value_.length) {} - - size_t prefix_length() const { - return len_val_.length() + - (wire_value_.insert_null_before_wire_value ? 1 : 0); - } - - void WritePrefix(uint8_t* prefix_data) { - len_val_.Write(wire_value_.huffman_prefix, prefix_data); - if (wire_value_.insert_null_before_wire_value) { - prefix_data[len_val_.length()] = 0; - } - } - - const grpc_slice& data() { return wire_value_.data; } - - private: - WireValue wire_value_; - VarintWriter<1> len_val_; -}; - class BinaryStringValue { public: - explicit BinaryStringValue(const grpc_slice& value, - bool use_true_binary_metadata) - : wire_value_(GetWireValue(value, use_true_binary_metadata, true)), + explicit BinaryStringValue(Slice value, bool use_true_binary_metadata) + : wire_value_( + GetWireValue(std::move(value), use_true_binary_metadata, true)), len_val_(wire_value_.length) {} size_t prefix_length() const { @@ -284,7 +229,7 @@ class BinaryStringValue { } } - const grpc_slice& data() { return wire_value_.data; } + Slice data() { return std::move(wire_value_.data); } private: WireValue wire_value_; @@ -293,24 +238,24 @@ class BinaryStringValue { class NonBinaryStringValue { public: - explicit NonBinaryStringValue(const grpc_slice& value) - : value_(value), len_val_(GRPC_SLICE_LENGTH(value)) {} + explicit NonBinaryStringValue(Slice value) + : value_(std::move(value)), len_val_(value_.length()) {} size_t prefix_length() const { return len_val_.length(); } void WritePrefix(uint8_t* prefix_data) { len_val_.Write(0x00, prefix_data); } - const grpc_slice& data() { return value_; } + Slice data() { return std::move(value_); } private: - grpc_slice value_; + Slice value_; VarintWriter<1> len_val_; }; class StringKey { public: - explicit StringKey(grpc_slice key) - : key_(key), len_key_(GRPC_SLICE_LENGTH(key)) {} + explicit StringKey(Slice key) + : key_(std::move(key)), len_key_(key_.length()) {} size_t prefix_length() const { return 1 + len_key_.length(); } @@ -319,91 +264,71 @@ class StringKey { len_key_.Write(0x00, data + 1); } - grpc_slice key() const { return key_; } + Slice key() { return std::move(key_); } private: - grpc_slice key_; + Slice key_; VarintWriter<1> len_key_; }; -void HPackCompressor::Framer::EmitLitHdrIncIdx(uint32_t key_index, - grpc_mdelem elem) { - GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX(); - StringValue emit(DefinitelyInterned(), elem, use_true_binary_metadata_); - VarintWriter<2> key(key_index); - uint8_t* data = AddTiny(key.length() + emit.prefix_length()); - key.Write(0x40, data); - emit.WritePrefix(data + key.length()); - Add(emit.data()); -} - -void HPackCompressor::Framer::EmitLitHdrNotIdx(uint32_t key_index, - grpc_mdelem elem) { - GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX(); - StringValue emit(DefinitelyInterned(), elem, use_true_binary_metadata_); - VarintWriter<4> key(key_index); - uint8_t* data = AddTiny(key.length() + emit.prefix_length()); - key.Write(0x00, data); - emit.WritePrefix(data + key.length()); - Add(emit.data()); -} - -void HPackCompressor::Framer::EmitLitHdrWithStringKeyIncIdx(grpc_mdelem elem) { +void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyIncIdx( + Slice key_slice, Slice value_slice) { GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V(); GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(); - StringKey key(GRPC_MDKEY(elem)); + StringKey key(std::move(key_slice)); key.WritePrefix(0x40, AddTiny(key.prefix_length())); - Add(grpc_slice_ref_internal(key.key())); - StringValue emit(DefinitelyInterned(), elem, use_true_binary_metadata_); + Add(key.key()); + NonBinaryStringValue emit(std::move(value_slice)); emit.WritePrefix(AddTiny(emit.prefix_length())); Add(emit.data()); } -void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyIncIdx( - const grpc_slice& key_slice, const grpc_slice& value_slice) { - GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V(); +void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyNotIdx( + Slice key_slice, Slice value_slice) { + GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(); GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(); - StringKey key(key_slice); - key.WritePrefix(0x40, AddTiny(key.prefix_length())); - Add(grpc_slice_ref_internal(key.key())); - NonBinaryStringValue emit(value_slice); + StringKey key(std::move(key_slice)); + key.WritePrefix(0x00, AddTiny(key.prefix_length())); + Add(key.key()); + BinaryStringValue emit(std::move(value_slice), use_true_binary_metadata_); emit.WritePrefix(AddTiny(emit.prefix_length())); - Add(grpc_slice_ref_internal(emit.data())); + Add(emit.data()); } -void HPackCompressor::Framer::EmitLitHdrWithStringKeyNotIdx(grpc_mdelem elem) { - GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(); +void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyIncIdx( + Slice key_slice, Slice value_slice) { + GRPC_STATS_INC_HPACK_SEND_LITHDR_INCIDX_V(); GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(); - StringKey key(GRPC_MDKEY(elem)); - key.WritePrefix(0x00, AddTiny(key.prefix_length())); - Add(grpc_slice_ref_internal(key.key())); - StringValue emit(UnsureIfInterned(), elem, use_true_binary_metadata_); + StringKey key(std::move(key_slice)); + key.WritePrefix(0x40, AddTiny(key.prefix_length())); + Add(key.key()); + BinaryStringValue emit(std::move(value_slice), use_true_binary_metadata_); emit.WritePrefix(AddTiny(emit.prefix_length())); Add(emit.data()); } void HPackCompressor::Framer::EmitLitHdrWithBinaryStringKeyNotIdx( - const grpc_slice& key_slice, const grpc_slice& value_slice) { - GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(); + uint32_t key_index, Slice value_slice) { + GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX(); GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(); - StringKey key(key_slice); - key.WritePrefix(0x00, AddTiny(key.prefix_length())); - Add(grpc_slice_ref_internal(key.key())); - BinaryStringValue emit(value_slice, use_true_binary_metadata_); - emit.WritePrefix(AddTiny(emit.prefix_length())); + BinaryStringValue emit(std::move(value_slice), use_true_binary_metadata_); + VarintWriter<4> key(key_index); + uint8_t* data = AddTiny(key.length() + emit.prefix_length()); + key.Write(0x00, data); + emit.WritePrefix(data + key.length()); Add(emit.data()); } void HPackCompressor::Framer::EmitLitHdrWithNonBinaryStringKeyNotIdx( - const grpc_slice& key_slice, const grpc_slice& value_slice) { + Slice key_slice, Slice value_slice) { GRPC_STATS_INC_HPACK_SEND_LITHDR_NOTIDX_V(); GRPC_STATS_INC_HPACK_SEND_UNCOMPRESSED(); - StringKey key(key_slice); + StringKey key(std::move(key_slice)); key.WritePrefix(0x00, AddTiny(key.prefix_length())); - Add(grpc_slice_ref_internal(key.key())); - NonBinaryStringValue emit(value_slice); + Add(key.key()); + NonBinaryStringValue emit(std::move(value_slice)); emit.WritePrefix(AddTiny(emit.prefix_length())); - Add(grpc_slice_ref_internal(emit.data())); + Add(emit.data()); } void HPackCompressor::Framer::AdvertiseTableSizeChange() { @@ -411,159 +336,308 @@ void HPackCompressor::Framer::AdvertiseTableSizeChange() { w.Write(0x20, AddTiny(w.length())); } -void HPackCompressor::Framer::Log(grpc_mdelem elem) { - char* k = grpc_slice_to_c_string(GRPC_MDKEY(elem)); - char* v = nullptr; - if (grpc_is_binary_header_internal(GRPC_MDKEY(elem))) { - v = grpc_dump_slice(GRPC_MDVALUE(elem), GPR_DUMP_HEX); - } else { - v = grpc_slice_to_c_string(GRPC_MDVALUE(elem)); - } - gpr_log( - GPR_INFO, - "Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d", - k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem), - grpc_slice_is_interned(GRPC_MDKEY(elem)), - grpc_slice_is_interned(GRPC_MDVALUE(elem))); - gpr_free(k); - gpr_free(v); -} - -struct EmitIndexedStatus { - EmitIndexedStatus() = default; - EmitIndexedStatus(uint32_t elem_hash, bool emitted, bool can_add) - : elem_hash(elem_hash), emitted(emitted), can_add(can_add) {} - const uint32_t elem_hash = 0; - const bool emitted = false; - const bool can_add = false; -}; - -/* encode an mdelem */ -void HPackCompressor::Framer::EncodeDynamic(grpc_mdelem elem) { - const grpc_slice& elem_key = GRPC_MDKEY(elem); - // User-provided key len validated in grpc_validate_header_key_is_legal(). - GPR_DEBUG_ASSERT(GRPC_SLICE_LENGTH(elem_key) > 0); - // Header ordering: all reserved headers (prefixed with ':') must precede - // regular headers. This can be a debug assert, since: - // 1) User cannot give us ':' headers (grpc_validate_header_key_is_legal()). - // 2) grpc filters/core should be checked during debug builds. */ -#ifndef NDEBUG - if (GRPC_SLICE_START_PTR(elem_key)[0] != ':') { /* regular header */ - seen_regular_header_ = true; - } else { - GPR_DEBUG_ASSERT( - !seen_regular_header_ && - "Reserved header (colon-prefixed) happening after regular ones."); - } -#endif - if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace)) { - Log(elem); - } - const bool elem_interned = GRPC_MDELEM_IS_INTERNED(elem); - const bool key_interned = elem_interned || grpc_slice_is_interned(elem_key); - // Key is not interned, emit literals. - if (!key_interned) { - EmitLitHdrWithStringKeyNotIdx(elem); +void HPackCompressor::SliceIndex::EmitTo(y_absl::string_view key, + const Slice& value, Framer* framer) { + auto& table = framer->compressor_->table_; + using It = std::vector<ValueIndex>::iterator; + It prev = values_.end(); + uint32_t transport_length = + key.length() + value.length() + hpack_constants::kEntryOverhead; + if (transport_length > HPackEncoderTable::MaxEntrySize()) { + framer->EmitLitHdrWithNonBinaryStringKeyNotIdx(Slice::FromStaticString(key), + value.Ref()); return; } - /* Interned metadata => maybe already indexed. */ - uint32_t elem_hash = 0; - if (elem_interned) { - // Update filter to see if we can perhaps add this elem. - elem_hash = - GRPC_MDELEM_STORAGE(elem) == GRPC_MDELEM_STORAGE_INTERNED - ? reinterpret_cast<InternedMetadata*>(GRPC_MDELEM_DATA(elem)) - ->hash() - : reinterpret_cast<StaticMetadata*>(GRPC_MDELEM_DATA(elem))->hash(); - bool can_add_to_hashtable = - compressor_->filter_elems_.AddElement(elem_hash % kNumFilterValues); - /* is this elem currently in the decoders table? */ - auto indices_key = - compressor_->elem_index_.Lookup(KeyElem(elem, elem_hash)); - if (indices_key.has_value() && - compressor_->table_.ConvertableToDynamicIndex(*indices_key)) { - EmitIndexed(compressor_->table_.DynamicIndex(*indices_key)); + // Linear scan through previous values to see if we find the value. + for (It it = values_.begin(); it != values_.end(); ++it) { + if (value == it->value) { + // Got a hit... is it still in the decode table? + if (table.ConvertableToDynamicIndex(it->index)) { + // Yes, emit the index and proceed to cleanup. + framer->EmitIndexed(table.DynamicIndex(it->index)); + } else { + // Not current, emit a new literal and update the index. + it->index = table.AllocateIndex(transport_length); + framer->EmitLitHdrWithNonBinaryStringKeyIncIdx( + Slice::FromStaticString(key), value.Ref()); + } + // Bubble this entry up if we can - ensures that the most used values end + // up towards the start of the array. + if (prev != values_.end()) std::swap(*prev, *it); + // If there are entries at the end of the array, and those entries are no + // longer in the table, remove them. + while (!values_.empty() && + !table.ConvertableToDynamicIndex(values_.back().index)) { + values_.pop_back(); + } + // All done, early out. return; } - /* Didn't hit either cuckoo index, so no emit. */ - if (!can_add_to_hashtable) elem_hash = 0; - } - - /* should this elem be in the table? */ - const size_t decoder_space_usage = - MetadataSizeInHPackTable(elem, use_true_binary_metadata_); - const bool decoder_space_available = - decoder_space_usage < kMaxDecoderSpaceUsage; - const bool should_add_elem = - elem_interned && decoder_space_available && elem_hash != 0; - /* no hits for the elem... maybe there's a key? */ - const uint32_t key_hash = elem_key.refcount->Hash(elem_key); - auto indices_key = - compressor_->key_index_.Lookup(KeySliceRef(elem_key.refcount, key_hash)); - if (indices_key.has_value() && - compressor_->table_.ConvertableToDynamicIndex(*indices_key)) { - if (should_add_elem) { - EmitLitHdrIncIdx(compressor_->table_.DynamicIndex(*indices_key), elem); - compressor_->AddElem(elem, decoder_space_usage, elem_hash, key_hash); - } else { - EmitLitHdrNotIdx(compressor_->table_.DynamicIndex(*indices_key), elem); - } - return; + prev = it; } - /* no elem, key in the table... fall back to literal emission */ - const bool should_add_key = !elem_interned && decoder_space_available; - if (should_add_elem || should_add_key) { - EmitLitHdrWithStringKeyIncIdx(elem); + // No hit, emit a new literal and add it to the index. + uint32_t index = table.AllocateIndex(transport_length); + framer->EmitLitHdrWithNonBinaryStringKeyIncIdx(Slice::FromStaticString(key), + value.Ref()); + values_.emplace_back(value.Ref(), index); +} + +void HPackCompressor::Framer::Encode(const Slice& key, const Slice& value) { + if (y_absl::EndsWith(key.as_string_view(), "-bin")) { + EmitLitHdrWithBinaryStringKeyNotIdx(key.Ref(), value.Ref()); } else { - EmitLitHdrWithStringKeyNotIdx(elem); - } - if (should_add_elem) { - compressor_->AddElem(elem, decoder_space_usage, elem_hash, key_hash); - } else if (should_add_key) { - compressor_->AddKey(elem, decoder_space_usage, key_hash); + EmitLitHdrWithNonBinaryStringKeyNotIdx(key.Ref(), value.Ref()); } } +void HPackCompressor::Framer::Encode(HttpPathMetadata, const Slice& value) { + compressor_->path_index_.EmitTo(HttpPathMetadata::key(), value, this); +} + +void HPackCompressor::Framer::Encode(HttpAuthorityMetadata, + const Slice& value) { + compressor_->authority_index_.EmitTo(HttpAuthorityMetadata::key(), value, + this); +} + void HPackCompressor::Framer::Encode(TeMetadata, TeMetadata::ValueType value) { GPR_ASSERT(value == TeMetadata::ValueType::kTrailers); EncodeAlwaysIndexed( - &compressor_->te_index_, GRPC_MDSTR_TE, GRPC_MDSTR_TRAILERS, + &compressor_->te_index_, "te", Slice::FromStaticString("trailers"), 2 /* te */ + 8 /* trailers */ + hpack_constants::kEntryOverhead); } +void HPackCompressor::Framer::Encode(ContentTypeMetadata, + ContentTypeMetadata::ValueType value) { + if (value != ContentTypeMetadata::ValueType::kApplicationGrpc) { + gpr_log(GPR_ERROR, "Not encoding bad content-type header"); + return; + } + EncodeAlwaysIndexed(&compressor_->content_type_index_, "content-type", + Slice::FromStaticString("application/grpc"), + 12 /* content-type */ + 16 /* application/grpc */ + + hpack_constants::kEntryOverhead); +} + +void HPackCompressor::Framer::Encode(HttpSchemeMetadata, + HttpSchemeMetadata::ValueType value) { + switch (value) { + case HttpSchemeMetadata::ValueType::kHttp: + EmitIndexed(6); // :scheme: http + break; + case HttpSchemeMetadata::ValueType::kHttps: + EmitIndexed(7); // :scheme: https + break; + case HttpSchemeMetadata::ValueType::kInvalid: + GPR_ASSERT(false); + break; + } +} + +void HPackCompressor::Framer::Encode(GrpcTraceBinMetadata, const Slice& slice) { + EncodeIndexedKeyWithBinaryValue(&compressor_->grpc_trace_bin_index_, + "grpc-trace-bin", slice.Ref()); +} + +void HPackCompressor::Framer::Encode(GrpcTagsBinMetadata, const Slice& slice) { + EncodeIndexedKeyWithBinaryValue(&compressor_->grpc_tags_bin_index_, + "grpc-tags-bin", slice.Ref()); +} + +void HPackCompressor::Framer::Encode(HttpStatusMetadata, uint32_t status) { + if (status == 200) { + EmitIndexed(8); // :status: 200 + return; + } + uint8_t index = 0; + switch (status) { + case 204: + index = 9; // :status: 204 + break; + case 206: + index = 10; // :status: 206 + break; + case 304: + index = 11; // :status: 304 + break; + case 400: + index = 12; // :status: 400 + break; + case 404: + index = 13; // :status: 404 + break; + case 500: + index = 14; // :status: 500 + break; + } + if (GPR_LIKELY(index != 0)) { + EmitIndexed(index); + } else { + EmitLitHdrWithNonBinaryStringKeyIncIdx(Slice::FromStaticString(":status"), + Slice::FromInt64(status)); + } +} + +void HPackCompressor::Framer::Encode(HttpMethodMetadata, + HttpMethodMetadata::ValueType method) { + switch (method) { + case HttpMethodMetadata::ValueType::kGet: + EmitIndexed(2); // :method: GET + break; + case HttpMethodMetadata::ValueType::kPost: + EmitIndexed(3); // :method: POST + break; + case HttpMethodMetadata::ValueType::kPut: + EmitLitHdrWithNonBinaryStringKeyNotIdx(Slice::FromStaticString(":method"), + Slice::FromStaticString("PUT")); + break; + case HttpMethodMetadata::ValueType::kInvalid: + GPR_ASSERT(false); + break; + } +} + void HPackCompressor::Framer::EncodeAlwaysIndexed(uint32_t* index, - const grpc_slice& key, - const grpc_slice& value, + y_absl::string_view key, + Slice value, uint32_t transport_length) { if (compressor_->table_.ConvertableToDynamicIndex(*index)) { EmitIndexed(compressor_->table_.DynamicIndex(*index)); } else { *index = compressor_->table_.AllocateIndex(transport_length); - EmitLitHdrWithNonBinaryStringKeyIncIdx(key, value); + EmitLitHdrWithNonBinaryStringKeyIncIdx(Slice::FromStaticString(key), + std::move(value)); + } +} + +void HPackCompressor::Framer::EncodeIndexedKeyWithBinaryValue( + uint32_t* index, y_absl::string_view key, Slice value) { + if (compressor_->table_.ConvertableToDynamicIndex(*index)) { + EmitLitHdrWithBinaryStringKeyNotIdx( + compressor_->table_.DynamicIndex(*index), std::move(value)); + } else { + *index = compressor_->table_.AllocateIndex(key.length() + value.length() + + hpack_constants::kEntryOverhead); + EmitLitHdrWithBinaryStringKeyIncIdx(Slice::FromStaticString(key), + std::move(value)); } } void HPackCompressor::Framer::Encode(GrpcTimeoutMetadata, grpc_millis deadline) { - char timeout_str[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; - grpc_mdelem mdelem; - grpc_http2_encode_timeout(deadline - ExecCtx::Get()->Now(), timeout_str); - mdelem = grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_TIMEOUT, - UnmanagedMemorySlice(timeout_str)); - EncodeDynamic(mdelem); - GRPC_MDELEM_UNREF(mdelem); + Timeout timeout = Timeout::FromDuration(deadline - ExecCtx::Get()->Now()); + for (auto it = compressor_->previous_timeouts_.begin(); + it != compressor_->previous_timeouts_.end(); ++it) { + double ratio = timeout.RatioVersus(it->timeout); + // If the timeout we're sending is shorter than a previous timeout, but + // within 3% of it, we'll consider sending it. + if (ratio > -3 && ratio <= 0 && + compressor_->table_.ConvertableToDynamicIndex(it->index)) { + EmitIndexed(compressor_->table_.DynamicIndex(it->index)); + // Put this timeout to the front of the queue - forces common timeouts to + // be considered earlier. + std::swap(*it, *compressor_->previous_timeouts_.begin()); + return; + } + } + // Clean out some expired timeouts. + while (!compressor_->previous_timeouts_.empty() && + !compressor_->table_.ConvertableToDynamicIndex( + compressor_->previous_timeouts_.back().index)) { + compressor_->previous_timeouts_.pop_back(); + } + Slice encoded = timeout.Encode(); + uint32_t index = compressor_->table_.AllocateIndex( + GrpcTimeoutMetadata::key().length() + encoded.length() + + hpack_constants::kEntryOverhead); + compressor_->previous_timeouts_.push_back(PreviousTimeout{timeout, index}); + EmitLitHdrWithNonBinaryStringKeyIncIdx( + Slice::FromStaticString(GrpcTimeoutMetadata::key()), std::move(encoded)); } void HPackCompressor::Framer::Encode(UserAgentMetadata, const Slice& slice) { + if (slice.length() > HPackEncoderTable::MaxEntrySize()) { + EmitLitHdrWithNonBinaryStringKeyNotIdx( + Slice::FromStaticString(UserAgentMetadata::key()), slice.Ref()); + return; + } if (!slice.is_equivalent(compressor_->user_agent_)) { compressor_->user_agent_ = slice.Ref(); compressor_->user_agent_index_ = 0; } EncodeAlwaysIndexed( - &compressor_->user_agent_index_, GRPC_MDSTR_USER_AGENT, slice.c_slice(), + &compressor_->user_agent_index_, "user-agent", slice.Ref(), 10 /* user-agent */ + slice.size() + hpack_constants::kEntryOverhead); } +void HPackCompressor::Framer::Encode(GrpcStatusMetadata, + grpc_status_code status) { + const uint32_t code = static_cast<uint32_t>(status); + uint32_t* index = nullptr; + if (code < kNumCachedGrpcStatusValues) { + index = &compressor_->cached_grpc_status_[code]; + if (compressor_->table_.ConvertableToDynamicIndex(*index)) { + EmitIndexed(compressor_->table_.DynamicIndex(*index)); + return; + } + } + Slice key = Slice::FromStaticString(GrpcStatusMetadata::key()); + Slice value = Slice::FromInt64(code); + const uint32_t transport_length = + key.length() + value.length() + hpack_constants::kEntryOverhead; + if (index != nullptr) { + *index = compressor_->table_.AllocateIndex(transport_length); + EmitLitHdrWithNonBinaryStringKeyIncIdx(std::move(key), std::move(value)); + } else { + EmitLitHdrWithNonBinaryStringKeyNotIdx(std::move(key), std::move(value)); + } +} + +void HPackCompressor::Framer::Encode(GrpcEncodingMetadata, + grpc_compression_algorithm value) { + uint32_t* index = nullptr; + if (value < GRPC_COMPRESS_ALGORITHMS_COUNT) { + index = &compressor_->cached_grpc_encoding_[static_cast<uint32_t>(value)]; + if (compressor_->table_.ConvertableToDynamicIndex(*index)) { + EmitIndexed(compressor_->table_.DynamicIndex(*index)); + return; + } + } + auto key = Slice::FromStaticString(GrpcEncodingMetadata::key()); + auto encoded_value = GrpcEncodingMetadata::Encode(value); + uint32_t transport_length = + key.length() + encoded_value.length() + hpack_constants::kEntryOverhead; + if (index != nullptr) { + *index = compressor_->table_.AllocateIndex(transport_length); + EmitLitHdrWithNonBinaryStringKeyIncIdx(std::move(key), + std::move(encoded_value)); + } else { + EmitLitHdrWithNonBinaryStringKeyNotIdx(std::move(key), + std::move(encoded_value)); + } +} + +void HPackCompressor::Framer::Encode(GrpcAcceptEncodingMetadata, + CompressionAlgorithmSet value) { + if (compressor_->grpc_accept_encoding_index_ != 0 && + value == compressor_->grpc_accept_encoding_ && + compressor_->table_.ConvertableToDynamicIndex( + compressor_->grpc_accept_encoding_index_)) { + EmitIndexed(compressor_->table_.DynamicIndex( + compressor_->grpc_accept_encoding_index_)); + return; + } + auto key = Slice::FromStaticString(GrpcAcceptEncodingMetadata::key()); + auto encoded_value = GrpcAcceptEncodingMetadata::Encode(value); + uint32_t transport_length = + key.length() + encoded_value.length() + hpack_constants::kEntryOverhead; + compressor_->grpc_accept_encoding_index_ = + compressor_->table_.AllocateIndex(transport_length); + compressor_->grpc_accept_encoding_ = value; + EmitLitHdrWithNonBinaryStringKeyIncIdx(std::move(key), + std::move(encoded_value)); +} + void HPackCompressor::SetMaxUsableSize(uint32_t max_table_size) { max_usable_size_ = max_table_size; SetMaxTableSize(std::min(table_.max_size(), max_table_size)); @@ -595,16 +669,4 @@ HPackCompressor::Framer::Framer(const EncodeHeaderOptions& options, } } -void HPackCompressor::Framer::Encode(grpc_mdelem md) { - if (GRPC_MDELEM_STORAGE(md) == GRPC_MDELEM_STORAGE_STATIC) { - const uintptr_t static_index = - reinterpret_cast<StaticMetadata*>(GRPC_MDELEM_DATA(md))->StaticIndex(); - if (static_index < hpack_constants::kLastStaticEntry) { - EmitIndexed(static_cast<uint32_t>(static_index + 1)); - return; - } - } - EncodeDynamic(md); -} - } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.h index f7eaeb28d4..6dda75c6eb 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.h +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.h @@ -21,14 +21,13 @@ #include <grpc/support/port_platform.h> +#include <cstdint> + #include <grpc/slice.h> #include <grpc/slice_buffer.h> #include "src/core/ext/transport/chttp2/transport/frame.h" -#include "src/core/ext/transport/chttp2/transport/hpack_encoder_index.h" #include "src/core/ext/transport/chttp2/transport/hpack_encoder_table.h" -#include "src/core/ext/transport/chttp2/transport/popularity_count.h" -#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata_batch.h" #include "src/core/lib/transport/transport.h" @@ -36,48 +35,9 @@ extern grpc_core::TraceFlag grpc_http_trace; namespace grpc_core { -// Wrapper to take an array of mdelems and make them encodable -class MetadataArray { - public: - MetadataArray(grpc_mdelem** elems, size_t count) - : elems_(elems), count_(count) {} - - template <typename Encoder> - void Encode(Encoder* encoder) const { - for (size_t i = 0; i < count_; i++) { - encoder->Encode(*elems_[i]); - } - } - - private: - grpc_mdelem** elems_; - size_t count_; -}; - -namespace metadata_detail { -template <typename A, typename B> -class ConcatMetadata { - public: - ConcatMetadata(const A& a, const B& b) : a_(a), b_(b) {} - - template <typename Encoder> - void Encode(Encoder* encoder) const { - a_.Encode(encoder); - b_.Encode(encoder); - } - - private: - const A& a_; - const B& b_; -}; -} // namespace metadata_detail - -template <typename A, typename B> -metadata_detail::ConcatMetadata<A, B> ConcatMetadata(const A& a, const B& b) { - return metadata_detail::ConcatMetadata<A, B>(a, b); -} - class HPackCompressor { + class SliceIndex; + public: HPackCompressor() = default; ~HPackCompressor() = default; @@ -116,30 +76,41 @@ class HPackCompressor { Framer(const Framer&) = delete; Framer& operator=(const Framer&) = delete; - void Encode(grpc_mdelem md); + void Encode(const Slice& key, const Slice& value); + void Encode(HttpPathMetadata, const Slice& value); + void Encode(HttpAuthorityMetadata, const Slice& value); + void Encode(HttpStatusMetadata, uint32_t status); void Encode(GrpcTimeoutMetadata, grpc_millis deadline); void Encode(TeMetadata, TeMetadata::ValueType value); + void Encode(ContentTypeMetadata, ContentTypeMetadata::ValueType value); + void Encode(HttpSchemeMetadata, HttpSchemeMetadata::ValueType value); + void Encode(HttpMethodMetadata, HttpMethodMetadata::ValueType method); void Encode(UserAgentMetadata, const Slice& slice); + void Encode(GrpcStatusMetadata, grpc_status_code status); + void Encode(GrpcEncodingMetadata, grpc_compression_algorithm value); + void Encode(GrpcAcceptEncodingMetadata, CompressionAlgorithmSet value); + void Encode(GrpcTagsBinMetadata, const Slice& slice); + void Encode(GrpcTraceBinMetadata, const Slice& slice); void Encode(GrpcMessageMetadata, const Slice& slice) { if (slice.empty()) return; EmitLitHdrWithNonBinaryStringKeyNotIdx( - StaticSlice::FromStaticString("grpc-message").c_slice(), - slice.c_slice()); + Slice::FromStaticString("grpc-message"), slice.Ref()); } template <typename Which> - void Encode(Which, const Slice& slice) { + void Encode(Which, const typename Which::ValueType& value) { + const Slice& slice = MetadataValueAsSlice<Which>(value); if (y_absl::EndsWith(Which::key(), "-bin")) { EmitLitHdrWithBinaryStringKeyNotIdx( - StaticSlice::FromStaticString(Which::key()).c_slice(), - slice.c_slice()); + Slice::FromStaticString(Which::key()), slice.Ref()); } else { EmitLitHdrWithNonBinaryStringKeyNotIdx( - StaticSlice::FromStaticString(Which::key()).c_slice(), - slice.c_slice()); + Slice::FromStaticString(Which::key()), slice.Ref()); } } private: + friend class SliceIndex; + struct FramePrefix { // index (in output_) of the header for the frame size_t header_idx; @@ -154,26 +125,24 @@ class HPackCompressor { void AdvertiseTableSizeChange(); void EmitIndexed(uint32_t index); - void EncodeDynamic(grpc_mdelem elem); - static GPR_ATTRIBUTE_NOINLINE void Log(grpc_mdelem elem); - - void EmitLitHdrIncIdx(uint32_t key_index, grpc_mdelem elem); - void EmitLitHdrNotIdx(uint32_t key_index, grpc_mdelem elem); - void EmitLitHdrWithStringKeyIncIdx(grpc_mdelem elem); - void EmitLitHdrWithNonBinaryStringKeyIncIdx(const grpc_slice& key_slice, - const grpc_slice& value_slice); - void EmitLitHdrWithBinaryStringKeyNotIdx(const grpc_slice& key_slice, - const grpc_slice& value_slice); - void EmitLitHdrWithNonBinaryStringKeyNotIdx(const grpc_slice& key_slice, - const grpc_slice& value_slice); - void EmitLitHdrWithStringKeyNotIdx(grpc_mdelem elem); - - void EncodeAlwaysIndexed(uint32_t* index, const grpc_slice& key, - const grpc_slice& value, - uint32_t transport_length); + void EmitLitHdrWithNonBinaryStringKeyIncIdx(Slice key_slice, + Slice value_slice); + void EmitLitHdrWithBinaryStringKeyIncIdx(Slice key_slice, + Slice value_slice); + void EmitLitHdrWithBinaryStringKeyNotIdx(Slice key_slice, + Slice value_slice); + void EmitLitHdrWithBinaryStringKeyNotIdx(uint32_t key_index, + Slice value_slice); + void EmitLitHdrWithNonBinaryStringKeyNotIdx(Slice key_slice, + Slice value_slice); + + void EncodeAlwaysIndexed(uint32_t* index, y_absl::string_view key, + Slice value, uint32_t transport_length); + void EncodeIndexedKeyWithBinaryValue(uint32_t* index, y_absl::string_view key, + Slice value); size_t CurrentFrameSize() const; - void Add(grpc_slice slice); + void Add(Slice slice); uint8_t* AddTiny(size_t len); // maximum size of a frame @@ -183,10 +152,6 @@ class HPackCompressor { const bool is_end_of_stream_; // output stream id const uint32_t stream_id_; -#ifndef NDEBUG - // have we seen a regular (non-colon-prefixed) header yet? - bool seen_regular_header_ = false; -#endif grpc_slice_buffer* const output_; grpc_transport_one_way_stats* const stats_; HPackCompressor* const compressor_; @@ -195,14 +160,7 @@ class HPackCompressor { private: static constexpr size_t kNumFilterValues = 64; - - void AddKeyWithIndex(grpc_slice_refcount* key_ref, uint32_t new_index, - uint32_t key_hash); - void AddElemWithIndex(grpc_mdelem elem, uint32_t new_index, - uint32_t elem_hash, uint32_t key_hash); - void AddElem(grpc_mdelem elem, size_t elem_size, uint32_t elem_hash, - uint32_t key_hash); - void AddKey(grpc_mdelem elem, size_t elem_size, uint32_t key_hash); + static constexpr uint32_t kNumCachedGrpcStatusValues = 16; // maximum number of bytes we'll use for the decode table (to guard against // peers ooming us by setting decode table size high) @@ -212,96 +170,48 @@ class HPackCompressor { bool advertise_table_size_change_ = false; HPackEncoderTable table_; - // filter tables for elems: this tables provides an approximate - // popularity count for particular hashes, and are used to determine whether - // a new literal should be added to the compression table or not. - // They track a single integer that counts how often a particular value has - // been seen. When that count reaches max (255), all values are halved. - PopularityCount<kNumFilterValues> filter_elems_; - - class KeyElem { + class SliceIndex { public: - class Stored { - public: - Stored() : elem_(GRPC_MDNULL) {} - explicit Stored(grpc_mdelem elem) : elem_(GRPC_MDELEM_REF(elem)) {} - Stored(const Stored& other) : elem_(GRPC_MDELEM_REF(other.elem_)) {} - Stored& operator=(Stored other) { - std::swap(elem_, other.elem_); - return *this; - } - ~Stored() { GRPC_MDELEM_UNREF(elem_); } - - const grpc_mdelem& elem() const { return elem_; } - - bool operator==(const Stored& other) const noexcept { - return elem_.payload == other.elem_.payload; - } - - private: - grpc_mdelem elem_; - }; - - KeyElem(grpc_mdelem elem, uint32_t hash) : elem_(elem), hash_(hash) {} - KeyElem(const KeyElem&); - KeyElem& operator=(const KeyElem&); - - uint32_t hash() const { - // TODO(ctiller): unify this with what's in the cc file when we move this - // code to c++ - return hash_ >> 6; - } - - Stored stored() const { return Stored(elem_); } - - bool operator==(const Stored& stored) const noexcept { - return elem_.payload == stored.elem().payload; - } + void EmitTo(y_absl::string_view key, const Slice& value, Framer* framer); private: - grpc_mdelem elem_; - uint32_t hash_; + struct ValueIndex { + ValueIndex(Slice value, uint32_t index) + : value(std::move(value)), index(index) {} + Slice value; + uint32_t index; + }; + std::vector<ValueIndex> values_; }; - class KeySliceRef { - public: - using Stored = RefCountedPtr<grpc_slice_refcount>; - - KeySliceRef(grpc_slice_refcount* ref, uint32_t hash) - : ref_(ref), hash_(hash) {} - KeySliceRef(const KeySliceRef&) = delete; - KeySliceRef& operator=(const KeySliceRef&) = delete; - - uint32_t hash() const { - // TODO(ctiller): unify this with what's in the cc file when we move this - // code to c++ - return hash_ >> 6; - } - - Stored stored() const { - ref_->Ref(); - return Stored(ref_); - } - - bool operator==(const Stored& stored) const noexcept { - return ref_ == stored.get(); - } - - private: - grpc_slice_refcount* ref_; - uint32_t hash_; + struct PreviousTimeout { + Timeout timeout; + uint32_t index; }; - // entry tables for keys & elems: these tables track values that have been - // seen and *may* be in the decompressor table - HPackEncoderIndex<KeyElem, kNumFilterValues> elem_index_; - HPackEncoderIndex<KeySliceRef, kNumFilterValues> key_index_; // Index into table_ for the te:trailers metadata element uint32_t te_index_ = 0; + // Index into table_ for the content-type metadata element + uint32_t content_type_index_ = 0; // Index into table_ for the user-agent metadata element uint32_t user_agent_index_ = 0; + // Cached grpc-status values + uint32_t cached_grpc_status_[kNumCachedGrpcStatusValues] = {}; + // Cached grpc-encoding values + uint32_t cached_grpc_encoding_[GRPC_COMPRESS_ALGORITHMS_COUNT] = {}; + // Cached grpc-accept-encoding value + uint32_t grpc_accept_encoding_index_ = 0; + // The grpc-accept-encoding string referred to by grpc_accept_encoding_index_ + CompressionAlgorithmSet grpc_accept_encoding_; + // Index of something that was sent with grpc-tags-bin + uint32_t grpc_tags_bin_index_ = 0; + // Index of something that was sent with grpc-trace-bin + uint32_t grpc_trace_bin_index_ = 0; // The user-agent string referred to by user_agent_index_ Slice user_agent_; + SliceIndex path_index_; + SliceIndex authority_index_; + std::vector<PreviousTimeout> previous_timeouts_; }; } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_index.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_index.h deleted file mode 100644 index f3e5003bcd..0000000000 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_index.h +++ /dev/null @@ -1,107 +0,0 @@ -// 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_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_INDEX_H -#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_INDEX_H - -#include <grpc/support/port_platform.h> - -#include "y_absl/types/optional.h" - -namespace grpc_core { - -// A fixed size mapping of a key to a chronologically ordered index -template <typename Key, size_t kNumEntries> -class HPackEncoderIndex { - public: - using Index = uint32_t; - - HPackEncoderIndex() : entries_{} {} - - // If key exists in the table, update it to a new index. - // If it does not and there is an empty slot, add it to the index. - // Finally, if it does not and there is no empty slot, evict the oldest - // conflicting member. - void Insert(const Key& key, Index new_index) { - auto* const cuckoo_first = first_slot(key); - if (cuckoo_first->UpdateOrAdd(key, new_index)) return; - auto* const cuckoo_second = second_slot(key); - if (cuckoo_second->UpdateOrAdd(key, new_index)) return; - auto* const clobber = Older(cuckoo_first, cuckoo_second); - clobber->key = key.stored(); - clobber->index = new_index; - } - - // Lookup key and return its index, or return empty if it's not in this table. - y_absl::optional<Index> Lookup(const Key& key) { - auto* const cuckoo_first = first_slot(key); - if (key == cuckoo_first->key) return cuckoo_first->index; - auto* const cuckoo_second = second_slot(key); - if (key == cuckoo_second->key) return cuckoo_second->index; - return {}; - } - - private: - using StoredKey = typename Key::Stored; - - // One entry in the index - struct Entry { - Entry() : key{}, index{} {}; - - StoredKey key; - Index index; - - // Update this entry if it matches key, otherwise if it's empty add it. - // If neither happens, return false. - bool UpdateOrAdd(const Key& new_key, Index new_index) { - if (new_key == key) { - index = new_index; - return true; - } else if (key == StoredKey()) { - key = new_key.stored(); - index = new_index; - return true; - } else { - return false; - } - } - }; - - static Entry* Older(Entry* a, Entry* b) { - if (a->index < b->index) { - return a; - } else { - return b; - } - } - - // Return the first slot in which key could be stored. - Entry* first_slot(const Key& key) { - return &entries_[key.hash() % kNumEntries]; - } - - // Return the second slot in which key could be stored. - Entry* second_slot(const Key& key) { - return &entries_[(key.hash() / kNumEntries) % kNumEntries]; - } - - // Fixed size entry map. - // We store each key/value pair in two slots based on it's hash value. - // They can be evicted individually. - Entry entries_[kNumEntries]; -}; - -} // namespace grpc_core - -#endif // GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_ENCODER_INDEX_H diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc index bfe152a91f..ef31a01924 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc @@ -22,7 +22,7 @@ namespace grpc_core { uint32_t HPackEncoderTable::AllocateIndex(size_t element_size) { uint32_t new_index = tail_remote_index_ + table_elems_ + 1; - GPR_DEBUG_ASSERT(element_size < 65536); + GPR_DEBUG_ASSERT(element_size <= MaxEntrySize()); if (element_size > max_table_size_) { while (table_size_ > 0) { diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.h index 47971d271c..7aedd2c8b9 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.h +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.h @@ -29,6 +29,8 @@ class HPackEncoderTable { public: HPackEncoderTable() : elem_size_(hpack_constants::kInitialTableEntries) {} + static constexpr size_t MaxEntrySize() { return 65535; } + // Reserve space in table for the new element, evict entries if needed. // Return the new index of the element. Return 0 to indicate not adding to // table. diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.cc index 29be85c5cb..7c8fc3aeb5 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.cc @@ -1076,11 +1076,7 @@ class HPackParser::Parser { return HandleMetadataSizeLimitExceeded(md); } - grpc_error_handle err = metadata_buffer_->Set(md); - if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) { - input_->SetError(err); - return false; - } + metadata_buffer_->Set(md); return true; } @@ -1129,8 +1125,11 @@ class HPackParser::Parser { auto value_slice = value->Take<TakeValueType>(); const auto transport_size = key_string.size() + value_slice.size() + hpack_constants::kEntryOverhead; - return grpc_metadata_batch::Parse(key->string_view(), - std::move(value_slice), transport_size); + return grpc_metadata_batch::Parse( + key->string_view(), std::move(value_slice), transport_size, + [key_string](y_absl::string_view error, const Slice& value) { + ReportMetadataParseError(key_string, error, value.as_string_view()); + }); } // Parse an index encoded key and a string encoded value @@ -1143,7 +1142,11 @@ class HPackParser::Parser { } auto value = ParseValueString(elem->is_binary_header()); if (GPR_UNLIKELY(!value.has_value())) return {}; - return elem->WithNewValue(value->Take<TakeValueType>()); + return elem->WithNewValue(value->Take<TakeValueType>(), + [=](y_absl::string_view error, const Slice& value) { + ReportMetadataParseError( + elem->key(), error, value.as_string_view()); + }); } // Parse a varint index encoded key and a string encoded value @@ -1230,6 +1233,14 @@ class HPackParser::Parser { false); } + static void ReportMetadataParseError(y_absl::string_view key, + y_absl::string_view error, + y_absl::string_view value) { + gpr_log( + GPR_ERROR, "Error parsing metadata: %s", + y_absl::StrCat("error=", error, " key=", key, " value=", value).c_str()); + } + Input* const input_; grpc_metadata_batch* const metadata_buffer_; HPackTable* const table_; @@ -1356,25 +1367,6 @@ static void force_client_rst_stream(void* sp, grpc_error_handle /*error*/) { GRPC_CHTTP2_STREAM_UNREF(s, "final_rst"); } -static void parse_stream_compression_md(grpc_chttp2_transport* /*t*/, - grpc_chttp2_stream* s, - grpc_metadata_batch* initial_metadata) { - if (initial_metadata->legacy_index()->named.content_encoding == nullptr || - grpc_stream_compression_method_parse( - GRPC_MDVALUE( - initial_metadata->legacy_index()->named.content_encoding->md), - false, &s->stream_decompression_method) == 0) { - s->stream_decompression_method = - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS; - } - - if (s->stream_decompression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS) { - s->stream_decompression_ctx = nullptr; - grpc_slice_buffer_init(&s->decompressed_data_buffer); - } -} - grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser, grpc_chttp2_transport* t, grpc_chttp2_stream* s, @@ -1398,11 +1390,6 @@ grpc_error_handle grpc_chttp2_header_parser_parse(void* hpack_parser, return GRPC_ERROR_CREATE_FROM_STATIC_STRING( "Too many trailer frames"); } - /* Process stream compression md element if it exists */ - if (s->header_frames_received == - 0) { /* Only acts on initial metadata */ - parse_stream_compression_md(t, s, &s->initial_metadata_buffer); - } s->published_metadata[s->header_frames_received] = GRPC_METADATA_PUBLISHED_FROM_WIRE; maybe_complete_funcs[s->header_frames_received](t, s); diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.h index 88b5d52c41..2e52021014 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.h +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.h @@ -25,7 +25,6 @@ #include "src/core/ext/transport/chttp2/transport/frame.h" #include "src/core/ext/transport/chttp2/transport/hpack_parser_table.h" -#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata_batch.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc index 3aa8741b96..aac7435116 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc @@ -28,11 +28,11 @@ #include <grpc/support/alloc.h> #include <grpc/support/log.h> +#include "src/core/ext/transport/chttp2/transport/hpack_constants.h" #include "src/core/lib/debug/trace.h" #include "src/core/lib/gpr/murmur_hash.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/validate_metadata.h" -#include "src/core/lib/transport/static_metadata.h" extern grpc_core::TraceFlag grpc_http_trace; @@ -143,4 +143,97 @@ grpc_error_handle HPackTable::Add(Memento md) { return GRPC_ERROR_NONE; } +namespace { +struct StaticTableEntry { + const char* key; + const char* value; +}; + +const StaticTableEntry kStaticTable[hpack_constants::kLastStaticEntry] = { + {":authority", ""}, + {":method", "GET"}, + {":method", "POST"}, + {":path", "/"}, + {":path", "/index.html"}, + {":scheme", "http"}, + {":scheme", "https"}, + {":status", "200"}, + {":status", "204"}, + {":status", "206"}, + {":status", "304"}, + {":status", "400"}, + {":status", "404"}, + {":status", "500"}, + {"accept-charset", ""}, + {"accept-encoding", "gzip, deflate"}, + {"accept-language", ""}, + {"accept-ranges", ""}, + {"accept", ""}, + {"access-control-allow-origin", ""}, + {"age", ""}, + {"allow", ""}, + {"authorization", ""}, + {"cache-control", ""}, + {"content-disposition", ""}, + {"content-encoding", ""}, + {"content-language", ""}, + {"content-length", ""}, + {"content-location", ""}, + {"content-range", ""}, + {"content-type", ""}, + {"cookie", ""}, + {"date", ""}, + {"etag", ""}, + {"expect", ""}, + {"expires", ""}, + {"from", ""}, + {"host", ""}, + {"if-match", ""}, + {"if-modified-since", ""}, + {"if-none-match", ""}, + {"if-range", ""}, + {"if-unmodified-since", ""}, + {"last-modified", ""}, + {"link", ""}, + {"location", ""}, + {"max-forwards", ""}, + {"proxy-authenticate", ""}, + {"proxy-authorization", ""}, + {"range", ""}, + {"referer", ""}, + {"refresh", ""}, + {"retry-after", ""}, + {"server", ""}, + {"set-cookie", ""}, + {"strict-transport-security", ""}, + {"transfer-encoding", ""}, + {"user-agent", ""}, + {"vary", ""}, + {"via", ""}, + {"www-authenticate", ""}, +}; + +GPR_ATTRIBUTE_NOINLINE HPackTable::Memento MakeMemento(size_t i) { + auto sm = kStaticTable[i]; + return grpc_metadata_batch::Parse( + sm.key, Slice::FromStaticString(sm.value), + strlen(sm.key) + strlen(sm.value) + hpack_constants::kEntryOverhead, + [](y_absl::string_view, const Slice&) { + abort(); // not expecting to see this + }); +} + +} // namespace + +const HPackTable::StaticMementos& HPackTable::GetStaticMementos() { + static const StaticMementos static_mementos; + return static_mementos; +} + +HPackTable::StaticMementos::StaticMementos() { + for (uint32_t i = 0; i < hpack_constants::kLastStaticEntry; i++) { + memento[i] = MakeMemento(i); + } +} + } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.h index 3251b80327..c1ff236082 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.h @@ -26,9 +26,7 @@ #include "src/core/ext/transport/chttp2/transport/hpack_constants.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/iomgr/error.h" -#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/metadata_batch.h" -#include "src/core/lib/transport/static_metadata.h" namespace grpc_core { @@ -69,17 +67,10 @@ class HPackTable { private: struct StaticMementos { - StaticMementos() { - for (uint32_t i = 0; i < hpack_constants::kLastStaticEntry; i++) { - memento[i] = Memento(g_static_mdelem_manifested[i]); - } - } + StaticMementos(); Memento memento[hpack_constants::kLastStaticEntry]; }; - static const StaticMementos& GetStaticMementos() { - static const StaticMementos static_mementos; - return static_mementos; - } + static const StaticMementos& GetStaticMementos() GPR_ATTRIBUTE_NOINLINE; enum { kInlineEntries = hpack_constants::kInitialTableEntries }; using EntriesVec = y_absl::InlinedVector<Memento, kInlineEntries>; @@ -121,17 +112,4 @@ class HPackTable { } // namespace grpc_core -/* Returns the static hpack table index that corresponds to /a elem. Returns 0 - if /a elem is not statically stored or if it is not in the static hpack - table */ -inline uintptr_t grpc_chttp2_get_static_hpack_table_index(grpc_mdelem md) { - uintptr_t index = - reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(md)) - - grpc_core::g_static_mdelem_table; - if (index < grpc_core::hpack_constants::kLastStaticEntry) { - return index + 1; // Hpack static metadata element indices start at 1 - } - return 0; -} - #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSER_TABLE_H */ diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.cc deleted file mode 100644 index fb1d2cb21b..0000000000 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.cc +++ /dev/null @@ -1,46 +0,0 @@ -// 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 <grpc/support/port_platform.h> - -#include "src/core/ext/transport/chttp2/transport/hpack_utils.h" - -#include "src/core/lib/surface/validate_metadata.h" - -namespace grpc_core { - -namespace { -size_t Base64EncodedSize(size_t raw_length) { - static constexpr uint8_t tail_xtra[3] = {0, 2, 3}; - return raw_length / 3 * 4 + tail_xtra[raw_length % 3]; -} -} // namespace - -// Return the size occupied by some metadata in the HPACK table. -size_t MetadataSizeInHPackTable(grpc_mdelem elem, - bool use_true_binary_metadata) { - const uint8_t* key_buf = GRPC_SLICE_START_PTR(GRPC_MDKEY(elem)); - size_t key_len = GRPC_SLICE_LENGTH(GRPC_MDKEY(elem)); - size_t overhead_and_key = 32 + key_len; - size_t value_len = GRPC_SLICE_LENGTH(GRPC_MDVALUE(elem)); - if (grpc_key_is_binary_header(key_buf, key_len)) { - return overhead_and_key + (use_true_binary_metadata - ? value_len + 1 - : Base64EncodedSize(value_len)); - } else { - return overhead_and_key + value_len; - } -} - -} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h index dbf0576b31..7a9f2a914e 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h @@ -36,7 +36,6 @@ #include "src/core/ext/transport/chttp2/transport/hpack_parser.h" #include "src/core/ext/transport/chttp2/transport/stream_map.h" #include "src/core/lib/channel/channelz.h" -#include "src/core/lib/compression/stream_compression.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/iomgr/combiner.h" #include "src/core/lib/iomgr/endpoint.h" @@ -254,8 +253,6 @@ class Chttp2IncomingByteStream : public ByteStream { static void NextLocked(void* arg, grpc_error_handle error_ignored); static void OrphanLocked(void* arg, grpc_error_handle error_ignored); - void MaybeCreateStreamDecompressionCtx(); - grpc_chttp2_transport* transport_; // Immutable. grpc_chttp2_stream* stream_; // Immutable. @@ -523,8 +520,6 @@ struct grpc_chttp2_stream { explicit Reffer(grpc_chttp2_stream* s); } reffer; - grpc_core::MemoryAllocator::Reservation stream_reservation; - grpc_closure destroy_stream; grpc_closure* destroy_stream_arg; @@ -644,38 +639,10 @@ struct grpc_chttp2_stream { grpc_chttp2_write_cb* finish_after_write = nullptr; size_t sending_bytes = 0; - /* Stream compression method to be used. */ - grpc_stream_compression_method stream_compression_method = - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS; - /* Stream decompression method to be used. */ - grpc_stream_compression_method stream_decompression_method = - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS; - - /** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed - */ - bool unprocessed_incoming_frames_decompressed = false; /** Whether the bytes needs to be traced using Fathom */ bool traced = false; - /** gRPC header bytes that are already decompressed */ - size_t decompressed_header_bytes = 0; /** Byte counter for number of bytes written */ size_t byte_counter = 0; - - /** Amount of uncompressed bytes sent out when compressed_data_buffer is - * emptied */ - size_t uncompressed_data_size; - /** Stream compression compress context */ - grpc_stream_compression_context* stream_compression_ctx; - /** Buffer storing data that is compressed but not sent */ - grpc_slice_buffer compressed_data_buffer; - - /** Stream compression decompress context */ - grpc_stream_compression_context* stream_decompression_ctx; - /** Temporary buffer storing decompressed data. - * Initialized, used, and destroyed only when stream uses (non-identity) - * compression. - */ - grpc_slice_buffer decompressed_data_buffer; }; /** Transport writing call flow: diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc index 10cbbb59c8..356b78b206 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc @@ -31,7 +31,6 @@ #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_utils.h" #include "src/core/lib/transport/http2_errors.h" -#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/status_conversion.h" #include "src/core/lib/transport/timeout_encoding.h" @@ -306,11 +305,6 @@ static grpc_error_handle skip_parser(void* /*parser*/, return GRPC_ERROR_NONE; } -grpc_error_handle skip_header(grpc_mdelem md) { - GRPC_MDELEM_UNREF(md); - return GRPC_ERROR_NONE; -} - static HPackParser::Boundary hpack_boundary_type(grpc_chttp2_transport* t, bool is_eoh) { if (is_eoh) { diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/popularity_count.h b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/popularity_count.h deleted file mode 100644 index 3f4b4d11d8..0000000000 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/popularity_count.h +++ /dev/null @@ -1,60 +0,0 @@ -// 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_TRANSPORT_CHTTP2_TRANSPORT_POPULARITY_COUNT_H -#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_POPULARITY_COUNT_H - -#include <grpc/support/port_platform.h> - -namespace grpc_core { - -// filter tables for elems: this tables provides an approximate -// popularity count for particular hashes, and are used to determine whether -// a new literal should be added to the compression table or not. -// They track a single integer that counts how often a particular value has -// been seen. When that count reaches max (255), all values are halved. */ -template <uint8_t kElems> -class PopularityCount { - public: - PopularityCount() : sum_{0}, elems_{} {} - - // increment a filter count, halve all counts if one element reaches max - // return true if this element seems to be popular, false otherwise - bool AddElement(uint8_t idx) { - elems_[idx]++; - if (GPR_LIKELY(elems_[idx] < 255)) { - sum_++; - } else { - HalveFilter(); - } - return elems_[idx] >= 2 * sum_ / kElems; - } - - private: - // halve all counts because an element reached max - void HalveFilter() { - sum_ = 0; - for (int i = 0; i < kElems; i++) { - elems_[i] /= 2; - sum_ += elems_[i]; - } - } - - uint32_t sum_; - uint8_t elems_[kElems]; -}; - -} // namespace grpc_core - -#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_POPULARITY_COUNT_H */ diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc index bd8f555aee..0b974af882 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc +++ b/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc @@ -25,7 +25,6 @@ #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h" #include "src/core/ext/transport/chttp2/transport/context_list.h" #include "src/core/ext/transport/chttp2/transport/internal.h" -#include "src/core/lib/compression/stream_compression.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/slice/slice_internal.h" @@ -164,16 +163,10 @@ static void report_stall(grpc_chttp2_transport* t, grpc_chttp2_stream* s, "%s:%p stream %d moved to stalled list by %s. This is FULLY expected " "to happen in a healthy program that is not seeing flow control stalls." " However, if you know that there are unwanted stalls, here is some " - "helpful data: [fc:pending=%" PRIdPTR ":pending-compressed=%" PRIdPTR - ":flowed=%" PRId64 ":peer_initwin=%d:t_win=%" PRId64 - ":s_win=%d:s_delta=%" PRId64 "]", + "helpful data: [fc:pending=%" PRIdPTR ":flowed=%" PRId64 + ":peer_initwin=%d:t_win=%" PRId64 ":s_win=%d:s_delta=%" PRId64 "]", t->peer_string.c_str(), t, s->id, staller, - s->flow_controlled_buffer.length, - s->stream_compression_method == - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS - ? 0 - : s->compressed_data_buffer.length, - s->flow_controlled_bytes_flowed, + s->flow_controlled_buffer.length, s->flow_controlled_bytes_flowed, t->settings[GRPC_ACKED_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], t->flow_control->remote_window(), @@ -192,10 +185,30 @@ static uint32_t target_write_size(grpc_chttp2_transport* /*t*/) { return 1024 * 1024; } +namespace { + +class CountDefaultMetadataEncoder { + public: + size_t count() const { return count_; } + + void Encode(const grpc_core::Slice&, const grpc_core::Slice&) {} + + template <typename Which> + void Encode(Which, const typename Which::ValueType&) { + count_++; + } + + private: + size_t count_ = 0; +}; + +} // namespace + // Returns true if initial_metadata contains only default headers. static bool is_default_initial_metadata(grpc_metadata_batch* initial_metadata) { - return initial_metadata->default_count() == - initial_metadata->non_deadline_count(); + CountDefaultMetadataEncoder enc; + initial_metadata->Encode(&enc); + return enc.count() == initial_metadata->count(); } namespace { @@ -344,7 +357,7 @@ class DataSendContext { bool AnyOutgoing() const { return max_outgoing() > 0; } - void FlushUncompressedBytes() { + void FlushBytes() { uint32_t send_bytes = static_cast<uint32_t>( std::min(size_t(max_outgoing()), s_->flow_controlled_buffer.length)); is_last_frame_ = send_bytes == s_->flow_controlled_buffer.length && @@ -357,60 +370,6 @@ class DataSendContext { s_->sending_bytes += send_bytes; } - void FlushCompressedBytes() { - GPR_DEBUG_ASSERT(s_->stream_compression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS); - - uint32_t send_bytes = static_cast<uint32_t>( - std::min(size_t(max_outgoing()), s_->compressed_data_buffer.length)); - bool is_last_data_frame = - (send_bytes == s_->compressed_data_buffer.length && - s_->flow_controlled_buffer.length == 0 && - s_->fetching_send_message == nullptr); - if (is_last_data_frame && s_->send_trailing_metadata != nullptr && - s_->stream_compression_ctx != nullptr) { - if (GPR_UNLIKELY(!grpc_stream_compress( - s_->stream_compression_ctx, &s_->flow_controlled_buffer, - &s_->compressed_data_buffer, nullptr, MAX_SIZE_T, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH))) { - gpr_log(GPR_ERROR, "Stream compression failed."); - } - grpc_stream_compression_context_destroy(s_->stream_compression_ctx); - s_->stream_compression_ctx = nullptr; - /* After finish, bytes in s->compressed_data_buffer may be - * more than max_outgoing. Start another round of the current - * while loop so that send_bytes and is_last_data_frame are - * recalculated. */ - return; - } - is_last_frame_ = is_last_data_frame && - s_->send_trailing_metadata != nullptr && - s_->send_trailing_metadata->empty(); - grpc_chttp2_encode_data(s_->id, &s_->compressed_data_buffer, send_bytes, - is_last_frame_, &s_->stats.outgoing, &t_->outbuf); - s_->flow_control->SentData(send_bytes); - if (s_->compressed_data_buffer.length == 0) { - s_->sending_bytes += s_->uncompressed_data_size; - } - } - - void CompressMoreBytes() { - GPR_DEBUG_ASSERT(s_->stream_compression_method != - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS); - - if (s_->stream_compression_ctx == nullptr) { - s_->stream_compression_ctx = - grpc_stream_compression_context_create(s_->stream_compression_method); - } - s_->uncompressed_data_size = s_->flow_controlled_buffer.length; - if (GPR_UNLIKELY(!grpc_stream_compress( - s_->stream_compression_ctx, &s_->flow_controlled_buffer, - &s_->compressed_data_buffer, nullptr, MAX_SIZE_T, - GRPC_STREAM_COMPRESSION_FLUSH_SYNC))) { - gpr_log(GPR_ERROR, "Stream compression failed."); - } - } - bool is_last_frame() const { return is_last_frame_; } void CallCallbacks() { @@ -455,7 +414,6 @@ class StreamWriteContext { // https://github.com/grpc/proposal/blob/master/A6-client-retries.md#when-retries-are-valid if (!t_->is_client && s_->fetching_send_message == nullptr && s_->flow_controlled_buffer.length == 0 && - compressed_data_buffer_len() == 0 && s_->send_trailing_metadata != nullptr && is_default_initial_metadata(s_->send_initial_metadata)) { ConvertInitialMetadataToTrailingMetadata(); @@ -486,13 +444,6 @@ class StreamWriteContext { "send_initial_metadata_finished"); } - size_t compressed_data_buffer_len() { - return s_->stream_compression_method == - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS - ? 0 - : s_->compressed_data_buffer.length; - } - void FlushWindowUpdates() { /* send any window updates */ const uint32_t stream_announce = s_->flow_control->MaybeSendUpdate(); @@ -508,8 +459,7 @@ class StreamWriteContext { void FlushData() { if (!s_->sent_initial_metadata) return; - if (s_->flow_controlled_buffer.length == 0 && - compressed_data_buffer_len() == 0) { + if (s_->flow_controlled_buffer.length == 0) { return; // early out: nothing to do } @@ -526,22 +476,9 @@ class StreamWriteContext { return; // early out: nothing to do } - if (s_->stream_compression_method == - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS) { - while (s_->flow_controlled_buffer.length > 0 && - data_send_context.max_outgoing() > 0) { - data_send_context.FlushUncompressedBytes(); - } - } else { - while ((s_->flow_controlled_buffer.length > 0 || - s_->compressed_data_buffer.length > 0) && - data_send_context.max_outgoing() > 0) { - if (s_->compressed_data_buffer.length > 0) { - data_send_context.FlushCompressedBytes(); - } else { - data_send_context.CompressMoreBytes(); - } - } + while (s_->flow_controlled_buffer.length > 0 && + data_send_context.max_outgoing() > 0) { + data_send_context.FlushBytes(); } grpc_chttp2_reset_ping_clock(t_); if (data_send_context.is_last_frame()) { @@ -549,8 +486,7 @@ class StreamWriteContext { } data_send_context.CallCallbacks(); stream_became_writable_ = true; - if (s_->flow_controlled_buffer.length > 0 || - compressed_data_buffer_len() > 0) { + if (s_->flow_controlled_buffer.length > 0) { GRPC_CHTTP2_STREAM_REF(s_, "chttp2_writing:fork"); grpc_chttp2_list_add_writable_stream(t_, s_); } @@ -563,13 +499,20 @@ class StreamWriteContext { if (s_->send_trailing_metadata == nullptr) return; if (s_->fetching_send_message != nullptr) return; if (s_->flow_controlled_buffer.length != 0) return; - if (compressed_data_buffer_len() != 0) return; GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata")); if (s_->send_trailing_metadata->empty()) { grpc_chttp2_encode_data(s_->id, &s_->flow_controlled_buffer, 0, true, &s_->stats.outgoing, &t_->outbuf); } else { + if (send_status_.has_value()) { + s_->send_trailing_metadata->Set(grpc_core::HttpStatusMetadata(), + *send_status_); + } + if (send_content_type_.has_value()) { + s_->send_trailing_metadata->Set(grpc_core::ContentTypeMetadata(), + *send_content_type_); + } t_->hpack_compressor.EncodeHeaders( grpc_core::HPackCompressor::EncodeHeaderOptions{ s_->id, true, @@ -580,12 +523,7 @@ class StreamWriteContext { t_->settings[GRPC_PEER_SETTINGS] [GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE], &s_->stats.outgoing}, - grpc_core::ConcatMetadata( - grpc_core::MetadataArray( - extra_headers_for_trailing_metadata_, - num_extra_headers_for_trailing_metadata_), - *s_->send_trailing_metadata), - &t_->outbuf); + *s_->send_trailing_metadata, &t_->outbuf); } write_context_->IncTrailingMetadataWrites(); grpc_chttp2_reset_ping_clock(t_); @@ -605,18 +543,10 @@ class StreamWriteContext { gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)")); // When sending Trailers-Only, we need to move the :status and // content-type headers to the trailers. - if (s_->send_initial_metadata->legacy_index()->named.status != nullptr) { - extra_headers_for_trailing_metadata_ - [num_extra_headers_for_trailing_metadata_++] = - &s_->send_initial_metadata->legacy_index()->named.status->md; - } - if (s_->send_initial_metadata->legacy_index()->named.content_type != - nullptr) { - extra_headers_for_trailing_metadata_ - [num_extra_headers_for_trailing_metadata_++] = - &s_->send_initial_metadata->legacy_index() - ->named.content_type->md; - } + send_status_ = + s_->send_initial_metadata->get(grpc_core::HttpStatusMetadata()); + send_content_type_ = + s_->send_initial_metadata->get(grpc_core::ContentTypeMetadata()); } void SentLastFrame() { @@ -641,8 +571,9 @@ class StreamWriteContext { grpc_chttp2_transport* const t_; grpc_chttp2_stream* const s_; bool stream_became_writable_ = false; - grpc_mdelem* extra_headers_for_trailing_metadata_[2]; - size_t num_extra_headers_for_trailing_metadata_ = 0; + y_absl::optional<uint32_t> send_status_; + y_absl::optional<grpc_core::ContentTypeMetadata::ValueType> send_content_type_ = + {}; }; } // namespace diff --git a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_plugin.cc b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_plugin.cc index 8e251fa2d8..34de19aecc 100644 --- a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_plugin.cc +++ b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_plugin.cc @@ -22,7 +22,3 @@ #include "src/core/lib/debug/trace.h" grpc_core::TraceFlag grpc_inproc_trace(false, "inproc"); - -void grpc_inproc_plugin_init(void) { grpc_inproc_transport_init(); } - -void grpc_inproc_plugin_shutdown(void) { grpc_inproc_transport_shutdown(); } diff --git a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc index 144c630c8b..0a29ac5dfb 100644 --- a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc +++ b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc @@ -46,12 +46,6 @@ } while (0) namespace { -grpc_slice g_empty_slice; -grpc_slice g_fake_path_key; -grpc_slice g_fake_path_value; -grpc_slice g_fake_auth_key; -grpc_slice g_fake_auth_value; - struct inproc_stream; bool cancel_stream_locked(inproc_stream* s, grpc_error_handle error); void maybe_process_ops_locked(inproc_stream* s, grpc_error_handle error); @@ -280,13 +274,10 @@ struct inproc_stream { void log_metadata(const grpc_metadata_batch* md_batch, bool is_client, bool is_initial) { - md_batch->ForEach([=](grpc_mdelem md) { - char* key = grpc_slice_to_c_string(GRPC_MDKEY(md)); - char* value = grpc_slice_to_c_string(GRPC_MDVALUE(md)); - gpr_log(GPR_INFO, "INPROC:%s:%s: %s: %s", is_initial ? "HDR" : "TRL", - is_client ? "CLI" : "SVR", key, value); - gpr_free(key); - gpr_free(value); + TString prefix = y_absl::StrCat( + "INPROC:", is_initial ? "HDR:" : "TRL:", is_client ? "CLI:" : "SVR:"); + md_batch->Log([&prefix](y_absl::string_view key, y_absl::string_view value) { + gpr_log(GPR_INFO, "%s", y_absl::StrCat(prefix, key, ": ", value).c_str()); }); } @@ -296,19 +287,9 @@ class CopySink { public: explicit CopySink(grpc_metadata_batch* dst) : dst_(dst) {} - void Encode(grpc_mdelem md) { - // Differently to grpc_metadata_batch_copy, we always copy slices here so - // that we don't need to deal with the plethora of edge cases in that world. - // TODO(ctiller): revisit this when deleting mdelem. - md = grpc_mdelem_from_slices(grpc_slice_intern(GRPC_MDKEY(md)), - grpc_slice_copy(GRPC_MDVALUE(md))); - // Error unused in non-debug builds. - grpc_error_handle GRPC_UNUSED error = dst_->Append(md); - // The only way that Append() can fail is if - // there's a duplicate entry for a callout. However, that can't be - // the case here, because we would not have been allowed to create - // a source batch that had that kind of conflict. - GPR_DEBUG_ASSERT(error == GRPC_ERROR_NONE); + void Encode(const grpc_core::Slice& key, const grpc_core::Slice& value) { + dst_->Append(key.as_string_view(), value.AsOwned(), + [](y_absl::string_view, const grpc_core::Slice&) {}); } template <class T, class V> @@ -462,14 +443,10 @@ void fail_helper_locked(inproc_stream* s, grpc_error_handle error) { // If this is a server, provide initial metadata with a path and authority // since it expects that as well as no error yet grpc_metadata_batch fake_md(s->arena); - grpc_linked_mdelem* path_md = - static_cast<grpc_linked_mdelem*>(s->arena->Alloc(sizeof(*path_md))); - path_md->md = grpc_mdelem_from_slices(g_fake_path_key, g_fake_path_value); - GPR_ASSERT(fake_md.LinkTail(path_md) == GRPC_ERROR_NONE); - grpc_linked_mdelem* auth_md = - static_cast<grpc_linked_mdelem*>(s->arena->Alloc(sizeof(*auth_md))); - auth_md->md = grpc_mdelem_from_slices(g_fake_auth_key, g_fake_auth_value); - GPR_ASSERT(fake_md.LinkTail(auth_md) == GRPC_ERROR_NONE); + fake_md.Set(grpc_core::HttpPathMetadata(), + grpc_core::Slice::FromStaticString("/")); + fake_md.Set(grpc_core::HttpAuthorityMetadata(), + grpc_core::Slice::FromStaticString("inproc-fail")); (void)fill_in_metadata( s, &fake_md, 0, @@ -1260,26 +1237,6 @@ void inproc_transports_create(grpc_transport** server_transport, } } // namespace -/******************************************************************************* - * GLOBAL INIT AND DESTROY - */ -void grpc_inproc_transport_init(void) { - grpc_core::ExecCtx exec_ctx; - g_empty_slice = grpc_core::ExternallyManagedSlice(); - - grpc_slice key_tmp = grpc_slice_from_static_string(":path"); - g_fake_path_key = grpc_slice_intern(key_tmp); - grpc_slice_unref_internal(key_tmp); - - g_fake_path_value = grpc_slice_from_static_string("/"); - - grpc_slice auth_tmp = grpc_slice_from_static_string(":authority"); - g_fake_auth_key = grpc_slice_intern(auth_tmp); - grpc_slice_unref_internal(auth_tmp); - - g_fake_auth_value = grpc_slice_from_static_string("inproc-fail"); -} - grpc_channel* grpc_inproc_channel_create(grpc_server* server, const grpc_channel_args* args, void* /*reserved*/) { @@ -1358,12 +1315,3 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server, return channel; } - -void grpc_inproc_transport_shutdown(void) { - grpc_core::ExecCtx exec_ctx; - grpc_slice_unref_internal(g_empty_slice); - grpc_slice_unref_internal(g_fake_path_key); - grpc_slice_unref_internal(g_fake_path_value); - grpc_slice_unref_internal(g_fake_auth_key); - grpc_slice_unref_internal(g_fake_auth_value); -} diff --git a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.h b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.h index 7a5b3bb627..0ff22ffa59 100644 --- a/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.h +++ b/contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.h @@ -29,7 +29,4 @@ grpc_channel* grpc_inproc_channel_create(grpc_server* server, extern grpc_core::TraceFlag grpc_inproc_trace; -void grpc_inproc_transport_init(void); -void grpc_inproc_transport_shutdown(void); - #endif /* GRPC_CORE_EXT_TRANSPORT_INPROC_INPROC_TRANSPORT_H */ diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c new file mode 100644 index 0000000000..a3a4568693 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c @@ -0,0 +1,61 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/rbac/v3/rbac.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include <stddef.h> +#include "upb/msg_internal.h" +#include "envoy/extensions/filters/http/rbac/v3/rbac.upb.h" +#include "envoy/config/rbac/v3/rbac.upb.h" +#include "udpa/annotations/status.upb.h" +#include "udpa/annotations/versioning.upb.h" + +#include "upb/port_def.inc" + +static const upb_msglayout_sub envoy_extensions_filters_http_rbac_v3_RBAC_submsgs[1] = { + {.submsg = &envoy_config_rbac_v3_RBAC_msginit}, +}; + +static const upb_msglayout_field envoy_extensions_filters_http_rbac_v3_RBAC__fields[3] = { + {1, UPB_SIZE(12, 24), 1, 0, 11, _UPB_MODE_SCALAR | (_UPB_REP_PTR << _UPB_REP_SHIFT)}, + {2, UPB_SIZE(16, 32), 2, 0, 11, _UPB_MODE_SCALAR | (_UPB_REP_PTR << _UPB_REP_SHIFT)}, + {3, UPB_SIZE(4, 8), 0, 0, 9, _UPB_MODE_SCALAR | (_UPB_REP_STRVIEW << _UPB_REP_SHIFT)}, +}; + +const upb_msglayout envoy_extensions_filters_http_rbac_v3_RBAC_msginit = { + &envoy_extensions_filters_http_rbac_v3_RBAC_submsgs[0], + &envoy_extensions_filters_http_rbac_v3_RBAC__fields[0], + UPB_SIZE(24, 48), 3, _UPB_MSGEXT_NONE, 3, 255, +}; + +static const upb_msglayout_sub envoy_extensions_filters_http_rbac_v3_RBACPerRoute_submsgs[1] = { + {.submsg = &envoy_extensions_filters_http_rbac_v3_RBAC_msginit}, +}; + +static const upb_msglayout_field envoy_extensions_filters_http_rbac_v3_RBACPerRoute__fields[1] = { + {2, UPB_SIZE(4, 8), 1, 0, 11, _UPB_MODE_SCALAR | (_UPB_REP_PTR << _UPB_REP_SHIFT)}, +}; + +const upb_msglayout envoy_extensions_filters_http_rbac_v3_RBACPerRoute_msginit = { + &envoy_extensions_filters_http_rbac_v3_RBACPerRoute_submsgs[0], + &envoy_extensions_filters_http_rbac_v3_RBACPerRoute__fields[0], + UPB_SIZE(8, 16), 1, _UPB_MSGEXT_NONE, 0, 255, +}; + +static const upb_msglayout *messages_layout[2] = { + &envoy_extensions_filters_http_rbac_v3_RBAC_msginit, + &envoy_extensions_filters_http_rbac_v3_RBACPerRoute_msginit, +}; + +const upb_msglayout_file envoy_extensions_filters_http_rbac_v3_rbac_proto_upb_file_layout = { + messages_layout, + NULL, + 2, + 0, +}; + +#include "upb/port_undef.inc" + diff --git a/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h new file mode 100644 index 0000000000..7aad918ddf --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h @@ -0,0 +1,146 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/rbac/v3/rbac.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_FILTERS_HTTP_RBAC_V3_RBAC_PROTO_UPB_H_ +#define ENVOY_EXTENSIONS_FILTERS_HTTP_RBAC_V3_RBAC_PROTO_UPB_H_ + +#include "upb/msg_internal.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_rbac_v3_RBAC; +struct envoy_extensions_filters_http_rbac_v3_RBACPerRoute; +typedef struct envoy_extensions_filters_http_rbac_v3_RBAC envoy_extensions_filters_http_rbac_v3_RBAC; +typedef struct envoy_extensions_filters_http_rbac_v3_RBACPerRoute envoy_extensions_filters_http_rbac_v3_RBACPerRoute; +extern const upb_msglayout envoy_extensions_filters_http_rbac_v3_RBAC_msginit; +extern const upb_msglayout envoy_extensions_filters_http_rbac_v3_RBACPerRoute_msginit; +struct envoy_config_rbac_v3_RBAC; +extern const upb_msglayout envoy_config_rbac_v3_RBAC_msginit; + + +/* envoy.extensions.filters.http.rbac.v3.RBAC */ + +UPB_INLINE envoy_extensions_filters_http_rbac_v3_RBAC *envoy_extensions_filters_http_rbac_v3_RBAC_new(upb_arena *arena) { + return (envoy_extensions_filters_http_rbac_v3_RBAC *)_upb_msg_new(&envoy_extensions_filters_http_rbac_v3_RBAC_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_http_rbac_v3_RBAC *envoy_extensions_filters_http_rbac_v3_RBAC_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_http_rbac_v3_RBAC *ret = envoy_extensions_filters_http_rbac_v3_RBAC_new(arena); + if (!ret) return NULL; + if (!upb_decode(buf, size, ret, &envoy_extensions_filters_http_rbac_v3_RBAC_msginit, arena)) return NULL; + return ret; +} +UPB_INLINE envoy_extensions_filters_http_rbac_v3_RBAC *envoy_extensions_filters_http_rbac_v3_RBAC_parse_ex(const char *buf, size_t size, + const upb_extreg *extreg, int options, + upb_arena *arena) { + envoy_extensions_filters_http_rbac_v3_RBAC *ret = envoy_extensions_filters_http_rbac_v3_RBAC_new(arena); + if (!ret) return NULL; + if (!_upb_decode(buf, size, ret, &envoy_extensions_filters_http_rbac_v3_RBAC_msginit, extreg, options, arena)) { + return NULL; + } + return ret; +} +UPB_INLINE char *envoy_extensions_filters_http_rbac_v3_RBAC_serialize(const envoy_extensions_filters_http_rbac_v3_RBAC *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_http_rbac_v3_RBAC_msginit, arena, len); +} + +UPB_INLINE bool envoy_extensions_filters_http_rbac_v3_RBAC_has_rules(const envoy_extensions_filters_http_rbac_v3_RBAC *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const struct envoy_config_rbac_v3_RBAC* envoy_extensions_filters_http_rbac_v3_RBAC_rules(const envoy_extensions_filters_http_rbac_v3_RBAC *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), const struct envoy_config_rbac_v3_RBAC*); } +UPB_INLINE bool envoy_extensions_filters_http_rbac_v3_RBAC_has_shadow_rules(const envoy_extensions_filters_http_rbac_v3_RBAC *msg) { return _upb_hasbit(msg, 2); } +UPB_INLINE const struct envoy_config_rbac_v3_RBAC* envoy_extensions_filters_http_rbac_v3_RBAC_shadow_rules(const envoy_extensions_filters_http_rbac_v3_RBAC *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(16, 32), const struct envoy_config_rbac_v3_RBAC*); } +UPB_INLINE upb_strview envoy_extensions_filters_http_rbac_v3_RBAC_shadow_rules_stat_prefix(const envoy_extensions_filters_http_rbac_v3_RBAC *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview); } + +UPB_INLINE void envoy_extensions_filters_http_rbac_v3_RBAC_set_rules(envoy_extensions_filters_http_rbac_v3_RBAC *msg, struct envoy_config_rbac_v3_RBAC* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(12, 24), struct envoy_config_rbac_v3_RBAC*) = value; +} +UPB_INLINE struct envoy_config_rbac_v3_RBAC* envoy_extensions_filters_http_rbac_v3_RBAC_mutable_rules(envoy_extensions_filters_http_rbac_v3_RBAC *msg, upb_arena *arena) { + struct envoy_config_rbac_v3_RBAC* sub = (struct envoy_config_rbac_v3_RBAC*)envoy_extensions_filters_http_rbac_v3_RBAC_rules(msg); + if (sub == NULL) { + sub = (struct envoy_config_rbac_v3_RBAC*)_upb_msg_new(&envoy_config_rbac_v3_RBAC_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_rbac_v3_RBAC_set_rules(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_rbac_v3_RBAC_set_shadow_rules(envoy_extensions_filters_http_rbac_v3_RBAC *msg, struct envoy_config_rbac_v3_RBAC* value) { + _upb_sethas(msg, 2); + *UPB_PTR_AT(msg, UPB_SIZE(16, 32), struct envoy_config_rbac_v3_RBAC*) = value; +} +UPB_INLINE struct envoy_config_rbac_v3_RBAC* envoy_extensions_filters_http_rbac_v3_RBAC_mutable_shadow_rules(envoy_extensions_filters_http_rbac_v3_RBAC *msg, upb_arena *arena) { + struct envoy_config_rbac_v3_RBAC* sub = (struct envoy_config_rbac_v3_RBAC*)envoy_extensions_filters_http_rbac_v3_RBAC_shadow_rules(msg); + if (sub == NULL) { + sub = (struct envoy_config_rbac_v3_RBAC*)_upb_msg_new(&envoy_config_rbac_v3_RBAC_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_rbac_v3_RBAC_set_shadow_rules(msg, sub); + } + return sub; +} +UPB_INLINE void envoy_extensions_filters_http_rbac_v3_RBAC_set_shadow_rules_stat_prefix(envoy_extensions_filters_http_rbac_v3_RBAC *msg, upb_strview value) { + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_strview) = value; +} + +/* envoy.extensions.filters.http.rbac.v3.RBACPerRoute */ + +UPB_INLINE envoy_extensions_filters_http_rbac_v3_RBACPerRoute *envoy_extensions_filters_http_rbac_v3_RBACPerRoute_new(upb_arena *arena) { + return (envoy_extensions_filters_http_rbac_v3_RBACPerRoute *)_upb_msg_new(&envoy_extensions_filters_http_rbac_v3_RBACPerRoute_msginit, arena); +} +UPB_INLINE envoy_extensions_filters_http_rbac_v3_RBACPerRoute *envoy_extensions_filters_http_rbac_v3_RBACPerRoute_parse(const char *buf, size_t size, + upb_arena *arena) { + envoy_extensions_filters_http_rbac_v3_RBACPerRoute *ret = envoy_extensions_filters_http_rbac_v3_RBACPerRoute_new(arena); + if (!ret) return NULL; + if (!upb_decode(buf, size, ret, &envoy_extensions_filters_http_rbac_v3_RBACPerRoute_msginit, arena)) return NULL; + return ret; +} +UPB_INLINE envoy_extensions_filters_http_rbac_v3_RBACPerRoute *envoy_extensions_filters_http_rbac_v3_RBACPerRoute_parse_ex(const char *buf, size_t size, + const upb_extreg *extreg, int options, + upb_arena *arena) { + envoy_extensions_filters_http_rbac_v3_RBACPerRoute *ret = envoy_extensions_filters_http_rbac_v3_RBACPerRoute_new(arena); + if (!ret) return NULL; + if (!_upb_decode(buf, size, ret, &envoy_extensions_filters_http_rbac_v3_RBACPerRoute_msginit, extreg, options, arena)) { + return NULL; + } + return ret; +} +UPB_INLINE char *envoy_extensions_filters_http_rbac_v3_RBACPerRoute_serialize(const envoy_extensions_filters_http_rbac_v3_RBACPerRoute *msg, upb_arena *arena, size_t *len) { + return upb_encode(msg, &envoy_extensions_filters_http_rbac_v3_RBACPerRoute_msginit, arena, len); +} + +UPB_INLINE bool envoy_extensions_filters_http_rbac_v3_RBACPerRoute_has_rbac(const envoy_extensions_filters_http_rbac_v3_RBACPerRoute *msg) { return _upb_hasbit(msg, 1); } +UPB_INLINE const envoy_extensions_filters_http_rbac_v3_RBAC* envoy_extensions_filters_http_rbac_v3_RBACPerRoute_rbac(const envoy_extensions_filters_http_rbac_v3_RBACPerRoute *msg) { return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const envoy_extensions_filters_http_rbac_v3_RBAC*); } + +UPB_INLINE void envoy_extensions_filters_http_rbac_v3_RBACPerRoute_set_rbac(envoy_extensions_filters_http_rbac_v3_RBACPerRoute *msg, envoy_extensions_filters_http_rbac_v3_RBAC* value) { + _upb_sethas(msg, 1); + *UPB_PTR_AT(msg, UPB_SIZE(4, 8), envoy_extensions_filters_http_rbac_v3_RBAC*) = value; +} +UPB_INLINE struct envoy_extensions_filters_http_rbac_v3_RBAC* envoy_extensions_filters_http_rbac_v3_RBACPerRoute_mutable_rbac(envoy_extensions_filters_http_rbac_v3_RBACPerRoute *msg, upb_arena *arena) { + struct envoy_extensions_filters_http_rbac_v3_RBAC* sub = (struct envoy_extensions_filters_http_rbac_v3_RBAC*)envoy_extensions_filters_http_rbac_v3_RBACPerRoute_rbac(msg); + if (sub == NULL) { + sub = (struct envoy_extensions_filters_http_rbac_v3_RBAC*)_upb_msg_new(&envoy_extensions_filters_http_rbac_v3_RBAC_msginit, arena); + if (!sub) return NULL; + envoy_extensions_filters_http_rbac_v3_RBACPerRoute_set_rbac(msg, sub); + } + return sub; +} + +extern const upb_msglayout_file envoy_extensions_filters_http_rbac_v3_rbac_proto_upb_file_layout; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_FILTERS_HTTP_RBAC_V3_RBAC_PROTO_UPB_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c new file mode 100644 index 0000000000..772df657df --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c @@ -0,0 +1,188 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/rbac/v3/rbac.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/config/rbac/v3/rbac.upbdefs.h" +#include "envoy/config/rbac/v3/rbac.upb.h" + +extern upb_def_init envoy_config_core_v3_address_proto_upbdefinit; +extern upb_def_init envoy_config_core_v3_extension_proto_upbdefinit; +extern upb_def_init envoy_config_route_v3_route_components_proto_upbdefinit; +extern upb_def_init envoy_type_matcher_v3_metadata_proto_upbdefinit; +extern upb_def_init envoy_type_matcher_v3_path_proto_upbdefinit; +extern upb_def_init envoy_type_matcher_v3_string_proto_upbdefinit; +extern upb_def_init envoy_type_v3_range_proto_upbdefinit; +extern upb_def_init google_api_expr_v1alpha1_checked_proto_upbdefinit; +extern upb_def_init google_api_expr_v1alpha1_syntax_proto_upbdefinit; +extern upb_def_init envoy_annotations_deprecation_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 upb_def_init validate_validate_proto_upbdefinit; +static const char descriptor[3378] = {'\n', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', 'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', '/', 'r', 'b', +'a', 'c', '.', 'p', 'r', 'o', 't', 'o', '\022', '\024', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', +'a', 'c', '.', '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', '/', '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', '/', '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', '$', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'm', +'e', 't', 'a', 'd', 'a', 't', 'a', '.', 'p', 'r', 'o', 't', 'o', '\032', ' ', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', +'/', 'm', 'a', 't', 'c', 'h', 'e', 'r', '/', 'v', '3', '/', 'p', 'a', 't', 'h', '.', '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', 'e', 'n', 'v', 'o', 'y', '/', 't', 'y', 'p', 'e', '/', 'v', '3', '/', 'r', +'a', 'n', 'g', 'e', '.', 'p', 'r', 'o', 't', 'o', '\032', '&', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', +'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 'c', 'h', 'e', 'c', 'k', 'e', 'd', '.', 'p', 'r', 'o', 't', 'o', +'\032', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '/', 's', 'y', 'n', 't', 'a', 'x', '.', 'p', 'r', 'o', 't', 'o', '\032', '#', 'e', 'n', 'v', 'o', 'y', '/', 'a', 'n', 'n', +'o', 't', 'a', 't', 'i', 'o', 'n', 's', '/', 'd', 'e', 'p', 'r', 'e', 'c', 'a', 't', 'i', 'o', 'n', '.', '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', '\032', +'\027', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '/', 'v', 'a', 'l', 'i', 'd', 'a', 't', 'e', '.', 'p', 'r', 'o', 't', 'o', '\"', +'\266', '\002', '\n', '\004', 'R', 'B', 'A', 'C', '\022', 'C', '\n', '\006', 'a', 'c', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\016', '2', +'!', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', +'A', 'C', '.', 'A', 'c', 't', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\202', '\001', '\002', '\020', '\001', 'R', '\006', 'a', 'c', 't', 'i', +'o', 'n', '\022', 'D', '\n', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '(', '.', 'e', 'n', +'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', '.', 'P', +'o', 'l', 'i', 'c', 'i', 'e', 's', 'E', 'n', 't', 'r', 'y', 'R', '\010', 'p', 'o', 'l', 'i', 'c', 'i', 'e', 's', '\032', 'Y', '\n', +'\r', 'P', 'o', 'l', 'i', 'c', 'i', 'e', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', +'(', '\t', 'R', '\003', 'k', 'e', 'y', '\022', '2', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\034', '.', +'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'o', 'l', 'i', +'c', 'y', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '&', '\n', '\006', 'A', 'c', 't', 'i', 'o', 'n', '\022', '\t', +'\n', '\005', 'A', 'L', 'L', 'O', 'W', '\020', '\000', '\022', '\010', '\n', '\004', 'D', 'E', 'N', 'Y', '\020', '\001', '\022', '\007', '\n', '\003', 'L', 'O', +'G', '\020', '\002', ':', ' ', '\232', '\305', '\210', '\036', '\033', '\n', '\031', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'R', 'B', 'A', 'C', '\"', '\223', '\003', '\n', '\006', 'P', 'o', 'l', 'i', 'c', 'y', '\022', 'L', +'\n', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', +'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', +'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\013', 'p', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', +'s', '\022', 'I', '\n', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', +'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', +'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', '\001', 'R', '\n', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', +'s', '\022', 'Z', '\n', '\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', +'p', 'r', 'B', '\034', '\362', '\230', '\376', '\217', '\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', 's', 'i', 'o', 'n', '_', 's', 'p', +'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R', '\t', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', 'p', '\n', '\021', 'c', 'h', 'e', +'c', 'k', 'e', 'd', '_', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\004', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'h', +'e', 'c', 'k', 'e', 'd', 'E', 'x', 'p', 'r', 'B', '\034', '\362', '\230', '\376', '\217', '\005', '\026', '\022', '\024', 'e', 'x', 'p', 'r', 'e', 's', +'s', 'i', 'o', 'n', '_', 's', 'p', 'e', 'c', 'i', 'f', 'i', 'e', 'r', 'R', '\020', 'c', 'h', 'e', 'c', 'k', 'e', 'd', 'C', 'o', +'n', 'd', 'i', 't', 'i', 'o', 'n', ':', '\"', '\232', '\305', '\210', '\036', '\035', '\n', '\033', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', +'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'o', 'l', 'i', 'c', 'y', '\"', '\332', '\007', '\n', '\n', 'P', 'e', +'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '\022', 'C', '\n', '\t', 'a', 'n', 'd', '_', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\001', +'(', '\013', '2', '$', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', +'.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\010', 'a', 'n', 'd', 'R', 'u', 'l', +'e', 's', '\022', 'A', '\n', '\010', 'o', 'r', '_', 'r', 'u', 'l', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '$', '.', 'e', 'n', +'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', +'s', 'i', 'o', 'n', '.', 'S', 'e', 't', 'H', '\000', 'R', '\007', 'o', 'r', 'R', 'u', 'l', 'e', 's', '\022', '\033', '\n', '\003', 'a', 'n', +'y', '\030', '\003', ' ', '\001', '(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', 'y', '\022', '>', +'\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\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', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', 'r', 'l', '_', 'p', 'a', 't', 'h', '\030', +'\n', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', +'r', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', +'t', 'h', '\022', 'H', '\n', '\016', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'i', 'p', '\030', '\005', ' ', '\001', '(', +'\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', +'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\r', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', 'I', +'p', '\022', '6', '\n', '\020', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', 'r', 't', '\030', '\006', ' ', '\001', +'(', '\r', 'B', '\t', '\372', 'B', '\006', '*', '\004', '\030', '\377', '\377', '\003', 'H', '\000', 'R', '\017', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', +'i', 'o', 'n', 'P', 'o', 'r', 't', '\022', 'Q', '\n', '\026', 'd', 'e', 's', 't', 'i', 'n', 'a', 't', 'i', 'o', 'n', '_', 'p', 'o', +'r', 't', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\013', ' ', '\001', '(', '\013', '2', '\031', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', +'p', 'e', '.', 'v', '3', '.', 'I', 'n', 't', '3', '2', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\024', 'd', 'e', 's', 't', 'i', +'n', 'a', 't', 'i', 'o', 'n', 'P', 'o', 'r', 't', 'R', 'a', 'n', 'g', 'e', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', +'t', 'a', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', +'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', +'R', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\022', '=', '\n', '\010', 'n', 'o', 't', '_', 'r', 'u', 'l', 'e', '\030', '\010', ' ', +'\001', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', +'3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'H', '\000', 'R', '\007', 'n', 'o', 't', 'R', 'u', 'l', 'e', '\022', 'Z', +'\n', '\025', 'r', 'e', 'q', 'u', 'e', 's', 't', 'e', 'd', '_', 's', 'e', 'r', 'v', 'e', 'r', '_', 'n', 'a', 'm', 'e', '\030', '\t', +' ', '\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', 'H', '\000', 'R', '\023', 'r', 'e', 'q', 'u', +'e', 's', 't', 'e', 'd', 'S', 'e', 'r', 'v', 'e', 'r', 'N', 'a', 'm', 'e', '\022', 'F', '\n', '\007', 'm', 'a', 't', 'c', 'h', 'e', +'r', '\030', '\014', ' ', '\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', 'H', '\000', 'R', '\007', 'm', 'a', 't', 'c', 'h', 'e', 'r', '\032', 's', '\n', '\003', 'S', 'e', 't', '\022', '@', '\n', '\005', 'r', 'u', +'l', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', ' ', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\010', '\372', 'B', '\005', '\222', '\001', +'\002', '\010', '\001', 'R', '\005', 'r', 'u', 'l', 'e', 's', ':', '*', '\232', '\305', '\210', '\036', '%', '\n', '#', 'e', 'n', 'v', 'o', 'y', '.', +'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', +'.', 'S', 'e', 't', ':', '&', '\232', '\305', '\210', '\036', '!', '\n', '\037', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', +'.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'B', '\013', '\n', '\004', 'r', 'u', +'l', 'e', '\022', '\003', '\370', 'B', '\001', '\"', '\233', '\010', '\n', '\t', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '\022', '>', '\n', '\007', +'a', 'n', 'd', '_', 'i', 'd', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', +'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', +'H', '\000', 'R', '\006', 'a', 'n', 'd', 'I', 'd', 's', '\022', '<', '\n', '\006', 'o', 'r', '_', 'i', 'd', 's', '\030', '\002', ' ', '\001', '(', +'\013', '2', '#', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', +'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', 'H', '\000', 'R', '\005', 'o', 'r', 'I', 'd', 's', '\022', '\033', '\n', +'\003', 'a', 'n', 'y', '\030', '\003', ' ', '\001', '(', '\010', 'B', '\007', '\372', 'B', '\004', 'j', '\002', '\010', '\001', 'H', '\000', 'R', '\003', 'a', 'n', +'y', '\022', 'U', '\n', '\r', 'a', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\030', '\004', ' ', '\001', '(', '\013', '2', +'-', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', +'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'H', '\000', 'R', '\r', +'a', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\t', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', +'p', '\030', '\005', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', +'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'B', '\013', '\030', '\001', '\222', '\307', '\206', '\330', '\004', '\003', +'3', '.', '0', 'H', '\000', 'R', '\010', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'p', '\022', 'K', '\n', '\020', 'd', 'i', 'r', 'e', 'c', 't', +'_', 'r', 'e', 'm', 'o', 't', 'e', '_', 'i', 'p', '\030', '\n', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', +'c', 'o', 'n', 'f', 'i', 'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', +'\000', 'R', '\016', 'd', 'i', 'r', 'e', 'c', 't', 'R', 'e', 'm', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\t', 'r', 'e', 'm', 'o', +'t', 'e', '_', 'i', 'p', '\030', '\013', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', +'g', '.', 'c', 'o', 'r', 'e', '.', 'v', '3', '.', 'C', 'i', 'd', 'r', 'R', 'a', 'n', 'g', 'e', 'H', '\000', 'R', '\010', 'r', 'e', +'m', 'o', 't', 'e', 'I', 'p', '\022', '>', '\n', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\030', '\006', ' ', '\001', '(', '\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', 'H', '\000', 'R', '\006', 'h', 'e', 'a', 'd', 'e', 'r', '\022', '?', '\n', '\010', 'u', +'r', 'l', '_', 'p', 'a', 't', 'h', '\030', '\t', ' ', '\001', '(', '\013', '2', '\"', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', +'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', 'v', '3', '.', 'P', 'a', 't', 'h', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', +'\000', 'R', '\007', 'u', 'r', 'l', 'P', 'a', 't', 'h', '\022', 'D', '\n', '\010', 'm', 'e', 't', 'a', 'd', 'a', 't', 'a', '\030', '\007', ' ', +'\001', '(', '\013', '2', '&', '.', 'e', 'n', 'v', 'o', 'y', '.', 't', 'y', 'p', 'e', '.', 'm', 'a', 't', 'c', 'h', 'e', 'r', '.', +'v', '3', '.', 'M', 'e', 't', 'a', 'd', 'a', 't', 'a', 'M', 'a', 't', 'c', 'h', 'e', 'r', 'H', '\000', 'R', '\010', 'm', 'e', 't', +'a', 'd', 'a', 't', 'a', '\022', '8', '\n', '\006', 'n', 'o', 't', '_', 'i', 'd', '\030', '\010', ' ', '\001', '(', '\013', '2', '\037', '.', 'e', +'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', +'i', 'p', 'a', 'l', 'H', '\000', 'R', '\005', 'n', 'o', 't', 'I', 'd', '\032', 'm', '\n', '\003', 'S', 'e', 't', '\022', ';', '\n', '\003', 'i', +'d', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\037', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', +'b', 'a', 'c', '.', 'v', '3', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\010', '\372', 'B', '\005', '\222', '\001', '\002', '\010', +'\001', 'R', '\003', 'i', 'd', 's', ':', ')', '\232', '\305', '\210', '\036', '$', '\n', '\"', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', +'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'S', 'e', 't', '\032', +'\227', '\001', '\n', '\r', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', '\022', 'K', '\n', '\016', 'p', 'r', 'i', 'n', +'c', 'i', 'p', 'a', 'l', '_', 'n', 'a', 'm', 'e', '\030', '\002', ' ', '\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', '\r', 'p', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'N', 'a', 'm', 'e', ':', '3', '\232', '\305', '\210', '\036', +'.', '\n', ',', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', +'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', '.', 'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'a', 't', 'e', 'd', 'J', '\004', '\010', +'\001', '\020', '\002', ':', '%', '\232', '\305', '\210', '\036', ' ', '\n', '\036', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', +'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'P', 'r', 'i', 'n', 'c', 'i', 'p', 'a', 'l', 'B', '\021', '\n', '\n', 'i', 'd', 'e', 'n', +'t', 'i', 'f', 'i', 'e', 'r', '\022', '\003', '\370', 'B', '\001', 'B', '9', '\n', '\"', 'i', 'o', '.', 'e', 'n', 'v', 'o', 'y', 'p', 'r', +'o', 'x', 'y', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', 'B', +'\t', 'R', 'b', 'a', 'c', '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[15] = { + &envoy_config_core_v3_address_proto_upbdefinit, + &envoy_config_core_v3_extension_proto_upbdefinit, + &envoy_config_route_v3_route_components_proto_upbdefinit, + &envoy_type_matcher_v3_metadata_proto_upbdefinit, + &envoy_type_matcher_v3_path_proto_upbdefinit, + &envoy_type_matcher_v3_string_proto_upbdefinit, + &envoy_type_v3_range_proto_upbdefinit, + &google_api_expr_v1alpha1_checked_proto_upbdefinit, + &google_api_expr_v1alpha1_syntax_proto_upbdefinit, + &envoy_annotations_deprecation_proto_upbdefinit, + &udpa_annotations_migrate_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + &validate_validate_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_config_rbac_v3_rbac_proto_upbdefinit = { + deps, + &envoy_config_rbac_v3_rbac_proto_upb_file_layout, + "envoy/config/rbac/v3/rbac.proto", + UPB_STRVIEW_INIT(descriptor, 3378) +}; diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h new file mode 100644 index 0000000000..47efd41e21 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h @@ -0,0 +1,70 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/config/rbac/v3/rbac.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_CONFIG_RBAC_V3_RBAC_PROTO_UPBDEFS_H_ +#define ENVOY_CONFIG_RBAC_V3_RBAC_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_rbac_v3_rbac_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_RBAC_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.RBAC"); +} + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_RBAC_PoliciesEntry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.RBAC.PoliciesEntry"); +} + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_Policy_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.Policy"); +} + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_Permission_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.Permission"); +} + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_Permission_Set_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.Permission.Set"); +} + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_Principal_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.Principal"); +} + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_Principal_Set_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.Principal.Set"); +} + +UPB_INLINE const upb_msgdef *envoy_config_rbac_v3_Principal_Authenticated_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_config_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.config.rbac.v3.Principal.Authenticated"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_CONFIG_RBAC_V3_RBAC_PROTO_UPBDEFS_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c new file mode 100644 index 0000000000..7d17eaa836 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c @@ -0,0 +1,56 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/rbac/v3/rbac.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.h" +#include "envoy/extensions/filters/http/rbac/v3/rbac.upb.h" + +extern upb_def_init envoy_config_rbac_v3_rbac_proto_upbdefinit; +extern upb_def_init udpa_annotations_status_proto_upbdefinit; +extern upb_def_init udpa_annotations_versioning_proto_upbdefinit; +static const char descriptor[639] = {'\n', '0', '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', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', '/', 'r', 'b', 'a', 'c', '.', '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', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '\032', '\037', 'e', 'n', 'v', 'o', 'y', '/', 'c', 'o', 'n', +'f', 'i', 'g', '/', 'r', 'b', 'a', 'c', '/', 'v', '3', '/', 'r', 'b', 'a', 'c', '.', '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', '\"', '\336', '\001', '\n', '\004', 'R', 'B', 'A', 'C', '\022', '0', '\n', +'\005', 'r', 'u', 'l', 'e', 's', '\030', '\001', ' ', '\001', '(', '\013', '2', '\032', '.', 'e', 'n', 'v', 'o', 'y', '.', 'c', 'o', 'n', 'f', +'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', 'R', '\005', 'r', 'u', 'l', 'e', 's', '\022', '=', '\n', +'\014', 's', 'h', 'a', 'd', 'o', 'w', '_', 'r', 'u', 'l', 'e', 's', '\030', '\002', ' ', '\001', '(', '\013', '2', '\032', '.', 'e', 'n', 'v', +'o', 'y', '.', 'c', 'o', 'n', 'f', 'i', 'g', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', 'R', '\013', 's', +'h', 'a', 'd', 'o', 'w', 'R', 'u', 'l', 'e', 's', '\022', '7', '\n', '\030', 's', 'h', 'a', 'd', 'o', 'w', '_', 'r', 'u', 'l', 'e', +'s', '_', 's', 't', 'a', 't', '_', 'p', 'r', 'e', 'f', 'i', 'x', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\025', 's', 'h', 'a', 'd', +'o', 'w', 'R', 'u', 'l', 'e', 's', 'S', 't', 'a', 't', 'P', 'r', 'e', 'f', 'i', 'x', ':', ',', '\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', +'.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'R', 'B', 'A', 'C', '\"', '\213', '\001', '\n', '\014', 'R', 'B', 'A', 'C', 'P', 'e', 'r', +'R', 'o', 'u', 't', 'e', '\022', '?', '\n', '\004', 'r', 'b', 'a', 'c', '\030', '\002', ' ', '\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', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', '.', 'R', 'B', 'A', 'C', 'R', '\004', 'r', 'b', 'a', 'c', ':', '4', '\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', '.', 'r', 'b', 'a', 'c', '.', 'v', '2', '.', 'R', 'B', 'A', 'C', 'P', 'e', 'r', 'R', 'o', 'u', 't', 'e', 'J', +'\004', '\010', '\001', '\020', '\002', 'B', 'J', '\n', '3', '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', '.', 'r', 'b', 'a', 'c', '.', 'v', '3', 'B', '\t', 'R', 'b', 'a', 'c', '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[4] = { + &envoy_config_rbac_v3_rbac_proto_upbdefinit, + &udpa_annotations_status_proto_upbdefinit, + &udpa_annotations_versioning_proto_upbdefinit, + NULL +}; + +upb_def_init envoy_extensions_filters_http_rbac_v3_rbac_proto_upbdefinit = { + deps, + &envoy_extensions_filters_http_rbac_v3_rbac_proto_upb_file_layout, + "envoy/extensions/filters/http/rbac/v3/rbac.proto", + UPB_STRVIEW_INIT(descriptor, 639) +}; diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.h new file mode 100644 index 0000000000..afd1a89d76 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.h @@ -0,0 +1,40 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * envoy/extensions/filters/http/rbac/v3/rbac.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef ENVOY_EXTENSIONS_FILTERS_HTTP_RBAC_V3_RBAC_PROTO_UPBDEFS_H_ +#define ENVOY_EXTENSIONS_FILTERS_HTTP_RBAC_V3_RBAC_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_rbac_v3_rbac_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_http_rbac_v3_RBAC_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_http_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.http.rbac.v3.RBAC"); +} + +UPB_INLINE const upb_msgdef *envoy_extensions_filters_http_rbac_v3_RBACPerRoute_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &envoy_extensions_filters_http_rbac_v3_rbac_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "envoy.extensions.filters.http.rbac.v3.RBACPerRoute"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* ENVOY_EXTENSIONS_FILTERS_HTTP_RBAC_V3_RBAC_PROTO_UPBDEFS_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.c new file mode 100644 index 0000000000..3ff985637c --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.c @@ -0,0 +1,154 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/checked.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "google/api/expr/v1alpha1/checked.upbdefs.h" +#include "google/api/expr/v1alpha1/checked.upb.h" + +extern upb_def_init google_api_expr_v1alpha1_syntax_proto_upbdefinit; +extern upb_def_init google_protobuf_empty_proto_upbdefinit; +extern upb_def_init google_protobuf_struct_proto_upbdefinit; +static const char descriptor[3089] = {'\n', '&', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '/', 'c', 'h', 'e', 'c', 'k', 'e', 'd', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', +'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '\032', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', +'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 's', 'y', 'n', 't', 'a', 'x', '.', +'p', 'r', 'o', 't', 'o', '\032', '\033', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '/', 'e', 'm', +'p', 't', 'y', '.', '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', '\"', '\367', '\003', '\n', '\013', 'C', 'h', 'e', 'c', 'k', 'e', +'d', 'E', 'x', 'p', 'r', '\022', '\\', '\n', '\r', 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', '_', 'm', 'a', 'p', '\030', '\002', ' ', +'\003', '(', '\013', '2', '7', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', +'l', 'p', 'h', 'a', '1', '.', 'C', 'h', 'e', 'c', 'k', 'e', 'd', 'E', 'x', 'p', 'r', '.', 'R', 'e', 'f', 'e', 'r', 'e', 'n', +'c', 'e', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y', 'R', '\014', 'r', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', 'M', 'a', 'p', '\022', +'M', '\n', '\010', 't', 'y', 'p', 'e', '_', 'm', 'a', 'p', '\030', '\003', ' ', '\003', '(', '\013', '2', '2', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'h', 'e', 'c', 'k', +'e', 'd', 'E', 'x', 'p', 'r', '.', 'T', 'y', 'p', 'e', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y', 'R', '\007', 't', 'y', 'p', 'e', +'M', 'a', 'p', '\022', 'E', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\005', ' ', '\001', '(', '\013', '2', +'$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '\022', +'2', '\n', '\004', 'e', 'x', 'p', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\004', 'e', 'x', 'p', +'r', '\032', 'd', '\n', '\021', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', +'\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '9', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', +'\002', ' ', '\001', '(', '\013', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', +'1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', +'\002', '8', '\001', '\032', 'Z', '\n', '\014', 'T', 'y', 'p', 'e', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', +'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '4', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', +'(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', +'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', '\"', '\310', '\013', '\n', '\004', +'T', 'y', 'p', 'e', '\022', '*', '\n', '\003', 'd', 'y', 'n', '\030', '\001', ' ', '\001', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'E', 'm', 'p', 't', 'y', 'H', '\000', 'R', '\003', 'd', 'y', 'n', '\022', '0', +'\n', '\004', 'n', 'u', 'l', 'l', '\030', '\002', ' ', '\001', '(', '\016', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\004', 'n', 'u', 'l', 'l', '\022', 'L', +'\n', '\t', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', '\030', '\003', ' ', '\001', '(', '\016', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', +'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\t', 'p', 'r', 'i', 'm', 'i', 't', 'i', 'v', +'e', '\022', 'H', '\n', '\007', 'w', 'r', 'a', 'p', 'p', 'e', 'r', '\030', '\004', ' ', '\001', '(', '\016', '2', ',', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', +'.', 'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\007', 'w', 'r', 'a', 'p', 'p', 'e', 'r', +'\022', 'M', '\n', '\n', 'w', 'e', 'l', 'l', '_', 'k', 'n', 'o', 'w', 'n', '\030', '\005', ' ', '\001', '(', '\016', '2', ',', '.', 'g', 'o', +'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', +'p', 'e', '.', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\t', 'w', 'e', 'l', 'l', 'K', +'n', 'o', 'w', 'n', '\022', 'F', '\n', '\t', 'l', 'i', 's', 't', '_', 't', 'y', 'p', 'e', '\030', '\006', ' ', '\001', '(', '\013', '2', '\'', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', +'.', 'T', 'y', 'p', 'e', '.', 'L', 'i', 's', 't', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\010', 'l', 'i', 's', 't', 'T', 'y', 'p', +'e', '\022', 'C', '\n', '\010', 'm', 'a', 'p', '_', 't', 'y', 'p', 'e', '\030', '\007', ' ', '\001', '(', '\013', '2', '&', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', +'e', '.', 'M', 'a', 'p', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\007', 'm', 'a', 'p', 'T', 'y', 'p', 'e', '\022', 'I', '\n', '\010', 'f', +'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\010', ' ', '\001', '(', '\013', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'F', 'u', 'n', 'c', +'t', 'i', 'o', 'n', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\022', '#', '\n', '\014', 'm', +'e', 's', 's', 'a', 'g', 'e', '_', 't', 'y', 'p', 'e', '\030', '\t', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\013', 'm', 'e', 's', 's', +'a', 'g', 'e', 'T', 'y', 'p', 'e', '\022', '\037', '\n', '\n', 't', 'y', 'p', 'e', '_', 'p', 'a', 'r', 'a', 'm', '\030', '\n', ' ', '\001', +'(', '\t', 'H', '\000', 'R', '\t', 't', 'y', 'p', 'e', 'P', 'a', 'r', 'a', 'm', '\022', '4', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\013', +' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', +'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\004', 't', 'y', 'p', 'e', '\022', '.', '\n', '\005', 'e', 'r', +'r', 'o', 'r', '\030', '\014', ' ', '\001', '(', '\013', '2', '\026', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', +'u', 'f', '.', 'E', 'm', 'p', 't', 'y', 'H', '\000', 'R', '\005', 'e', 'r', 'r', 'o', 'r', '\022', 'R', '\n', '\r', 'a', 'b', 's', 't', +'r', 'a', 'c', 't', '_', 't', 'y', 'p', 'e', '\030', '\016', ' ', '\001', '(', '\013', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', '.', 'A', 'b', +'s', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', 'e', 'H', '\000', 'R', '\014', 'a', 'b', 's', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', +'e', '\032', 'G', '\n', '\010', 'L', 'i', 's', 't', 'T', 'y', 'p', 'e', '\022', ';', '\n', '\t', 'e', 'l', 'e', 'm', '_', 't', 'y', 'p', +'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', +'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\010', 'e', 'l', 'e', 'm', 'T', 'y', 'p', 'e', '\032', +'\203', '\001', '\n', '\007', 'M', 'a', 'p', 'T', 'y', 'p', 'e', '\022', '9', '\n', '\010', 'k', 'e', 'y', '_', 't', 'y', 'p', 'e', '\030', '\001', +' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', +'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\007', 'k', 'e', 'y', 'T', 'y', 'p', 'e', '\022', '=', '\n', '\n', 'v', +'a', 'l', 'u', 'e', '_', 't', 'y', 'p', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\t', 'v', +'a', 'l', 'u', 'e', 'T', 'y', 'p', 'e', '\032', '\214', '\001', '\n', '\014', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'T', 'y', 'p', 'e', +'\022', '?', '\n', '\013', 'r', 'e', 's', 'u', 'l', 't', '_', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', +'y', 'p', 'e', 'R', '\n', 'r', 'e', 's', 'u', 'l', 't', 'T', 'y', 'p', 'e', '\022', ';', '\n', '\t', 'a', 'r', 'g', '_', 't', 'y', +'p', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', +'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\010', 'a', 'r', 'g', 'T', 'y', 'p', 'e', +'s', '\032', 'k', '\n', '\014', 'A', 'b', 's', 't', 'r', 'a', 'c', 't', 'T', 'y', 'p', 'e', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', +'\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', 'G', '\n', '\017', 'p', 'a', 'r', 'a', 'm', 'e', 't', 'e', 'r', +'_', 't', 'y', 'p', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', +'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\016', 'p', 'a', 'r', 'a', +'m', 'e', 't', 'e', 'r', 'T', 'y', 'p', 'e', 's', '\"', 's', '\n', '\r', 'P', 'r', 'i', 'm', 'i', 't', 'i', 'v', 'e', 'T', 'y', +'p', 'e', '\022', '\036', '\n', '\032', 'P', 'R', 'I', 'M', 'I', 'T', 'I', 'V', 'E', '_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'S', 'P', +'E', 'C', 'I', 'F', 'I', 'E', 'D', '\020', '\000', '\022', '\010', '\n', '\004', 'B', 'O', 'O', 'L', '\020', '\001', '\022', '\t', '\n', '\005', 'I', 'N', +'T', '6', '4', '\020', '\002', '\022', '\n', '\n', '\006', 'U', 'I', 'N', 'T', '6', '4', '\020', '\003', '\022', '\n', '\n', '\006', 'D', 'O', 'U', 'B', +'L', 'E', '\020', '\004', '\022', '\n', '\n', '\006', 'S', 'T', 'R', 'I', 'N', 'G', '\020', '\005', '\022', '\t', '\n', '\005', 'B', 'Y', 'T', 'E', 'S', +'\020', '\006', '\"', 'V', '\n', '\r', 'W', 'e', 'l', 'l', 'K', 'n', 'o', 'w', 'n', 'T', 'y', 'p', 'e', '\022', '\037', '\n', '\033', 'W', 'E', +'L', 'L', '_', 'K', 'N', 'O', 'W', 'N', '_', 'T', 'Y', 'P', 'E', '_', 'U', 'N', 'S', 'P', 'E', 'C', 'I', 'F', 'I', 'E', 'D', +'\020', '\000', '\022', '\007', '\n', '\003', 'A', 'N', 'Y', '\020', '\001', '\022', '\r', '\n', '\t', 'T', 'I', 'M', 'E', 'S', 'T', 'A', 'M', 'P', '\020', +'\002', '\022', '\014', '\n', '\010', 'D', 'U', 'R', 'A', 'T', 'I', 'O', 'N', '\020', '\003', 'B', '\013', '\n', '\t', 't', 'y', 'p', 'e', '_', 'k', +'i', 'n', 'd', '\"', '\263', '\005', '\n', '\004', 'D', 'e', 'c', 'l', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', +'\t', 'R', '\004', 'n', 'a', 'm', 'e', '\022', '@', '\n', '\005', 'i', 'd', 'e', 'n', 't', '\030', '\002', ' ', '\001', '(', '\013', '2', '(', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', +'D', 'e', 'c', 'l', '.', 'I', 'd', 'e', 'n', 't', 'D', 'e', 'c', 'l', 'H', '\000', 'R', '\005', 'i', 'd', 'e', 'n', 't', '\022', 'I', +'\n', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'D', 'e', 'c', 'l', '.', 'F', +'u', 'n', 'c', 't', 'i', 'o', 'n', 'D', 'e', 'c', 'l', 'H', '\000', 'R', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\032', '\213', +'\001', '\n', '\t', 'I', 'd', 'e', 'n', 't', 'D', 'e', 'c', 'l', '\022', '2', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', +'\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', +'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\004', 't', 'y', 'p', 'e', '\022', '8', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', +' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', +'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', '\020', '\n', +'\003', 'd', 'o', 'c', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\003', 'd', 'o', 'c', '\032', '\356', '\002', '\n', '\014', 'F', 'u', 'n', 'c', 't', +'i', 'o', 'n', 'D', 'e', 'c', 'l', '\022', 'R', '\n', '\t', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 's', '\030', '\001', ' ', '\003', '(', +'\013', '2', '4', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', +'h', 'a', '1', '.', 'D', 'e', 'c', 'l', '.', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', 'D', 'e', 'c', 'l', '.', 'O', 'v', 'e', +'r', 'l', 'o', 'a', 'd', 'R', '\t', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 's', '\032', '\211', '\002', '\n', '\010', 'O', 'v', 'e', 'r', +'l', 'o', 'a', 'd', '\022', '\037', '\n', '\013', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '_', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\t', +'R', '\n', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'I', 'd', '\022', '6', '\n', '\006', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\002', ' ', +'\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', +'l', 'p', 'h', 'a', '1', '.', 'T', 'y', 'p', 'e', 'R', '\006', 'p', 'a', 'r', 'a', 'm', 's', '\022', '\037', '\n', '\013', 't', 'y', 'p', +'e', '_', 'p', 'a', 'r', 'a', 'm', 's', '\030', '\003', ' ', '\003', '(', '\t', 'R', '\n', 't', 'y', 'p', 'e', 'P', 'a', 'r', 'a', 'm', +'s', '\022', '?', '\n', '\013', 'r', 'e', 's', 'u', 'l', 't', '_', 't', 'y', 'p', 'e', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', +'T', 'y', 'p', 'e', 'R', '\n', 'r', 'e', 's', 'u', 'l', 't', 'T', 'y', 'p', 'e', '\022', '0', '\n', '\024', 'i', 's', '_', 'i', 'n', +'s', 't', 'a', 'n', 'c', 'e', '_', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', '(', '\010', 'R', '\022', 'i', 's', +'I', 'n', 's', 't', 'a', 'n', 'c', 'e', 'F', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\022', '\020', '\n', '\003', 'd', 'o', 'c', '\030', '\006', +' ', '\001', '(', '\t', 'R', '\003', 'd', 'o', 'c', 'B', '\013', '\n', '\t', 'd', 'e', 'c', 'l', '_', 'k', 'i', 'n', 'd', '\"', 'z', '\n', +'\t', 'R', 'e', 'f', 'e', 'r', 'e', 'n', 'c', 'e', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', +'\004', 'n', 'a', 'm', 'e', '\022', '\037', '\n', '\013', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', '_', 'i', 'd', '\030', '\003', ' ', '\003', '(', +'\t', 'R', '\n', 'o', 'v', 'e', 'r', 'l', 'o', 'a', 'd', 'I', 'd', '\022', '8', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', +'\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', +'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', 'l', '\n', '\034', +'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', +'h', 'a', '1', 'B', '\t', 'D', 'e', 'c', 'l', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', +'e', 'a', 'p', 'i', 's', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', +'x', 'p', 'r', '\370', '\001', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[4] = { + &google_api_expr_v1alpha1_syntax_proto_upbdefinit, + &google_protobuf_empty_proto_upbdefinit, + &google_protobuf_struct_proto_upbdefinit, + NULL +}; + +upb_def_init google_api_expr_v1alpha1_checked_proto_upbdefinit = { + deps, + &google_api_expr_v1alpha1_checked_proto_upb_file_layout, + "google/api/expr/v1alpha1/checked.proto", + UPB_STRVIEW_INIT(descriptor, 3089) +}; diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.h new file mode 100644 index 0000000000..539e255c60 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.h @@ -0,0 +1,95 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/checked.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_API_EXPR_V1ALPHA1_CHECKED_PROTO_UPBDEFS_H_ +#define GOOGLE_API_EXPR_V1ALPHA1_CHECKED_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 google_api_expr_v1alpha1_checked_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_CheckedExpr_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.CheckedExpr"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_CheckedExpr_ReferenceMapEntry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.CheckedExpr.ReferenceMapEntry"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_CheckedExpr_TypeMapEntry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.CheckedExpr.TypeMapEntry"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Type_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Type"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Type_ListType_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Type.ListType"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Type_MapType_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Type.MapType"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Type_FunctionType_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Type.FunctionType"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Type_AbstractType_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Type.AbstractType"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Decl_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Decl"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Decl_IdentDecl_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Decl.IdentDecl"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Decl_FunctionDecl_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Decl.FunctionDecl"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Decl_FunctionDecl_Overload_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Decl.FunctionDecl.Overload"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Reference_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_checked_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Reference"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* GOOGLE_API_EXPR_V1ALPHA1_CHECKED_PROTO_UPBDEFS_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.c new file mode 100644 index 0000000000..71a31f0c66 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.c @@ -0,0 +1,58 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/eval.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "google/api/expr/v1alpha1/eval.upbdefs.h" +#include "google/api/expr/v1alpha1/eval.upb.h" + +extern upb_def_init google_api_expr_v1alpha1_value_proto_upbdefinit; +extern upb_def_init google_rpc_status_proto_upbdefinit; +static const char descriptor[738] = {'\n', '#', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '/', 'e', 'v', 'a', 'l', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', +'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '\032', '$', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', +'/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 'v', 'a', 'l', 'u', 'e', '.', 'p', 'r', 'o', 't', +'o', '\032', '\027', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'r', 'p', 'c', '/', 's', 't', 'a', 't', 'u', 's', '.', 'p', 'r', 'o', 't', +'o', '\"', '\302', '\001', '\n', '\t', 'E', 'v', 'a', 'l', 'S', 't', 'a', 't', 'e', '\022', ';', '\n', '\006', 'v', 'a', 'l', 'u', 'e', 's', +'\030', '\001', ' ', '\003', '(', '\013', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', +'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'V', 'a', 'l', 'u', 'e', 'R', '\006', 'v', 'a', 'l', 'u', 'e', +'s', '\022', 'D', '\n', '\007', 'r', 'e', 's', 'u', 'l', 't', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '*', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'v', 'a', 'l', +'S', 't', 'a', 't', 'e', '.', 'R', 'e', 's', 'u', 'l', 't', 'R', '\007', 'r', 'e', 's', 'u', 'l', 't', 's', '\032', '2', '\n', '\006', +'R', 'e', 's', 'u', 'l', 't', '\022', '\022', '\n', '\004', 'e', 'x', 'p', 'r', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\004', 'e', 'x', 'p', +'r', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\003', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\"', '\312', +'\001', '\n', '\t', 'E', 'x', 'p', 'r', 'V', 'a', 'l', 'u', 'e', '\022', '7', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', +'(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', +'p', 'h', 'a', '1', '.', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\022', ':', '\n', '\005', 'e', 'r', +'r', 'o', 'r', '\030', '\002', ' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', +'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'r', 'r', 'o', 'r', 'S', 'e', 't', 'H', '\000', 'R', '\005', 'e', +'r', 'r', 'o', 'r', '\022', '@', '\n', '\007', 'u', 'n', 'k', 'n', 'o', 'w', 'n', '\030', '\003', ' ', '\001', '(', '\013', '2', '$', '.', 'g', +'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'U', +'n', 'k', 'n', 'o', 'w', 'n', 'S', 'e', 't', 'H', '\000', 'R', '\007', 'u', 'n', 'k', 'n', 'o', 'w', 'n', 'B', '\006', '\n', '\004', 'k', +'i', 'n', 'd', '\"', '6', '\n', '\010', 'E', 'r', 'r', 'o', 'r', 'S', 'e', 't', '\022', '*', '\n', '\006', 'e', 'r', 'r', 'o', 'r', 's', +'\030', '\001', ' ', '\003', '(', '\013', '2', '\022', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'r', 'p', 'c', '.', 'S', 't', 'a', 't', 'u', +'s', 'R', '\006', 'e', 'r', 'r', 'o', 'r', 's', '\"', '\"', '\n', '\n', 'U', 'n', 'k', 'n', 'o', 'w', 'n', 'S', 'e', 't', '\022', '\024', +'\n', '\005', 'e', 'x', 'p', 'r', 's', '\030', '\001', ' ', '\003', '(', '\003', 'R', '\005', 'e', 'x', 'p', 'r', 's', 'B', 'l', '\n', '\034', 'c', +'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', +'a', '1', 'B', '\t', 'E', 'v', 'a', 'l', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', +'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', 'e', +'a', 'p', 'i', 's', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', 'x', +'p', 'r', '\370', '\001', '\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[3] = { + &google_api_expr_v1alpha1_value_proto_upbdefinit, + &google_rpc_status_proto_upbdefinit, + NULL +}; + +upb_def_init google_api_expr_v1alpha1_eval_proto_upbdefinit = { + deps, + &google_api_expr_v1alpha1_eval_proto_upb_file_layout, + "google/api/expr/v1alpha1/eval.proto", + UPB_STRVIEW_INIT(descriptor, 738) +}; diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.h new file mode 100644 index 0000000000..aba88bc8c2 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.h @@ -0,0 +1,55 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/eval.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_API_EXPR_V1ALPHA1_EVAL_PROTO_UPBDEFS_H_ +#define GOOGLE_API_EXPR_V1ALPHA1_EVAL_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 google_api_expr_v1alpha1_eval_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_EvalState_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_eval_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.EvalState"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_EvalState_Result_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_eval_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.EvalState.Result"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_ExprValue_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_eval_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.ExprValue"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_ErrorSet_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_eval_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.ErrorSet"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_UnknownSet_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_eval_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.UnknownSet"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* GOOGLE_API_EXPR_V1ALPHA1_EVAL_PROTO_UPBDEFS_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.c new file mode 100644 index 0000000000..9bb469f66c --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.c @@ -0,0 +1,44 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/explain.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "google/api/expr/v1alpha1/explain.upbdefs.h" +#include "google/api/expr/v1alpha1/explain.upb.h" + +extern upb_def_init google_api_expr_v1alpha1_value_proto_upbdefinit; +static const char descriptor[434] = {'\n', '&', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '/', 'e', 'x', 'p', 'l', 'a', 'i', 'n', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', +'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '\032', '$', 'g', 'o', 'o', 'g', 'l', 'e', '/', +'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '/', 'v', 'a', 'l', 'u', 'e', '.', 'p', +'r', 'o', 't', 'o', '\"', '\316', '\001', '\n', '\007', 'E', 'x', 'p', 'l', 'a', 'i', 'n', '\022', '7', '\n', '\006', 'v', 'a', 'l', 'u', 'e', +'s', '\030', '\001', ' ', '\003', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', +'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'V', 'a', 'l', 'u', 'e', 'R', '\006', 'v', 'a', 'l', 'u', 'e', 's', '\022', 'I', +'\n', '\n', 'e', 'x', 'p', 'r', '_', 's', 't', 'e', 'p', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '*', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'l', +'a', 'i', 'n', '.', 'E', 'x', 'p', 'r', 'S', 't', 'e', 'p', 'R', '\t', 'e', 'x', 'p', 'r', 'S', 't', 'e', 'p', 's', '\032', ';', +'\n', '\010', 'E', 'x', 'p', 'r', 'S', 't', 'e', 'p', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\002', 'i', +'d', '\022', '\037', '\n', '\013', 'v', 'a', 'l', 'u', 'e', '_', 'i', 'n', 'd', 'e', 'x', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\n', 'v', +'a', 'l', 'u', 'e', 'I', 'n', 'd', 'e', 'x', ':', '\002', '\030', '\001', 'B', 'o', '\n', '\034', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', 'B', '\014', 'E', 'x', 'p', +'l', 'a', 'i', 'n', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', +'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', 'e', 'a', 'p', 'i', 's', +'/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', 'x', 'p', 'r', '\370', '\001', +'\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[2] = { + &google_api_expr_v1alpha1_value_proto_upbdefinit, + NULL +}; + +upb_def_init google_api_expr_v1alpha1_explain_proto_upbdefinit = { + deps, + &google_api_expr_v1alpha1_explain_proto_upb_file_layout, + "google/api/expr/v1alpha1/explain.proto", + UPB_STRVIEW_INIT(descriptor, 434) +}; diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.h new file mode 100644 index 0000000000..e7c7c090c4 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.h @@ -0,0 +1,40 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/explain.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_API_EXPR_V1ALPHA1_EXPLAIN_PROTO_UPBDEFS_H_ +#define GOOGLE_API_EXPR_V1ALPHA1_EXPLAIN_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 google_api_expr_v1alpha1_explain_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Explain_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_explain_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Explain"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Explain_ExprStep_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_explain_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Explain.ExprStep"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* GOOGLE_API_EXPR_V1ALPHA1_EXPLAIN_PROTO_UPBDEFS_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.c new file mode 100644 index 0000000000..5219acb73d --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.c @@ -0,0 +1,153 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/syntax.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "google/api/expr/v1alpha1/syntax.upbdefs.h" +#include "google/api/expr/v1alpha1/syntax.upb.h" + +extern upb_def_init google_protobuf_duration_proto_upbdefinit; +extern upb_def_init google_protobuf_struct_proto_upbdefinit; +extern upb_def_init google_protobuf_timestamp_proto_upbdefinit; +static const char descriptor[3059] = {'\n', '%', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '/', 's', 'y', 'n', 't', 'a', 'x', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', +'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '\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', '\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', '\"', '\207', '\001', '\n', '\n', 'P', 'a', 'r', 's', 'e', 'd', 'E', 'x', 'p', 'r', +'\022', '2', '\n', '\004', 'e', 'x', 'p', 'r', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', +'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\004', 'e', 'x', +'p', 'r', '\022', 'E', '\n', '\013', 's', 'o', 'u', 'r', 'c', 'e', '_', 'i', 'n', 'f', 'o', '\030', '\003', ' ', '\001', '(', '\013', '2', '$', +'.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', +'.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', 'R', '\n', 's', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '\"', '\334', +'\014', '\n', '\004', 'E', 'x', 'p', 'r', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\002', ' ', '\001', '(', '\003', 'R', '\002', 'i', 'd', '\022', 'C', +'\n', '\n', 'c', 'o', 'n', 's', 't', '_', 'e', 'x', 'p', 'r', '\030', '\003', ' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'C', 'o', 'n', 's', +'t', 'a', 'n', 't', 'H', '\000', 'R', '\t', 'c', 'o', 'n', 's', 't', 'E', 'x', 'p', 'r', '\022', 'E', '\n', '\n', 'i', 'd', 'e', 'n', +'t', '_', 'e', 'x', 'p', 'r', '\030', '\004', ' ', '\001', '(', '\013', '2', '$', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', +'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'I', 'd', 'e', 'n', 't', +'H', '\000', 'R', '\t', 'i', 'd', 'e', 'n', 't', 'E', 'x', 'p', 'r', '\022', 'H', '\n', '\013', 's', 'e', 'l', 'e', 'c', 't', '_', 'e', +'x', 'p', 'r', '\030', '\005', ' ', '\001', '(', '\013', '2', '%', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', +'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'S', 'e', 'l', 'e', 'c', 't', 'H', '\000', +'R', '\n', 's', 'e', 'l', 'e', 'c', 't', 'E', 'x', 'p', 'r', '\022', 'B', '\n', '\t', 'c', 'a', 'l', 'l', '_', 'e', 'x', 'p', 'r', +'\030', '\006', ' ', '\001', '(', '\013', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', +'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'C', 'a', 'l', 'l', 'H', '\000', 'R', '\010', 'c', 'a', 'l', +'l', 'E', 'x', 'p', 'r', '\022', 'H', '\n', '\t', 'l', 'i', 's', 't', '_', 'e', 'x', 'p', 'r', '\030', '\007', ' ', '\001', '(', '\013', '2', +')', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '.', 'E', 'x', 'p', 'r', '.', 'C', 'r', 'e', 'a', 't', 'e', 'L', 'i', 's', 't', 'H', '\000', 'R', '\010', 'l', 'i', 's', 't', +'E', 'x', 'p', 'r', '\022', 'N', '\n', '\013', 's', 't', 'r', 'u', 'c', 't', '_', 'e', 'x', 'p', 'r', '\030', '\010', ' ', '\001', '(', '\013', +'2', '+', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', +'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'C', 'r', 'e', 'a', 't', 'e', 'S', 't', 'r', 'u', 'c', 't', 'H', '\000', 'R', '\n', 's', +'t', 'r', 'u', 'c', 't', 'E', 'x', 'p', 'r', '\022', ']', '\n', '\022', 'c', 'o', 'm', 'p', 'r', 'e', 'h', 'e', 'n', 's', 'i', 'o', +'n', '_', 'e', 'x', 'p', 'r', '\030', '\t', ' ', '\001', '(', '\013', '2', ',', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', +'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'C', 'o', 'm', 'p', 'r', +'e', 'h', 'e', 'n', 's', 'i', 'o', 'n', 'H', '\000', 'R', '\021', 'c', 'o', 'm', 'p', 'r', 'e', 'h', 'e', 'n', 's', 'i', 'o', 'n', +'E', 'x', 'p', 'r', '\032', '\033', '\n', '\005', 'I', 'd', 'e', 'n', 't', '\022', '\022', '\n', '\004', 'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', +'(', '\t', 'R', '\004', 'n', 'a', 'm', 'e', '\032', 'u', '\n', '\006', 'S', 'e', 'l', 'e', 'c', 't', '\022', '8', '\n', '\007', 'o', 'p', 'e', +'r', 'a', 'n', 'd', '\030', '\001', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', +'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\007', 'o', 'p', 'e', 'r', 'a', 'n', +'d', '\022', '\024', '\n', '\005', 'f', 'i', 'e', 'l', 'd', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\005', 'f', 'i', 'e', 'l', 'd', '\022', '\033', +'\n', '\t', 't', 'e', 's', 't', '_', 'o', 'n', 'l', 'y', '\030', '\003', ' ', '\001', '(', '\010', 'R', '\010', 't', 'e', 's', 't', 'O', 'n', +'l', 'y', '\032', '\216', '\001', '\n', '\004', 'C', 'a', 'l', 'l', '\022', '6', '\n', '\006', 't', 'a', 'r', 'g', 'e', 't', '\030', '\001', ' ', '\001', +'(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', +'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\006', 't', 'a', 'r', 'g', 'e', 't', '\022', '\032', '\n', '\010', 'f', 'u', 'n', 'c', +'t', 'i', 'o', 'n', '\030', '\002', ' ', '\001', '(', '\t', 'R', '\010', 'f', 'u', 'n', 'c', 't', 'i', 'o', 'n', '\022', '2', '\n', '\004', 'a', +'r', 'g', 's', '\030', '\003', ' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', +'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\004', 'a', 'r', 'g', 's', '\032', 'H', '\n', +'\n', 'C', 'r', 'e', 'a', 't', 'e', 'L', 'i', 's', 't', '\022', ':', '\n', '\010', 'e', 'l', 'e', 'm', 'e', 'n', 't', 's', '\030', '\001', +' ', '\003', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', +'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\010', 'e', 'l', 'e', 'm', 'e', 'n', 't', 's', '\032', '\264', '\002', '\n', +'\014', 'C', 'r', 'e', 'a', 't', 'e', 'S', 't', 'r', 'u', 'c', 't', '\022', '!', '\n', '\014', 'm', 'e', 's', 's', 'a', 'g', 'e', '_', +'n', 'a', 'm', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\013', 'm', 'e', 's', 's', 'a', 'g', 'e', 'N', 'a', 'm', 'e', '\022', 'K', +'\n', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\030', '\002', ' ', '\003', '(', '\013', '2', '1', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', +'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', '.', 'C', 'r', +'e', 'a', 't', 'e', 'S', 't', 'r', 'u', 'c', 't', '.', 'E', 'n', 't', 'r', 'y', 'R', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', +'\032', '\263', '\001', '\n', '\005', 'E', 'n', 't', 'r', 'y', '\022', '\016', '\n', '\002', 'i', 'd', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\002', 'i', +'d', '\022', '\035', '\n', '\t', 'f', 'i', 'e', 'l', 'd', '_', 'k', 'e', 'y', '\030', '\002', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\010', 'f', +'i', 'e', 'l', 'd', 'K', 'e', 'y', '\022', '9', '\n', '\007', 'm', 'a', 'p', '_', 'k', 'e', 'y', '\030', '\003', ' ', '\001', '(', '\013', '2', +'\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '.', 'E', 'x', 'p', 'r', 'H', '\000', 'R', '\006', 'm', 'a', 'p', 'K', 'e', 'y', '\022', '4', '\n', '\005', 'v', 'a', 'l', 'u', 'e', +'\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', +'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', '\n', '\n', '\010', 'k', +'e', 'y', '_', 'k', 'i', 'n', 'd', '\032', '\375', '\002', '\n', '\r', 'C', 'o', 'm', 'p', 'r', 'e', 'h', 'e', 'n', 's', 'i', 'o', 'n', +'\022', '\031', '\n', '\010', 'i', 't', 'e', 'r', '_', 'v', 'a', 'r', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\007', 'i', 't', 'e', 'r', 'V', +'a', 'r', '\022', '=', '\n', '\n', 'i', 't', 'e', 'r', '_', 'r', 'a', 'n', 'g', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', +'E', 'x', 'p', 'r', 'R', '\t', 'i', 't', 'e', 'r', 'R', 'a', 'n', 'g', 'e', '\022', '\031', '\n', '\010', 'a', 'c', 'c', 'u', '_', 'v', +'a', 'r', '\030', '\003', ' ', '\001', '(', '\t', 'R', '\007', 'a', 'c', 'c', 'u', 'V', 'a', 'r', '\022', ';', '\n', '\t', 'a', 'c', 'c', 'u', +'_', 'i', 'n', 'i', 't', '\030', '\004', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', +'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\010', 'a', 'c', 'c', 'u', 'I', +'n', 'i', 't', '\022', 'E', '\n', '\016', 'l', 'o', 'o', 'p', '_', 'c', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\030', '\005', ' ', '\001', +'(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', +'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\r', 'l', 'o', 'o', 'p', 'C', 'o', 'n', 'd', 'i', 't', 'i', 'o', 'n', '\022', +';', '\n', '\t', 'l', 'o', 'o', 'p', '_', 's', 't', 'e', 'p', '\030', '\006', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', +'R', '\010', 'l', 'o', 'o', 'p', 'S', 't', 'e', 'p', '\022', '6', '\n', '\006', 'r', 'e', 's', 'u', 'l', 't', '\030', '\007', ' ', '\001', '(', +'\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', +'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\006', 'r', 'e', 's', 'u', 'l', 't', 'B', '\013', '\n', '\t', 'e', 'x', 'p', 'r', '_', +'k', 'i', 'n', 'd', '\"', '\301', '\003', '\n', '\010', 'C', 'o', 'n', 's', 't', 'a', 'n', 't', '\022', ';', '\n', '\n', 'n', 'u', 'l', 'l', +'_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', '\016', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', +'t', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\t', 'n', 'u', 'l', 'l', 'V', 'a', +'l', 'u', 'e', '\022', '\037', '\n', '\n', 'b', 'o', 'o', 'l', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\010', 'H', '\000', +'R', '\t', 'b', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\013', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', +'e', '\030', '\003', ' ', '\001', '(', '\003', 'H', '\000', 'R', '\n', 'i', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', +'u', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\004', ' ', '\001', '(', '\004', 'H', '\000', 'R', '\013', 'u', 'i', 'n', +'t', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', +'\005', ' ', '\001', '(', '\001', 'H', '\000', 'R', '\013', 'd', 'o', 'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 's', +'t', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\006', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', +'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\013', 'b', 'y', 't', 'e', 's', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', ' ', +'\001', '(', '\014', 'H', '\000', 'R', '\n', 'b', 'y', 't', 'e', 's', 'V', 'a', 'l', 'u', 'e', '\022', 'F', '\n', '\016', 'd', 'u', 'r', 'a', +'t', 'i', 'o', 'n', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\010', ' ', '\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', '\002', '\030', '\001', 'H', '\000', 'R', +'\r', 'd', 'u', 'r', 'a', 't', 'i', 'o', 'n', 'V', 'a', 'l', 'u', 'e', '\022', 'I', '\n', '\017', 't', 'i', 'm', 'e', 's', 't', 'a', +'m', 'p', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\t', ' ', '\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', 'B', '\002', '\030', '\001', 'H', '\000', 'R', '\016', +'t', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'V', 'a', 'l', 'u', 'e', 'B', '\017', '\n', '\r', 'c', 'o', 'n', 's', 't', 'a', 'n', +'t', '_', 'k', 'i', 'n', 'd', '\"', '\271', '\003', '\n', '\n', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '\022', '%', '\n', '\016', +'s', 'y', 'n', 't', 'a', 'x', '_', 'v', 'e', 'r', 's', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\r', 's', 'y', 'n', +'t', 'a', 'x', 'V', 'e', 'r', 's', 'i', 'o', 'n', '\022', '\032', '\n', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\030', '\002', ' ', +'\001', '(', '\t', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '!', '\n', '\014', 'l', 'i', 'n', 'e', '_', 'o', 'f', 'f', +'s', 'e', 't', 's', '\030', '\003', ' ', '\003', '(', '\005', 'R', '\013', 'l', 'i', 'n', 'e', 'O', 'f', 'f', 's', 'e', 't', 's', '\022', 'Q', +'\n', '\t', 'p', 'o', 's', 'i', 't', 'i', 'o', 'n', 's', '\030', '\004', ' ', '\003', '(', '\013', '2', '3', '.', 'g', 'o', 'o', 'g', 'l', +'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', +'e', 'I', 'n', 'f', 'o', '.', 'P', 'o', 's', 'i', 't', 'i', 'o', 'n', 's', 'E', 'n', 't', 'r', 'y', 'R', '\t', 'p', 'o', 's', +'i', 't', 'i', 'o', 'n', 's', '\022', 'U', '\n', '\013', 'm', 'a', 'c', 'r', 'o', '_', 'c', 'a', 'l', 'l', 's', '\030', '\005', ' ', '\003', +'(', '\013', '2', '4', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', +'p', 'h', 'a', '1', '.', 'S', 'o', 'u', 'r', 'c', 'e', 'I', 'n', 'f', 'o', '.', 'M', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', +'s', 'E', 'n', 't', 'r', 'y', 'R', '\n', 'm', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', 's', '\032', '<', '\n', '\016', 'P', 'o', 's', +'i', 't', 'i', 'o', 'n', 's', 'E', 'n', 't', 'r', 'y', '\022', '\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', +'\003', 'k', 'e', 'y', '\022', '\024', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\005', 'v', 'a', 'l', 'u', +'e', ':', '\002', '8', '\001', '\032', ']', '\n', '\017', 'M', 'a', 'c', 'r', 'o', 'C', 'a', 'l', 'l', 's', 'E', 'n', 't', 'r', 'y', '\022', +'\020', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\003', 'R', '\003', 'k', 'e', 'y', '\022', '4', '\n', '\005', 'v', 'a', 'l', 'u', +'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\036', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', +'.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'E', 'x', 'p', 'r', 'R', '\005', 'v', 'a', 'l', 'u', 'e', ':', '\002', '8', '\001', +'\"', 'p', '\n', '\016', 'S', 'o', 'u', 'r', 'c', 'e', 'P', 'o', 's', 'i', 't', 'i', 'o', 'n', '\022', '\032', '\n', '\010', 'l', 'o', 'c', +'a', 't', 'i', 'o', 'n', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\010', 'l', 'o', 'c', 'a', 't', 'i', 'o', 'n', '\022', '\026', '\n', '\006', +'o', 'f', 'f', 's', 'e', 't', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\006', 'o', 'f', 'f', 's', 'e', 't', '\022', '\022', '\n', '\004', 'l', +'i', 'n', 'e', '\030', '\003', ' ', '\001', '(', '\005', 'R', '\004', 'l', 'i', 'n', 'e', '\022', '\026', '\n', '\006', 'c', 'o', 'l', 'u', 'm', 'n', +'\030', '\004', ' ', '\001', '(', '\005', 'R', '\006', 'c', 'o', 'l', 'u', 'm', 'n', 'B', 'n', '\n', '\034', 'c', 'o', 'm', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', 'B', '\013', 'S', 'y', +'n', 't', 'a', 'x', 'P', 'r', 'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', +'g', '.', 'o', 'r', 'g', '/', 'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', 'e', 'a', 'p', 'i', 's', +'/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', 'x', 'p', 'r', '\370', '\001', +'\001', 'b', '\006', 'p', 'r', 'o', 't', 'o', '3', +}; + +static upb_def_init *deps[4] = { + &google_protobuf_duration_proto_upbdefinit, + &google_protobuf_struct_proto_upbdefinit, + &google_protobuf_timestamp_proto_upbdefinit, + NULL +}; + +upb_def_init google_api_expr_v1alpha1_syntax_proto_upbdefinit = { + deps, + &google_api_expr_v1alpha1_syntax_proto_upb_file_layout, + "google/api/expr/v1alpha1/syntax.proto", + UPB_STRVIEW_INIT(descriptor, 3059) +}; diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.h new file mode 100644 index 0000000000..750f563fa7 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.h @@ -0,0 +1,100 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/syntax.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_API_EXPR_V1ALPHA1_SYNTAX_PROTO_UPBDEFS_H_ +#define GOOGLE_API_EXPR_V1ALPHA1_SYNTAX_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 google_api_expr_v1alpha1_syntax_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_ParsedExpr_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.ParsedExpr"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_Ident_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr.Ident"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_Select_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr.Select"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_Call_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr.Call"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_CreateList_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr.CreateList"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_CreateStruct_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr.CreateStruct"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_CreateStruct_Entry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr.CreateStruct.Entry"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Expr_Comprehension_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Expr.Comprehension"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Constant_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Constant"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_SourceInfo_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.SourceInfo"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_SourceInfo_PositionsEntry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.SourceInfo.PositionsEntry"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_SourceInfo_MacroCallsEntry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.SourceInfo.MacroCallsEntry"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_SourcePosition_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_syntax_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.SourcePosition"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* GOOGLE_API_EXPR_V1ALPHA1_SYNTAX_PROTO_UPBDEFS_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.c b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.c new file mode 100644 index 0000000000..1313c37966 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.c @@ -0,0 +1,75 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/value.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#include "upb/def.h" +#include "google/api/expr/v1alpha1/value.upbdefs.h" +#include "google/api/expr/v1alpha1/value.upb.h" + +extern upb_def_init google_protobuf_any_proto_upbdefinit; +extern upb_def_init google_protobuf_struct_proto_upbdefinit; +static const char descriptor[1153] = {'\n', '$', 'g', 'o', 'o', 'g', 'l', 'e', '/', 'a', 'p', 'i', '/', 'e', 'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', +'1', '/', 'v', 'a', 'l', 'u', 'e', '.', 'p', 'r', 'o', 't', 'o', '\022', '\030', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', +'.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '\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', '\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', '\"', '\315', '\004', '\n', +'\005', 'V', 'a', 'l', 'u', 'e', '\022', ';', '\n', '\n', 'n', 'u', 'l', 'l', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\001', ' ', '\001', '(', +'\016', '2', '\032', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'p', 'r', 'o', 't', 'o', 'b', 'u', 'f', '.', 'N', 'u', 'l', 'l', 'V', +'a', 'l', 'u', 'e', 'H', '\000', 'R', '\t', 'n', 'u', 'l', 'l', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', '\n', 'b', 'o', 'o', 'l', +'_', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\010', 'H', '\000', 'R', '\t', 'b', 'o', 'o', 'l', 'V', 'a', 'l', 'u', 'e', +'\022', '!', '\n', '\013', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\003', ' ', '\001', '(', '\003', 'H', '\000', 'R', '\n', +'i', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 'u', 'i', 'n', 't', '6', '4', '_', 'v', 'a', 'l', 'u', +'e', '\030', '\004', ' ', '\001', '(', '\004', 'H', '\000', 'R', '\013', 'u', 'i', 'n', 't', '6', '4', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', +'\014', 'd', 'o', 'u', 'b', 'l', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\005', ' ', '\001', '(', '\001', 'H', '\000', 'R', '\013', 'd', 'o', +'u', 'b', 'l', 'e', 'V', 'a', 'l', 'u', 'e', '\022', '#', '\n', '\014', 's', 't', 'r', 'i', 'n', 'g', '_', 'v', 'a', 'l', 'u', 'e', +'\030', '\006', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\013', 's', 't', 'r', 'i', 'n', 'g', 'V', 'a', 'l', 'u', 'e', '\022', '!', '\n', '\013', +'b', 'y', 't', 'e', 's', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\007', ' ', '\001', '(', '\014', 'H', '\000', 'R', '\n', 'b', 'y', 't', 'e', +'s', 'V', 'a', 'l', 'u', 'e', '\022', 'D', '\n', '\n', 'e', 'n', 'u', 'm', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\t', ' ', '\001', '(', +'\013', '2', '#', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', +'h', 'a', '1', '.', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\t', 'e', 'n', 'u', 'm', 'V', 'a', 'l', 'u', +'e', '\022', '9', '\n', '\014', 'o', 'b', 'j', 'e', 'c', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\n', ' ', '\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', 'o', +'b', 'j', 'e', 'c', 't', 'V', 'a', 'l', 'u', 'e', '\022', 'A', '\n', '\t', 'm', 'a', 'p', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\013', +' ', '\001', '(', '\013', '2', '\"', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', +'a', 'l', 'p', 'h', 'a', '1', '.', 'M', 'a', 'p', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\010', 'm', 'a', 'p', 'V', 'a', 'l', +'u', 'e', '\022', 'D', '\n', '\n', 'l', 'i', 's', 't', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\014', ' ', '\001', '(', '\013', '2', '#', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', +'L', 'i', 's', 't', 'V', 'a', 'l', 'u', 'e', 'H', '\000', 'R', '\t', 'l', 'i', 's', 't', 'V', 'a', 'l', 'u', 'e', '\022', '\037', '\n', +'\n', 't', 'y', 'p', 'e', '_', 'v', 'a', 'l', 'u', 'e', '\030', '\017', ' ', '\001', '(', '\t', 'H', '\000', 'R', '\t', 't', 'y', 'p', 'e', +'V', 'a', 'l', 'u', 'e', 'B', '\006', '\n', '\004', 'k', 'i', 'n', 'd', '\"', '5', '\n', '\t', 'E', 'n', 'u', 'm', 'V', 'a', 'l', 'u', +'e', '\022', '\022', '\n', '\004', 't', 'y', 'p', 'e', '\030', '\001', ' ', '\001', '(', '\t', 'R', '\004', 't', 'y', 'p', 'e', '\022', '\024', '\n', '\005', +'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\005', 'R', '\005', 'v', 'a', 'l', 'u', 'e', '\"', 'D', '\n', '\t', 'L', 'i', 's', +'t', 'V', 'a', 'l', 'u', 'e', '\022', '7', '\n', '\006', 'v', 'a', 'l', 'u', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '\037', '.', +'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', +'V', 'a', 'l', 'u', 'e', 'R', '\006', 'v', 'a', 'l', 'u', 'e', 's', '\"', '\301', '\001', '\n', '\010', 'M', 'a', 'p', 'V', 'a', 'l', 'u', +'e', '\022', 'B', '\n', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\030', '\001', ' ', '\003', '(', '\013', '2', '(', '.', 'g', 'o', 'o', 'g', +'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'M', 'a', 'p', 'V', +'a', 'l', 'u', 'e', '.', 'E', 'n', 't', 'r', 'y', 'R', '\007', 'e', 'n', 't', 'r', 'i', 'e', 's', '\032', 'q', '\n', '\005', 'E', 'n', +'t', 'r', 'y', '\022', '1', '\n', '\003', 'k', 'e', 'y', '\030', '\001', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', 'g', 'l', 'e', +'.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'V', 'a', 'l', 'u', 'e', 'R', +'\003', 'k', 'e', 'y', '\022', '5', '\n', '\005', 'v', 'a', 'l', 'u', 'e', '\030', '\002', ' ', '\001', '(', '\013', '2', '\037', '.', 'g', 'o', 'o', +'g', 'l', 'e', '.', 'a', 'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', '.', 'V', 'a', 'l', +'u', 'e', 'R', '\005', 'v', 'a', 'l', 'u', 'e', 'B', 'm', '\n', '\034', 'c', 'o', 'm', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'a', +'p', 'i', '.', 'e', 'x', 'p', 'r', '.', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', 'B', '\n', 'V', 'a', 'l', 'u', 'e', 'P', 'r', +'o', 't', 'o', 'P', '\001', 'Z', '<', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'g', 'o', 'l', 'a', 'n', 'g', '.', 'o', 'r', 'g', '/', +'g', 'e', 'n', 'p', 'r', 'o', 't', 'o', '/', 'g', 'o', 'o', 'g', 'l', 'e', 'a', 'p', 'i', 's', '/', 'a', 'p', 'i', '/', 'e', +'x', 'p', 'r', '/', 'v', '1', 'a', 'l', 'p', 'h', 'a', '1', ';', 'e', 'x', 'p', 'r', '\370', '\001', '\001', 'b', '\006', 'p', 'r', 'o', +'t', 'o', '3', +}; + +static upb_def_init *deps[3] = { + &google_protobuf_any_proto_upbdefinit, + &google_protobuf_struct_proto_upbdefinit, + NULL +}; + +upb_def_init google_api_expr_v1alpha1_value_proto_upbdefinit = { + deps, + &google_api_expr_v1alpha1_value_proto_upb_file_layout, + "google/api/expr/v1alpha1/value.proto", + UPB_STRVIEW_INIT(descriptor, 1153) +}; diff --git a/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.h b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.h new file mode 100644 index 0000000000..8771e19411 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.h @@ -0,0 +1,55 @@ +/* This file was generated by upbc (the upb compiler) from the input + * file: + * + * google/api/expr/v1alpha1/value.proto + * + * Do not edit -- your changes will be discarded when the file is + * regenerated. */ + +#ifndef GOOGLE_API_EXPR_V1ALPHA1_VALUE_PROTO_UPBDEFS_H_ +#define GOOGLE_API_EXPR_V1ALPHA1_VALUE_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 google_api_expr_v1alpha1_value_proto_upbdefinit; + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_Value_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_value_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.Value"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_EnumValue_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_value_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.EnumValue"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_ListValue_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_value_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.ListValue"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_MapValue_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_value_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.MapValue"); +} + +UPB_INLINE const upb_msgdef *google_api_expr_v1alpha1_MapValue_Entry_getmsgdef(upb_symtab *s) { + _upb_symtab_loaddefinit(s, &google_api_expr_v1alpha1_value_proto_upbdefinit); + return upb_symtab_lookupmsg(s, "google.api.expr.v1alpha1.MapValue.Entry"); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#include "upb/port_undef.inc" + +#endif /* GOOGLE_API_EXPR_V1ALPHA1_VALUE_PROTO_UPBDEFS_H_ */ diff --git a/contrib/libs/grpc/src/core/ext/xds/upb_utils.h b/contrib/libs/grpc/src/core/ext/xds/upb_utils.h new file mode 100644 index 0000000000..1c280d4172 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/upb_utils.h @@ -0,0 +1,65 @@ +// +// 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_XDS_UPB_UTILS_H +#define GRPC_CORE_EXT_XDS_UPB_UTILS_H + +#include <grpc/support/port_platform.h> + +#include <util/generic/string.h> + +#include "y_absl/strings/string_view.h" +#include "upb/text_encode.h" +#include "upb/upb.h" +#include "upb/upb.hpp" + +#include "src/core/ext/xds/certificate_provider_store.h" +#include "src/core/lib/debug/trace.h" + +namespace grpc_core { + +class XdsClient; + +// TODO(roth): Rethink this. All fields except symtab and arena should come +// from XdsClient, injected into XdsResourceType::Decode() somehow without +// passing through XdsApi code, maybe via the AdsResponseParser. +struct XdsEncodingContext { + XdsClient* client; // Used only for logging. Unsafe for dereferencing. + TraceFlag* tracer; + upb_symtab* symtab; + upb_arena* arena; + bool use_v3; + const CertificateProviderStore::PluginDefinitionMap* + certificate_provider_definition_map; +}; + +// Works for both TString and y_absl::string_view. +template <typename T> +inline upb_strview StdStringToUpbString(const T& str) { + return upb_strview_make(str.data(), str.size()); +} + +inline y_absl::string_view UpbStringToAbsl(const upb_strview& str) { + return y_absl::string_view(str.data, str.size); +} + +inline TString UpbStringToStdString(const upb_strview& str) { + return TString(str.data, str.size); +} + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_UPB_UTILS_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_api.cc b/contrib/libs/grpc/src/core/ext/xds/xds_api.cc index 5420644ed9..b3a0f68c59 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_api.cc +++ b/contrib/libs/grpc/src/core/ext/xds/xds_api.cc @@ -18,64 +18,21 @@ #include "src/core/ext/xds/xds_api.h" -#include <algorithm> -#include <cctype> -#include <cstdint> -#include <cstdlib> +#include <set> #include <util/generic/string.h> +#include <vector> #include "y_absl/strings/str_cat.h" -#include "y_absl/strings/str_format.h" -#include "y_absl/strings/str_join.h" -#include "y_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" -#include "envoy/config/endpoint/v3/endpoint.upb.h" -#include "envoy/config/endpoint/v3/endpoint.upbdefs.h" -#include "envoy/config/endpoint/v3/endpoint_components.upb.h" #include "envoy/config/endpoint/v3/load_report.upb.h" -#include "envoy/config/listener/v3/api_listener.upb.h" -#include "envoy/config/listener/v3/listener.upb.h" -#include "envoy/config/listener/v3/listener.upbdefs.h" -#include "envoy/config/listener/v3/listener_components.upb.h" -#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" #include "envoy/service/discovery/v3/discovery.upbdefs.h" -#include "envoy/service/endpoint/v3/eds.upb.h" -#include "envoy/service/endpoint/v3/eds.upbdefs.h" -#include "envoy/service/listener/v3/lds.upb.h" #include "envoy/service/load_stats/v3/lrs.upb.h" #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" -#include "envoy/type/v3/range.upb.h" #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" @@ -83,13 +40,16 @@ #include "upb/text_encode.h" #include "upb/upb.h" #include "upb/upb.hpp" -#include "xds/type/v3/typed_struct.upb.h" #include <grpc/impl/codegen/log.h> #include <grpc/support/alloc.h> #include <grpc/support/string_util.h> +#include "src/core/ext/xds/upb_utils.h" +#include "src/core/ext/xds/xds_common_types.h" +#include "src/core/ext/xds/xds_resource_type.h" #include "src/core/ext/xds/xds_routing.h" +#include "src/core/lib/address_utils/parse_address.h" #include "src/core/lib/address_utils/sockaddr_utils.h" #include "src/core/lib/gpr/env.h" #include "src/core/lib/gpr/string.h" @@ -102,764 +62,6 @@ namespace grpc_core { -// 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 -// default. -bool XdsAggregateAndLogicalDnsClusterEnabled() { - char* value = gpr_getenv( - "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"); - bool parsed_value; - bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); - gpr_free(value); - return parse_succeeded && parsed_value; -} - -// TODO(yashykt): Remove once RBAC is no longer experimental -bool XdsRbacEnabled() { - char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_RBAC"); - bool parsed_value; - bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); - gpr_free(value); - return parse_succeeded && parsed_value; -} - -// -// XdsApi::RetryPolicy -// - -TString XdsApi::RetryPolicy::RetryBackOff::ToString() const { - std::vector<TString> contents; - contents.push_back( - y_absl::StrCat("RetryBackOff Base: ", base_interval.ToString())); - contents.push_back( - y_absl::StrCat("RetryBackOff max: ", max_interval.ToString())); - return y_absl::StrJoin(contents, ","); -} - -TString XdsApi::RetryPolicy::ToString() const { - std::vector<TString> contents; - contents.push_back(y_absl::StrFormat("num_retries=%d", num_retries)); - contents.push_back(retry_back_off.ToString()); - return y_absl::StrCat("{", y_absl::StrJoin(contents, ","), "}"); -} - -// -// XdsApi::Route::Matchers -// - -TString XdsApi::Route::Matchers::ToString() const { - std::vector<TString> contents; - contents.push_back( - y_absl::StrFormat("PathMatcher{%s}", path_matcher.ToString())); - for (const HeaderMatcher& header_matcher : header_matchers) { - contents.push_back(header_matcher.ToString()); - } - if (fraction_per_million.has_value()) { - contents.push_back(y_absl::StrFormat("Fraction Per Million %d", - fraction_per_million.value())); - } - return y_absl::StrJoin(contents, "\n"); -} - -// -// XdsApi::Route::RouteAction::HashPolicy -// - -XdsApi::Route::RouteAction::HashPolicy::HashPolicy(const HashPolicy& other) - : type(other.type), - header_name(other.header_name), - regex_substitution(other.regex_substitution) { - if (other.regex != nullptr) { - regex = - y_absl::make_unique<RE2>(other.regex->pattern(), other.regex->options()); - } -} - -XdsApi::Route::RouteAction::HashPolicy& -XdsApi::Route::RouteAction::HashPolicy::operator=(const HashPolicy& other) { - type = other.type; - header_name = other.header_name; - if (other.regex != nullptr) { - regex = - y_absl::make_unique<RE2>(other.regex->pattern(), other.regex->options()); - } - regex_substitution = other.regex_substitution; - return *this; -} - -XdsApi::Route::RouteAction::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::RouteAction::HashPolicy& -XdsApi::Route::RouteAction::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::RouteAction::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; -} - -TString XdsApi::Route::RouteAction::HashPolicy::ToString() const { - std::vector<TString> 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( - y_absl::StrFormat("terminal=%s", terminal ? "true" : "false")); - if (type == Type::HEADER) { - contents.push_back(y_absl::StrFormat( - "Header %s:/%s/%s", header_name, - (regex == nullptr) ? "" : regex->pattern(), regex_substitution)); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::Route::RouteAction::ClusterWeight -// - -TString XdsApi::Route::RouteAction::ClusterWeight::ToString() const { - std::vector<TString> contents; - contents.push_back(y_absl::StrCat("cluster=", name)); - contents.push_back(y_absl::StrCat("weight=", weight)); - if (!typed_per_filter_config.empty()) { - std::vector<TString> parts; - for (const auto& p : typed_per_filter_config) { - const TString& key = p.first; - const auto& config = p.second; - parts.push_back(y_absl::StrCat(key, "=", config.ToString())); - } - contents.push_back(y_absl::StrCat("typed_per_filter_config={", - y_absl::StrJoin(parts, ", "), "}")); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::Route::RouteAction -// - -TString XdsApi::Route::RouteAction::ToString() const { - std::vector<TString> contents; - for (const HashPolicy& hash_policy : hash_policies) { - contents.push_back(y_absl::StrCat("hash_policy=", hash_policy.ToString())); - } - if (retry_policy.has_value()) { - contents.push_back(y_absl::StrCat("retry_policy=", retry_policy->ToString())); - } - if (!cluster_name.empty()) { - contents.push_back(y_absl::StrFormat("Cluster name: %s", cluster_name)); - } - for (const ClusterWeight& cluster_weight : weighted_clusters) { - contents.push_back(cluster_weight.ToString()); - } - if (max_stream_duration.has_value()) { - contents.push_back(max_stream_duration->ToString()); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::Route -// - -TString XdsApi::Route::ToString() const { - std::vector<TString> contents; - contents.push_back(matchers.ToString()); - auto* route_action = y_absl::get_if<XdsApi::Route::RouteAction>(&action); - if (route_action != nullptr) { - contents.push_back(y_absl::StrCat("route=", route_action->ToString())); - } else if (y_absl::holds_alternative<XdsApi::Route::NonForwardingAction>( - action)) { - contents.push_back("non_forwarding_action={}"); - } else { - contents.push_back("unknown_action={}"); - } - if (!typed_per_filter_config.empty()) { - contents.push_back("typed_per_filter_config={"); - for (const auto& p : typed_per_filter_config) { - const TString& name = p.first; - const auto& config = p.second; - contents.push_back(y_absl::StrCat(" ", name, "=", config.ToString())); - } - contents.push_back("}"); - } - return y_absl::StrJoin(contents, "\n"); -} - -// -// XdsApi::RdsUpdate -// - -TString XdsApi::RdsUpdate::ToString() const { - std::vector<TString> vhosts; - for (const VirtualHost& vhost : virtual_hosts) { - vhosts.push_back( - y_absl::StrCat("vhost={\n" - " domains=[", - y_absl::StrJoin(vhost.domains, ", "), - "]\n" - " routes=[\n")); - for (const XdsApi::Route& route : vhost.routes) { - vhosts.push_back(" {\n"); - vhosts.push_back(route.ToString()); - vhosts.push_back("\n }\n"); - } - vhosts.push_back(" ]\n"); - vhosts.push_back(" typed_per_filter_config={\n"); - for (const auto& p : vhost.typed_per_filter_config) { - const TString& name = p.first; - const auto& config = p.second; - vhosts.push_back( - y_absl::StrCat(" ", name, "=", config.ToString(), "\n")); - } - vhosts.push_back(" }\n"); - vhosts.push_back("]\n"); - } - return y_absl::StrJoin(vhosts, ""); -} - -// -// XdsApi::CommonTlsContext::CertificateValidationContext -// - -TString XdsApi::CommonTlsContext::CertificateValidationContext::ToString() - const { - std::vector<TString> contents; - for (const auto& match : match_subject_alt_names) { - contents.push_back(match.ToString()); - } - return y_absl::StrFormat("{match_subject_alt_names=[%s]}", - y_absl::StrJoin(contents, ", ")); -} - -bool XdsApi::CommonTlsContext::CertificateValidationContext::Empty() const { - return match_subject_alt_names.empty(); -} - -// -// XdsApi::CommonTlsContext::CertificateProviderPluginInstance -// - -TString -XdsApi::CommonTlsContext::CertificateProviderPluginInstance::ToString() const { - y_absl::InlinedVector<TString, 2> contents; - if (!instance_name.empty()) { - contents.push_back(y_absl::StrFormat("instance_name=%s", instance_name)); - } - if (!certificate_name.empty()) { - contents.push_back( - y_absl::StrFormat("certificate_name=%s", certificate_name)); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -bool XdsApi::CommonTlsContext::CertificateProviderPluginInstance::Empty() - const { - return instance_name.empty() && certificate_name.empty(); -} - -// -// XdsApi::CommonTlsContext -// - -TString XdsApi::CommonTlsContext::ToString() const { - y_absl::InlinedVector<TString, 2> contents; - if (!tls_certificate_provider_instance.Empty()) { - contents.push_back( - y_absl::StrFormat("tls_certificate_provider_instance=%s", - tls_certificate_provider_instance.ToString())); - } - if (!certificate_validation_context.Empty()) { - contents.push_back( - y_absl::StrFormat("certificate_validation_context=%s", - certificate_validation_context.ToString())); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -bool XdsApi::CommonTlsContext::Empty() const { - return tls_certificate_provider_instance.Empty() && - certificate_validation_context.Empty(); -} - -// -// XdsApi::DownstreamTlsContext -// - -TString XdsApi::DownstreamTlsContext::ToString() const { - return y_absl::StrFormat("common_tls_context=%s, require_client_certificate=%s", - common_tls_context.ToString(), - require_client_certificate ? "true" : "false"); -} - -bool XdsApi::DownstreamTlsContext::Empty() const { - return common_tls_context.Empty(); -} - -// -// XdsApi::LdsUpdate::HttpConnectionManager -// - -TString XdsApi::LdsUpdate::HttpConnectionManager::ToString() const { - y_absl::InlinedVector<TString, 4> contents; - contents.push_back(y_absl::StrFormat( - "route_config_name=%s", - !route_config_name.empty() ? route_config_name.c_str() : "<inlined>")); - contents.push_back(y_absl::StrFormat("http_max_stream_duration=%s", - http_max_stream_duration.ToString())); - if (rds_update.has_value()) { - contents.push_back( - y_absl::StrFormat("rds_update=%s", rds_update->ToString())); - } - if (!http_filters.empty()) { - std::vector<TString> filter_strings; - for (const auto& http_filter : http_filters) { - filter_strings.push_back(http_filter.ToString()); - } - contents.push_back(y_absl::StrCat("http_filters=[", - y_absl::StrJoin(filter_strings, ", "), "]")); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::LdsUpdate::HttpFilter -// - -TString XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter::ToString() - const { - return y_absl::StrCat("{name=", name, ", config=", config.ToString(), "}"); -} - -// -// XdsApi::LdsUpdate::FilterChainData -// - -TString XdsApi::LdsUpdate::FilterChainData::ToString() const { - return y_absl::StrCat( - "{downstream_tls_context=", downstream_tls_context.ToString(), - " http_connection_manager=", http_connection_manager.ToString(), "}"); -} - -// -// XdsApi::LdsUpdate::FilterChainMap::CidrRange -// - -TString XdsApi::LdsUpdate::FilterChainMap::CidrRange::ToString() const { - return y_absl::StrCat( - "{address_prefix=", grpc_sockaddr_to_string(&address, false), - ", prefix_len=", prefix_len, "}"); -} - -// -// FilterChain -// - -struct FilterChain { - struct FilterChainMatch { - uint32_t destination_port = 0; - std::vector<XdsApi::LdsUpdate::FilterChainMap::CidrRange> prefix_ranges; - XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType source_type = - XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::kAny; - std::vector<XdsApi::LdsUpdate::FilterChainMap::CidrRange> - source_prefix_ranges; - std::vector<uint32_t> source_ports; - std::vector<TString> server_names; - TString transport_protocol; - std::vector<TString> application_protocols; - - TString ToString() const; - } filter_chain_match; - - std::shared_ptr<XdsApi::LdsUpdate::FilterChainData> filter_chain_data; -}; - -TString FilterChain::FilterChainMatch::ToString() const { - y_absl::InlinedVector<TString, 8> contents; - if (destination_port != 0) { - contents.push_back(y_absl::StrCat("destination_port=", destination_port)); - } - if (!prefix_ranges.empty()) { - std::vector<TString> prefix_ranges_content; - for (const auto& range : prefix_ranges) { - prefix_ranges_content.push_back(range.ToString()); - } - contents.push_back(y_absl::StrCat( - "prefix_ranges={", y_absl::StrJoin(prefix_ranges_content, ", "), "}")); - } - if (source_type == XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType:: - kSameIpOrLoopback) { - contents.push_back("source_type=SAME_IP_OR_LOOPBACK"); - } else if (source_type == XdsApi::LdsUpdate::FilterChainMap:: - ConnectionSourceType::kExternal) { - contents.push_back("source_type=EXTERNAL"); - } - if (!source_prefix_ranges.empty()) { - std::vector<TString> source_prefix_ranges_content; - for (const auto& range : source_prefix_ranges) { - source_prefix_ranges_content.push_back(range.ToString()); - } - contents.push_back( - y_absl::StrCat("source_prefix_ranges={", - y_absl::StrJoin(source_prefix_ranges_content, ", "), "}")); - } - if (!source_ports.empty()) { - contents.push_back( - y_absl::StrCat("source_ports={", y_absl::StrJoin(source_ports, ", "), "}")); - } - if (!server_names.empty()) { - contents.push_back( - y_absl::StrCat("server_names={", y_absl::StrJoin(server_names, ", "), "}")); - } - if (!transport_protocol.empty()) { - contents.push_back(y_absl::StrCat("transport_protocol=", transport_protocol)); - } - if (!application_protocols.empty()) { - contents.push_back(y_absl::StrCat("application_protocols={", - y_absl::StrJoin(application_protocols, ", "), - "}")); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::LdsUpdate::FilterChainMap -// - -TString XdsApi::LdsUpdate::FilterChainMap::ToString() const { - std::vector<TString> 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(y_absl::StrCat( - "{filter_chain_match=", filter_chain_match.ToString(), - ", filter_chain=", source_port_pair.second.data->ToString(), - "}")); - } - } - } - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::LdsUpdate -// - -TString XdsApi::LdsUpdate::ToString() const { - y_absl::InlinedVector<TString, 4> contents; - if (type == ListenerType::kTcpListener) { - contents.push_back(y_absl::StrCat("address=", address)); - contents.push_back( - y_absl::StrCat("filter_chain_map=", filter_chain_map.ToString())); - if (default_filter_chain.has_value()) { - contents.push_back(y_absl::StrCat("default_filter_chain=", - default_filter_chain->ToString())); - } - } else if (type == ListenerType::kHttpApiListener) { - contents.push_back(y_absl::StrFormat("http_connection_manager=%s", - http_connection_manager.ToString())); - } - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::CdsUpdate -// - -TString XdsApi::CdsUpdate::ToString() const { - y_absl::InlinedVector<TString, 8> contents; - switch (cluster_type) { - case EDS: - contents.push_back("cluster_type=EDS"); - if (!eds_service_name.empty()) { - contents.push_back( - y_absl::StrFormat("eds_service_name=%s", eds_service_name)); - } - break; - case LOGICAL_DNS: - contents.push_back("cluster_type=LOGICAL_DNS"); - contents.push_back(y_absl::StrFormat("dns_hostname=%s", dns_hostname)); - break; - case AGGREGATE: - contents.push_back("cluster_type=AGGREGATE"); - contents.push_back( - y_absl::StrFormat("prioritized_cluster_names=[%s]", - y_absl::StrJoin(prioritized_cluster_names, ", "))); - } - if (!common_tls_context.Empty()) { - contents.push_back(y_absl::StrFormat("common_tls_context=%s", - common_tls_context.ToString())); - } - if (lrs_load_reporting_server_name.has_value()) { - contents.push_back(y_absl::StrFormat("lrs_load_reporting_server_name=%s", - lrs_load_reporting_server_name.value())); - } - contents.push_back(y_absl::StrCat("lb_policy=", lb_policy)); - if (lb_policy == "RING_HASH") { - contents.push_back(y_absl::StrCat("min_ring_size=", min_ring_size)); - contents.push_back(y_absl::StrCat("max_ring_size=", max_ring_size)); - } - contents.push_back( - y_absl::StrFormat("max_concurrent_requests=%d", max_concurrent_requests)); - return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); -} - -// -// XdsApi::EdsUpdate -// - -TString XdsApi::EdsUpdate::Priority::Locality::ToString() const { - std::vector<TString> endpoint_strings; - for (const ServerAddress& endpoint : endpoints) { - endpoint_strings.emplace_back(endpoint.ToString()); - } - return y_absl::StrCat("{name=", name->AsHumanReadableString(), - ", lb_weight=", lb_weight, ", endpoints=[", - y_absl::StrJoin(endpoint_strings, ", "), "]}"); -} - -bool XdsApi::EdsUpdate::Priority::operator==(const Priority& other) const { - if (localities.size() != other.localities.size()) return false; - auto it1 = localities.begin(); - auto it2 = other.localities.begin(); - while (it1 != localities.end()) { - if (*it1->first != *it2->first) return false; - if (it1->second != it2->second) return false; - ++it1; - ++it2; - } - return true; -} - -TString XdsApi::EdsUpdate::Priority::ToString() const { - std::vector<TString> locality_strings; - for (const auto& p : localities) { - locality_strings.emplace_back(p.second.ToString()); - } - return y_absl::StrCat("[", y_absl::StrJoin(locality_strings, ", "), "]"); -} - -bool XdsApi::EdsUpdate::DropConfig::ShouldDrop( - const TString** category_name) const { - for (size_t i = 0; i < drop_category_list_.size(); ++i) { - const auto& drop_category = drop_category_list_[i]; - // Generate a random number in [0, 1000000). - const uint32_t random = static_cast<uint32_t>(rand()) % 1000000; - if (random < drop_category.parts_per_million) { - *category_name = &drop_category.name; - return true; - } - } - return false; -} - -TString XdsApi::EdsUpdate::DropConfig::ToString() const { - std::vector<TString> category_strings; - for (const DropCategory& category : drop_category_list_) { - category_strings.emplace_back( - y_absl::StrCat(category.name, "=", category.parts_per_million)); - } - return y_absl::StrCat("{[", y_absl::StrJoin(category_strings, ", "), - "], drop_all=", drop_all_, "}"); -} - -TString XdsApi::EdsUpdate::ToString() const { - std::vector<TString> priority_strings; - for (size_t i = 0; i < priorities.size(); ++i) { - const Priority& priority = priorities[i]; - priority_strings.emplace_back( - y_absl::StrCat("priority ", i, ": ", priority.ToString())); - } - return y_absl::StrCat("priorities=[", y_absl::StrJoin(priority_strings, ", "), - "], drop_config=", drop_config->ToString()); -} - -// -// XdsApi -// - -// TODO(roth): All constants and functions for individual resource types -// should be merged into the XdsResourceType abstraction. -const char* XdsApi::kLdsTypeUrl = "envoy.config.listener.v3.Listener"; -const char* XdsApi::kRdsTypeUrl = "envoy.config.route.v3.RouteConfiguration"; -const char* XdsApi::kCdsTypeUrl = "envoy.config.cluster.v3.Cluster"; -const char* XdsApi::kEdsTypeUrl = - "envoy.config.endpoint.v3.ClusterLoadAssignment"; - -namespace { - -const char* kLdsV2TypeUrl = "envoy.api.v2.Listener"; -const char* kRdsV2TypeUrl = "envoy.api.v2.RouteConfiguration"; -const char* kCdsV2TypeUrl = "envoy.api.v2.Cluster"; -const char* kEdsV2TypeUrl = "envoy.api.v2.ClusterLoadAssignment"; - -bool IsLdsInternal(y_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 IsRdsInternal(y_absl::string_view type_url, bool* /*is_v2*/ = nullptr) { - return type_url == XdsApi::kRdsTypeUrl || type_url == kRdsV2TypeUrl; -} - -bool IsCdsInternal(y_absl::string_view type_url, bool* /*is_v2*/ = nullptr) { - return type_url == XdsApi::kCdsTypeUrl || type_url == kCdsV2TypeUrl; -} - -bool IsEdsInternal(y_absl::string_view type_url, bool* /*is_v2*/ = nullptr) { - return type_url == XdsApi::kEdsTypeUrl || type_url == kEdsV2TypeUrl; -} - -y_absl::string_view TypeUrlExternalToInternal(bool use_v3, - const TString& type_url) { - if (!use_v3) { - if (type_url == XdsApi::kLdsTypeUrl) { - return kLdsV2TypeUrl; - } - if (type_url == XdsApi::kRdsTypeUrl) { - return kRdsV2TypeUrl; - } - if (type_url == XdsApi::kCdsTypeUrl) { - return kCdsV2TypeUrl; - } - if (type_url == XdsApi::kEdsTypeUrl) { - return kEdsV2TypeUrl; - } - } - return type_url; -} - -TString TypeUrlInternalToExternal(y_absl::string_view type_url) { - if (type_url == kLdsV2TypeUrl) { - return XdsApi::kLdsTypeUrl; - } else if (type_url == kRdsV2TypeUrl) { - return XdsApi::kRdsTypeUrl; - } else if (type_url == kCdsV2TypeUrl) { - return XdsApi::kCdsTypeUrl; - } else if (type_url == kEdsV2TypeUrl) { - return XdsApi::kEdsTypeUrl; - } - return TString(type_url); -} - -struct EncodingContext { - XdsClient* client; // Used only for logging. Unsafe for dereferencing. - TraceFlag* tracer; - upb_symtab* symtab; - upb_arena* arena; - bool use_v3; - const CertificateProviderStore::PluginDefinitionMap* - certificate_provider_definition_map; -}; - -class XdsResourceType { - public: - // A base type for resource data. - struct ResourceData {}; - - struct DecodeResult { - TString name; - y_absl::StatusOr<std::unique_ptr<ResourceData>> resource; - }; - - virtual ~XdsResourceType() = default; - - virtual y_absl::string_view type_url() const = 0; - - virtual y_absl::string_view v2_type_url() const = 0; - - virtual y_absl::StatusOr<DecodeResult> Decode( - const EncodingContext& context, y_absl::string_view serialized_resource, - bool is_v2) const = 0; - - bool IsType(y_absl::string_view resource_type, bool* is_v2) const { - if (resource_type == type_url()) return true; - if (resource_type == v2_type_url()) { - if (is_v2 != nullptr) *is_v2 = true; - return true; - } - return false; - } -}; - -y_absl::StatusOr<XdsApi::ResourceName> ParseResourceNameInternal( - y_absl::string_view name, - std::function<bool(y_absl::string_view, bool*)> is_expected_type) { - // Old-style names use the empty string for authority. - // authority is prefixed with "old:" to indicate that it's an old-style name. - if (!y_absl::StartsWith(name, "xdstp:")) { - return XdsApi::ResourceName{"old:", TString(name)}; - } - // New style name. Parse URI. - auto uri = URI::Parse(name); - if (!uri.ok()) return uri.status(); - // Split the resource type off of the path to get the id. - std::pair<y_absl::string_view, y_absl::string_view> path_parts = - y_absl::StrSplit(uri->path(), y_absl::MaxSplits('/', 1)); - if (!is_expected_type(path_parts.first, nullptr)) { - return y_absl::InvalidArgumentError( - "xdstp URI path must indicate valid xDS resource type"); - } - std::vector<std::pair<y_absl::string_view, y_absl::string_view>> query_parameters( - uri->query_parameter_map().begin(), uri->query_parameter_map().end()); - std::sort(query_parameters.begin(), query_parameters.end()); - return XdsApi::ResourceName{ - y_absl::StrCat("xdstp:", uri->authority()), - y_absl::StrCat( - path_parts.second, (query_parameters.empty() ? "?" : ""), - y_absl::StrJoin(query_parameters, "&", y_absl::PairFormatter("=")))}; -} - -} // namespace - // If gRPC is built with -DGRPC_XDS_USER_AGENT_NAME_SUFFIX="...", that string // will be appended to the user agent name reported to the xDS server. #ifdef GRPC_XDS_USER_AGENT_NAME_SUFFIX @@ -881,11 +83,13 @@ y_absl::StatusOr<XdsApi::ResourceName> ParseResourceNameInternal( XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node, const CertificateProviderStore::PluginDefinitionMap* - certificate_provider_definition_map) + certificate_provider_definition_map, + upb::SymbolTable* symtab) : client_(client), tracer_(tracer), node_(node), certificate_provider_definition_map_(certificate_provider_definition_map), + symtab_(symtab), build_version_(y_absl::StrCat("gRPC C-core ", GPR_PLATFORM_STRING, " ", grpc_version_string(), GRPC_XDS_USER_AGENT_NAME_SUFFIX_STRING, @@ -895,71 +99,14 @@ XdsApi::XdsApi(XdsClient* client, TraceFlag* tracer, user_agent_version_( y_absl::StrCat("C-core ", grpc_version_string(), GRPC_XDS_USER_AGENT_NAME_SUFFIX_STRING, - GRPC_XDS_USER_AGENT_VERSION_SUFFIX_STRING)) { - // Populate upb symtab with xDS proto messages that we want to print - // properly in logs. - // Note: This won't actually work properly until upb adds support for - // Any fields in textproto printing (internal b/178821188). - 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. - XdsHttpFilterRegistry::PopulateSymtab(symtab_.ptr()); -} - -bool XdsApi::IsLds(y_absl::string_view type_url) { - return IsLdsInternal(type_url); -} - -bool XdsApi::IsRds(y_absl::string_view type_url) { - return IsRdsInternal(type_url); -} - -bool XdsApi::IsCds(y_absl::string_view type_url) { - return IsCdsInternal(type_url); -} - -bool XdsApi::IsEds(y_absl::string_view type_url) { - return IsEdsInternal(type_url); -} - -y_absl::StatusOr<XdsApi::ResourceName> XdsApi::ParseResourceName( - y_absl::string_view name, bool (*is_expected_type)(y_absl::string_view)) { - return ParseResourceNameInternal( - name, [is_expected_type](y_absl::string_view type, bool*) { - return is_expected_type(type); - }); -} - -TString XdsApi::ConstructFullResourceName(y_absl::string_view authority, - y_absl::string_view resource_type, - y_absl::string_view name) { - if (y_absl::ConsumePrefix(&authority, "xdstp:")) { - return y_absl::StrCat("xdstp://", authority, "/", resource_type, "/", name); - } else { - return TString(y_absl::StripPrefix(name, "old:")); - } -} + GRPC_XDS_USER_AGENT_VERSION_SUFFIX_STRING)) {} namespace { -// Works for both TString and y_absl::string_view. -template <typename T> -inline upb_strview StdStringToUpbString(const T& str) { - return upb_strview_make(str.data(), str.size()); -} - -void PopulateMetadataValue(const EncodingContext& context, +void PopulateMetadataValue(const XdsEncodingContext& context, google_protobuf_Value* value_pb, const Json& value); -void PopulateListValue(const EncodingContext& context, +void PopulateListValue(const XdsEncodingContext& context, google_protobuf_ListValue* list_value, const Json::Array& values) { for (const auto& value : values) { @@ -969,7 +116,7 @@ void PopulateListValue(const EncodingContext& context, } } -void PopulateMetadata(const EncodingContext& context, +void PopulateMetadata(const XdsEncodingContext& context, google_protobuf_Struct* metadata_pb, const Json::Object& metadata) { for (const auto& p : metadata) { @@ -980,7 +127,7 @@ void PopulateMetadata(const EncodingContext& context, } } -void PopulateMetadataValue(const EncodingContext& context, +void PopulateMetadataValue(const XdsEncodingContext& context, google_protobuf_Value* value_pb, const Json& value) { switch (value.type()) { case Json::Type::JSON_NULL: @@ -1036,7 +183,7 @@ TString EncodeStringField(uint32_t field_number, const TString& str) { EncodeVarint(str.size()) + str; } -void PopulateBuildVersion(const EncodingContext& context, +void PopulateBuildVersion(const XdsEncodingContext& context, envoy_config_core_v3_Node* node_msg, const TString& build_version) { TString encoded_build_version = EncodeStringField(5, build_version); @@ -1048,7 +195,7 @@ void PopulateBuildVersion(const EncodingContext& context, encoded_build_version.size(), context.arena); } -void PopulateNode(const EncodingContext& context, +void PopulateNode(const XdsEncodingContext& context, const XdsBootstrap::Node* node, const TString& build_version, const TString& user_agent_name, @@ -1098,16 +245,8 @@ void PopulateNode(const EncodingContext& context, context.arena); } -inline y_absl::string_view UpbStringToAbsl(const upb_strview& str) { - return y_absl::string_view(str.data, str.size); -} - -inline TString UpbStringToStdString(const upb_strview& str) { - return TString(str.data, str.size); -} - void MaybeLogDiscoveryRequest( - const EncodingContext& context, + const XdsEncodingContext& context, const envoy_service_discovery_v3_DiscoveryRequest* request) { if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { @@ -1121,7 +260,7 @@ void MaybeLogDiscoveryRequest( } grpc_slice SerializeDiscoveryRequest( - const EncodingContext& context, + const XdsEncodingContext& context, envoy_service_discovery_v3_DiscoveryRequest* request) { size_t output_length; char* output = envoy_service_discovery_v3_DiscoveryRequest_serialize( @@ -1132,28 +271,24 @@ grpc_slice SerializeDiscoveryRequest( } // namespace grpc_slice XdsApi::CreateAdsRequest( - const XdsBootstrap::XdsServer& server, const TString& type_url, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& resource_names, - const TString& version, const TString& nonce, - grpc_error_handle error, bool populate_node) { + const XdsBootstrap::XdsServer& server, y_absl::string_view type_url, + y_absl::string_view version, y_absl::string_view nonce, + const std::vector<TString>& resource_names, grpc_error_handle error, + bool populate_node) { upb::Arena arena; - const EncodingContext context = {client_, - tracer_, - symtab_.ptr(), - arena.ptr(), - server.ShouldUseV3(), - certificate_provider_definition_map_}; + const XdsEncodingContext context = {client_, + tracer_, + symtab_->ptr(), + arena.ptr(), + server.ShouldUseV3(), + certificate_provider_definition_map_}; // Create a request. envoy_service_discovery_v3_DiscoveryRequest* request = envoy_service_discovery_v3_DiscoveryRequest_new(arena.ptr()); // Set type_url. - y_absl::string_view real_type_url = - TypeUrlExternalToInternal(server.ShouldUseV3(), type_url); - TString real_type_url_str = - y_absl::StrCat("type.googleapis.com/", real_type_url); + TString type_url_str = y_absl::StrCat("type.googleapis.com/", type_url); envoy_service_discovery_v3_DiscoveryRequest_set_type_url( - request, StdStringToUpbString(real_type_url_str)); + request, StdStringToUpbString(type_url_str)); // Set version_info. if (!version.empty()) { envoy_service_discovery_v3_DiscoveryRequest_set_version_info( @@ -1189,27 +324,10 @@ grpc_slice XdsApi::CreateAdsRequest( PopulateNode(context, node_, build_version_, user_agent_name_, user_agent_version_, node_msg); } - // A vector for temporary local storage of resource name strings. - std::vector<TString> resource_name_storage; - // Make sure the vector is sized right up-front, so that reallocations - // don't move the strings out from under the upb proto object that - // points to them. - size_t size = 0; - for (const auto& p : resource_names) { - size += p.second.size(); - } - resource_name_storage.reserve(size); // Add resource_names. - for (const auto& a : resource_names) { - y_absl::string_view authority = a.first; - for (const auto& p : a.second) { - y_absl::string_view resource_id = p; - resource_name_storage.push_back( - ConstructFullResourceName(authority, real_type_url, resource_id)); - envoy_service_discovery_v3_DiscoveryRequest_add_resource_names( - request, StdStringToUpbString(resource_name_storage.back()), - arena.ptr()); - } + for (const TString& resource_name : resource_names) { + envoy_service_discovery_v3_DiscoveryRequest_add_resource_names( + request, StdStringToUpbString(resource_name), arena.ptr()); } MaybeLogDiscoveryRequest(context, request); return SerializeDiscoveryRequest(context, request); @@ -1218,7 +336,7 @@ grpc_slice XdsApi::CreateAdsRequest( namespace { void MaybeLogDiscoveryResponse( - const EncodingContext& context, + const XdsEncodingContext& context, const envoy_service_discovery_v3_DiscoveryResponse* response) { if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { @@ -1231,2556 +349,61 @@ void MaybeLogDiscoveryResponse( } } -void MaybeLogListener(const EncodingContext& context, - const envoy_config_listener_v3_Listener* listener) { - if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && - gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { - const upb_msgdef* msg_type = - envoy_config_listener_v3_Listener_getmsgdef(context.symtab); - char buf[10240]; - upb_text_encode(listener, msg_type, nullptr, 0, buf, sizeof(buf)); - gpr_log(GPR_DEBUG, "[xds_client %p] Listener: %s", context.client, buf); - } -} - -void MaybeLogHttpConnectionManager( - const EncodingContext& context, - const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* - http_connection_manager_config) { - if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && - gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { - const upb_msgdef* msg_type = - envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef( - context.symtab); - char buf[10240]; - upb_text_encode(http_connection_manager_config, msg_type, nullptr, 0, buf, - sizeof(buf)); - gpr_log(GPR_DEBUG, "[xds_client %p] HttpConnectionManager: %s", - context.client, buf); - } -} - -void MaybeLogRouteConfiguration( - const EncodingContext& context, - const envoy_config_route_v3_RouteConfiguration* route_config) { - if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && - gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { - const upb_msgdef* msg_type = - envoy_config_route_v3_RouteConfiguration_getmsgdef(context.symtab); - char buf[10240]; - upb_text_encode(route_config, msg_type, nullptr, 0, buf, sizeof(buf)); - gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", context.client, - buf); - } -} - -void MaybeLogCluster(const EncodingContext& context, - const envoy_config_cluster_v3_Cluster* cluster) { - if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && - gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { - const upb_msgdef* msg_type = - envoy_config_cluster_v3_Cluster_getmsgdef(context.symtab); - char buf[10240]; - upb_text_encode(cluster, msg_type, nullptr, 0, buf, sizeof(buf)); - gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", context.client, buf); - } -} - -void MaybeLogClusterLoadAssignment( - const EncodingContext& context, - const envoy_config_endpoint_v3_ClusterLoadAssignment* cla) { - if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && - gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { - const upb_msgdef* msg_type = - envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef( - context.symtab); - char buf[10240]; - upb_text_encode(cla, msg_type, nullptr, 0, buf, sizeof(buf)); - gpr_log(GPR_DEBUG, "[xds_client %p] ClusterLoadAssignment: %s", - context.client, buf); - } -} - -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; - if (case_sensitive_ptr != nullptr) { - case_sensitive = google_protobuf_BoolValue_value(case_sensitive_ptr); - } - StringMatcher::Type type; - TString match_string; - if (envoy_config_route_v3_RouteMatch_has_prefix(match)) { - y_absl::string_view prefix = - UpbStringToAbsl(envoy_config_route_v3_RouteMatch_prefix(match)); - // Empty prefix "" is accepted. - if (!prefix.empty()) { - // Prefix "/" is accepted. - if (prefix[0] != '/') { - // Prefix which does not start with a / will never match anything, so - // ignore this route. - *ignore_route = true; - return GRPC_ERROR_NONE; - } - std::vector<y_absl::string_view> prefix_elements = - y_absl::StrSplit(prefix.substr(1), y_absl::MaxSplits('/', 2)); - if (prefix_elements.size() > 2) { - // Prefix cannot have more than 2 slashes. - *ignore_route = true; - return GRPC_ERROR_NONE; - } else if (prefix_elements.size() == 2 && prefix_elements[0].empty()) { - // Prefix contains empty string between the 2 slashes - *ignore_route = true; - return GRPC_ERROR_NONE; - } - } - type = StringMatcher::Type::kPrefix; - match_string = TString(prefix); - } else if (envoy_config_route_v3_RouteMatch_has_path(match)) { - y_absl::string_view path = - UpbStringToAbsl(envoy_config_route_v3_RouteMatch_path(match)); - if (path.empty()) { - // Path that is empty will never match anything, so ignore this route. - *ignore_route = true; - return GRPC_ERROR_NONE; - } - if (path[0] != '/') { - // Path which does not start with a / will never match anything, so - // ignore this route. - *ignore_route = true; - return GRPC_ERROR_NONE; - } - std::vector<y_absl::string_view> path_elements = - y_absl::StrSplit(path.substr(1), y_absl::MaxSplits('/', 2)); - if (path_elements.size() != 2) { - // Path not in the required format of /service/method will never match - // anything, so ignore this route. - *ignore_route = true; - return GRPC_ERROR_NONE; - } else if (path_elements[0].empty()) { - // Path contains empty service name will never match anything, so ignore - // this route. - *ignore_route = true; - return GRPC_ERROR_NONE; - } else if (path_elements[1].empty()) { - // Path contains empty method name will never match anything, so ignore - // this route. - *ignore_route = true; - return GRPC_ERROR_NONE; - } - type = StringMatcher::Type::kExact; - match_string = TString(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::kSafeRegex; - match_string = UpbStringToStdString( - envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); - } else { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Invalid route path specifier specified."); - } - y_absl::StatusOr<StringMatcher> string_matcher = - StringMatcher::Create(type, match_string, case_sensitive); - if (!string_matcher.ok()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("path matcher: ", string_matcher.status().message())); - } - route->matchers.path_matcher = std::move(string_matcher.value()); - return GRPC_ERROR_NONE; -} - -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 = - envoy_config_route_v3_RouteMatch_headers(match, &size); - for (size_t i = 0; i < size; ++i) { - const envoy_config_route_v3_HeaderMatcher* header = headers[i]; - const TString name = - UpbStringToStdString(envoy_config_route_v3_HeaderMatcher_name(header)); - HeaderMatcher::Type type; - TString match_string; - int64_t range_start = 0; - int64_t range_end = 0; - bool present_match = false; - if (envoy_config_route_v3_HeaderMatcher_has_exact_match(header)) { - 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( - header)) { - 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::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::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::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::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::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::kContains; - match_string = UpbStringToStdString( - envoy_config_route_v3_HeaderMatcher_contains_match(header)); - } else { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Invalid route header matcher specified."); - } - bool invert_match = - envoy_config_route_v3_HeaderMatcher_invert_match(header); - y_absl::StatusOr<HeaderMatcher> header_matcher = - HeaderMatcher::Create(name, type, match_string, range_start, range_end, - present_match, invert_match); - if (!header_matcher.ok()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("header matcher: ", header_matcher.status().message())); - } - route->matchers.header_matchers.emplace_back( - std::move(header_matcher.value())); - } - return GRPC_ERROR_NONE; -} - -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); - if (runtime_fraction != nullptr) { - const envoy_type_v3_FractionalPercent* fraction = - envoy_config_core_v3_RuntimeFractionalPercent_default_value( - runtime_fraction); - if (fraction != nullptr) { - uint32_t numerator = envoy_type_v3_FractionalPercent_numerator(fraction); - const auto denominator = - static_cast<envoy_type_v3_FractionalPercent_DenominatorType>( - envoy_type_v3_FractionalPercent_denominator(fraction)); - // Normalize to million. - switch (denominator) { - case envoy_type_v3_FractionalPercent_HUNDRED: - numerator *= 10000; - break; - case envoy_type_v3_FractionalPercent_TEN_THOUSAND: - numerator *= 100; - break; - case envoy_type_v3_FractionalPercent_MILLION: - break; - default: - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Unknown denominator type"); - } - route->matchers.fraction_per_million = numerator; - } - } - return GRPC_ERROR_NONE; -} - -grpc_error_handle ExtractHttpFilterTypeName(const EncodingContext& context, - const google_protobuf_Any* any, - y_absl::string_view* filter_type) { - *filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any)); - if (*filter_type == "type.googleapis.com/xds.type.v3.TypedStruct" || - *filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") { - upb_strview any_value = google_protobuf_Any_value(any); - const auto* typed_struct = xds_type_v3_TypedStruct_parse( - any_value.data, any_value.size, context.arena); - if (typed_struct == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "could not parse TypedStruct from filter config"); - } - *filter_type = - UpbStringToAbsl(xds_type_v3_TypedStruct_type_url(typed_struct)); - } - *filter_type = y_absl::StripPrefix(*filter_type, "type.googleapis.com/"); - return GRPC_ERROR_NONE; -} - -template <typename ParentType, typename EntryType> -grpc_error_handle ParseTypedPerFilterConfig( - const EncodingContext& context, const ParentType* parent, - const EntryType* (*entry_func)(const ParentType*, size_t*), - upb_strview (*key_func)(const EntryType*), - const google_protobuf_Any* (*value_func)(const EntryType*), - XdsApi::TypedPerFilterConfig* typed_per_filter_config) { - size_t filter_it = UPB_MAP_BEGIN; - while (true) { - const auto* filter_entry = entry_func(parent, &filter_it); - if (filter_entry == nullptr) break; - y_absl::string_view key = UpbStringToAbsl(key_func(filter_entry)); - if (key.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("empty filter name in map"); - } - const google_protobuf_Any* any = value_func(filter_entry); - GPR_ASSERT(any != nullptr); - y_absl::string_view filter_type = - UpbStringToAbsl(google_protobuf_Any_type_url(any)); - if (filter_type.empty()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("no filter config specified for filter name ", key)); - } - bool is_optional = false; - if (filter_type == - "type.googleapis.com/envoy.config.route.v3.FilterConfig") { - upb_strview any_value = google_protobuf_Any_value(any); - const auto* filter_config = envoy_config_route_v3_FilterConfig_parse( - any_value.data, any_value.size, context.arena); - if (filter_config == nullptr) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("could not parse FilterConfig wrapper for ", key)); - } - 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_CPP_STRING( - y_absl::StrCat("no filter config specified for filter name ", key)); - } - } - 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 (is_optional) continue; - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("no filter registered for config type ", filter_type)); - } - y_absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config = - filter_impl->GenerateFilterConfigOverride( - google_protobuf_Any_value(any), context.arena); - if (!filter_config.ok()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "filter config for type ", filter_type, - " failed to parse: ", filter_config.status().ToString())); - } - (*typed_per_filter_config)[TString(key)] = std::move(*filter_config); - } - return GRPC_ERROR_NONE; -} - -XdsApi::Duration DurationParse(const google_protobuf_Duration* proto_duration) { - XdsApi::Duration duration; - duration.seconds = google_protobuf_Duration_seconds(proto_duration); - duration.nanos = google_protobuf_Duration_nanos(proto_duration); - return duration; -} - -grpc_error_handle RetryPolicyParse( - const EncodingContext& context, - const envoy_config_route_v3_RetryPolicy* retry_policy, - y_absl::optional<XdsApi::RetryPolicy>* retry) { - std::vector<grpc_error_handle> errors; - XdsApi::RetryPolicy retry_to_return; - auto retry_on = UpbStringToStdString( - envoy_config_route_v3_RetryPolicy_retry_on(retry_policy)); - std::vector<y_absl::string_view> codes = y_absl::StrSplit(retry_on, ','); - for (const auto& code : codes) { - if (code == "cancelled") { - retry_to_return.retry_on.Add(GRPC_STATUS_CANCELLED); - } else if (code == "deadline-exceeded") { - retry_to_return.retry_on.Add(GRPC_STATUS_DEADLINE_EXCEEDED); - } else if (code == "internal") { - retry_to_return.retry_on.Add(GRPC_STATUS_INTERNAL); - } else if (code == "resource-exhausted") { - retry_to_return.retry_on.Add(GRPC_STATUS_RESOURCE_EXHAUSTED); - } else if (code == "unavailable") { - retry_to_return.retry_on.Add(GRPC_STATUS_UNAVAILABLE); - } else { - if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { - gpr_log(GPR_INFO, "Unsupported retry_on policy %s.", - TString(code).c_str()); - } - } - } - const google_protobuf_UInt32Value* num_retries = - envoy_config_route_v3_RetryPolicy_num_retries(retry_policy); - if (num_retries != nullptr) { - uint32_t num_retries_value = google_protobuf_UInt32Value_value(num_retries); - if (num_retries_value == 0) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "RouteAction RetryPolicy num_retries set to invalid value 0.")); - } else { - retry_to_return.num_retries = num_retries_value; - } - } else { - retry_to_return.num_retries = 1; - } - const envoy_config_route_v3_RetryPolicy_RetryBackOff* backoff = - envoy_config_route_v3_RetryPolicy_retry_back_off(retry_policy); - if (backoff != nullptr) { - const google_protobuf_Duration* base_interval = - envoy_config_route_v3_RetryPolicy_RetryBackOff_base_interval(backoff); - if (base_interval == nullptr) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "RouteAction RetryPolicy RetryBackoff missing base interval.")); - } else { - retry_to_return.retry_back_off.base_interval = - DurationParse(base_interval); - } - const google_protobuf_Duration* max_interval = - envoy_config_route_v3_RetryPolicy_RetryBackOff_max_interval(backoff); - XdsApi::Duration max; - if (max_interval != nullptr) { - max = DurationParse(max_interval); - } else { - // if max interval is not set, it is 10x the base, if the value in nanos - // can yield another second, adjust the value in seconds accordingly. - max.seconds = retry_to_return.retry_back_off.base_interval.seconds * 10; - max.nanos = retry_to_return.retry_back_off.base_interval.nanos * 10; - if (max.nanos > 1000000000) { - max.seconds += max.nanos / 1000000000; - max.nanos = max.nanos % 1000000000; - } - } - retry_to_return.retry_back_off.max_interval = max; - } else { - retry_to_return.retry_back_off.base_interval.seconds = 0; - retry_to_return.retry_back_off.base_interval.nanos = 25000000; - retry_to_return.retry_back_off.max_interval.seconds = 0; - retry_to_return.retry_back_off.max_interval.nanos = 250000000; - } - if (errors.empty()) { - *retry = retry_to_return; - return GRPC_ERROR_NONE; - } else { - return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing retry policy", - &errors); - } -} - -grpc_error_handle RouteActionParse(const EncodingContext& context, - const envoy_config_route_v3_Route* route_msg, - XdsApi::Route::RouteAction* route, - bool* ignore_route) { - const envoy_config_route_v3_RouteAction* route_action = - envoy_config_route_v3_Route_route(route_msg); - // Get the cluster or weighted_clusters in the RouteAction. - if (envoy_config_route_v3_RouteAction_has_cluster(route_action)) { - route->cluster_name = UpbStringToStdString( - envoy_config_route_v3_RouteAction_cluster(route_action)); - if (route->cluster_name.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "RouteAction cluster contains empty cluster name."); - } - } else if (envoy_config_route_v3_RouteAction_has_weighted_clusters( - route_action)) { - const envoy_config_route_v3_WeightedCluster* weighted_cluster = - envoy_config_route_v3_RouteAction_weighted_clusters(route_action); - uint32_t total_weight = 100; - const google_protobuf_UInt32Value* weight = - envoy_config_route_v3_WeightedCluster_total_weight(weighted_cluster); - if (weight != nullptr) { - total_weight = google_protobuf_UInt32Value_value(weight); - } - size_t clusters_size; - const envoy_config_route_v3_WeightedCluster_ClusterWeight* const* clusters = - envoy_config_route_v3_WeightedCluster_clusters(weighted_cluster, - &clusters_size); - uint32_t sum_of_weights = 0; - for (size_t j = 0; j < clusters_size; ++j) { - const envoy_config_route_v3_WeightedCluster_ClusterWeight* - cluster_weight = clusters[j]; - XdsApi::Route::RouteAction::ClusterWeight cluster; - cluster.name = UpbStringToStdString( - envoy_config_route_v3_WeightedCluster_ClusterWeight_name( - cluster_weight)); - if (cluster.name.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "RouteAction weighted_cluster cluster contains empty cluster " - "name."); - } - const google_protobuf_UInt32Value* weight = - envoy_config_route_v3_WeightedCluster_ClusterWeight_weight( - cluster_weight); - if (weight == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "RouteAction weighted_cluster cluster missing weight"); - } - cluster.weight = google_protobuf_UInt32Value_value(weight); - if (cluster.weight == 0) continue; - sum_of_weights += cluster.weight; - 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, - envoy_config_route_v3_WeightedCluster_ClusterWeight_typed_per_filter_config_next, - envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_key, - envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_value, - &cluster.typed_per_filter_config); - if (error != GRPC_ERROR_NONE) return error; - } - route->weighted_clusters.emplace_back(std::move(cluster)); - } - if (total_weight != sum_of_weights) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "RouteAction weighted_cluster has incorrect total weight"); - } - if (route->weighted_clusters.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "RouteAction weighted_cluster has no valid clusters specified."); - } - } else { - // No cluster or weighted_clusters found in RouteAction, ignore this route. - *ignore_route = true; - } - if (!*ignore_route) { - const envoy_config_route_v3_RouteAction_MaxStreamDuration* - max_stream_duration = - envoy_config_route_v3_RouteAction_max_stream_duration(route_action); - if (max_stream_duration != nullptr) { - const google_protobuf_Duration* duration = - envoy_config_route_v3_RouteAction_MaxStreamDuration_grpc_timeout_header_max( - max_stream_duration); - if (duration == nullptr) { - duration = - envoy_config_route_v3_RouteAction_MaxStreamDuration_max_stream_duration( - max_stream_duration); - } - if (duration != nullptr) { - route->max_stream_duration = DurationParse(duration); - } - } - } - // Get HashPolicy from RouteAction - 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::RouteAction::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::RouteAction::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) { - 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 = y_absl::make_unique<RE2>( - 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) { - TString key = UpbStringToStdString( - envoy_config_route_v3_RouteAction_HashPolicy_FilterState_key( - filter_state)); - if (key == "io.grpc.channel_id") { - policy.type = XdsApi::Route::RouteAction::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)); - } - // Get retry policy - const envoy_config_route_v3_RetryPolicy* retry_policy = - envoy_config_route_v3_RouteAction_retry_policy(route_action); - if (retry_policy != nullptr) { - y_absl::optional<XdsApi::RetryPolicy> retry; - grpc_error_handle error = RetryPolicyParse(context, retry_policy, &retry); - if (error != GRPC_ERROR_NONE) return error; - route->retry_policy = retry; - } - return GRPC_ERROR_NONE; -} - -grpc_error_handle RouteConfigParse( - const EncodingContext& context, - const envoy_config_route_v3_RouteConfiguration* route_config, - bool /*is_v2*/, XdsApi::RdsUpdate* rds_update) { - // Get the virtual hosts. - size_t num_virtual_hosts; - const envoy_config_route_v3_VirtualHost* const* virtual_hosts = - envoy_config_route_v3_RouteConfiguration_virtual_hosts( - route_config, &num_virtual_hosts); - for (size_t i = 0; i < num_virtual_hosts; ++i) { - rds_update->virtual_hosts.emplace_back(); - XdsApi::RdsUpdate::VirtualHost& vhost = rds_update->virtual_hosts.back(); - // Parse domains. - size_t domain_size; - upb_strview const* domains = envoy_config_route_v3_VirtualHost_domains( - virtual_hosts[i], &domain_size); - for (size_t j = 0; j < domain_size; ++j) { - TString domain_pattern = UpbStringToStdString(domains[j]); - if (!XdsRouting::IsValidDomainPattern(domain_pattern)) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("Invalid domain pattern \"", domain_pattern, "\".")); - } - vhost.domains.emplace_back(std::move(domain_pattern)); - } - if (vhost.domains.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("VirtualHost has no domains"); - } - // Parse typed_per_filter_config. - if (context.use_v3) { - grpc_error_handle error = ParseTypedPerFilterConfig< - envoy_config_route_v3_VirtualHost, - envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry>( - context, virtual_hosts[i], - envoy_config_route_v3_VirtualHost_typed_per_filter_config_next, - envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_key, - envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_value, - &vhost.typed_per_filter_config); - if (error != GRPC_ERROR_NONE) return error; - } - // Parse retry policy. - y_absl::optional<XdsApi::RetryPolicy> virtual_host_retry_policy; - const envoy_config_route_v3_RetryPolicy* retry_policy = - envoy_config_route_v3_VirtualHost_retry_policy(virtual_hosts[i]); - if (retry_policy != nullptr) { - grpc_error_handle error = - RetryPolicyParse(context, retry_policy, &virtual_host_retry_policy); - if (error != GRPC_ERROR_NONE) return error; - } - // Parse routes. - size_t num_routes; - const envoy_config_route_v3_Route* const* routes = - envoy_config_route_v3_VirtualHost_routes(virtual_hosts[i], &num_routes); - if (num_routes < 1) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "No route found in the virtual host."); - } - // Loop over the whole list of routes - 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<void>(envoy_config_route_v3_RouteMatch_query_parameters( - match, &query_parameters_size)); - if (query_parameters_size > 0) { - continue; - } - XdsApi::Route route; - bool ignore_route = false; - grpc_error_handle error = - RoutePathMatchParse(match, &route, &ignore_route); - if (error != GRPC_ERROR_NONE) return error; - if (ignore_route) continue; - error = RouteHeaderMatchersParse(match, &route); - if (error != GRPC_ERROR_NONE) return error; - error = RouteRuntimeFractionParse(match, &route); - if (error != GRPC_ERROR_NONE) return error; - if (envoy_config_route_v3_Route_has_route(routes[j])) { - route.action.emplace<XdsApi::Route::RouteAction>(); - auto& route_action = - y_absl::get<XdsApi::Route::RouteAction>(route.action); - error = - RouteActionParse(context, routes[j], &route_action, &ignore_route); - if (error != GRPC_ERROR_NONE) return error; - if (ignore_route) continue; - if (route_action.retry_policy == y_absl::nullopt && - retry_policy != nullptr) { - route_action.retry_policy = virtual_host_retry_policy; - } - } else if (envoy_config_route_v3_Route_has_non_forwarding_action( - routes[j])) { - route.action.emplace<XdsApi::Route::NonForwardingAction>(); - } - if (context.use_v3) { - grpc_error_handle error = ParseTypedPerFilterConfig< - envoy_config_route_v3_Route, - envoy_config_route_v3_Route_TypedPerFilterConfigEntry>( - context, routes[j], - envoy_config_route_v3_Route_typed_per_filter_config_next, - envoy_config_route_v3_Route_TypedPerFilterConfigEntry_key, - envoy_config_route_v3_Route_TypedPerFilterConfigEntry_value, - &route.typed_per_filter_config); - if (error != GRPC_ERROR_NONE) return error; - } - vhost.routes.emplace_back(std::move(route)); - } - if (vhost.routes.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid routes specified."); - } - } - return GRPC_ERROR_NONE; -} - -// CertificateProviderInstance is deprecated but we are still supporting it for -// backward compatibility reasons. Note that we still parse the data into the -// same CertificateProviderPluginInstance struct since the fields are the same. -// TODO(yashykt): Remove this once we stop supporting the old way of fetching -// certificate provider instances. -grpc_error_handle CertificateProviderInstanceParse( - const EncodingContext& context, - const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance* - certificate_provider_instance_proto, - XdsApi::CommonTlsContext::CertificateProviderPluginInstance* - certificate_provider_plugin_instance) { - *certificate_provider_plugin_instance = { - UpbStringToStdString( - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance_instance_name( - certificate_provider_instance_proto)), - UpbStringToStdString( - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance_certificate_name( - certificate_provider_instance_proto))}; - if (context.certificate_provider_definition_map->find( - certificate_provider_plugin_instance->instance_name) == - context.certificate_provider_definition_map->end()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("Unrecognized certificate provider instance name: ", - certificate_provider_plugin_instance->instance_name)); - } - return GRPC_ERROR_NONE; -} - -grpc_error_handle CertificateProviderPluginInstanceParse( - const EncodingContext& context, - const envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance* - certificate_provider_plugin_instance_proto, - XdsApi::CommonTlsContext::CertificateProviderPluginInstance* - certificate_provider_plugin_instance) { - *certificate_provider_plugin_instance = { - UpbStringToStdString( - envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance_instance_name( - certificate_provider_plugin_instance_proto)), - UpbStringToStdString( - envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance_certificate_name( - certificate_provider_plugin_instance_proto))}; - if (context.certificate_provider_definition_map->find( - certificate_provider_plugin_instance->instance_name) == - context.certificate_provider_definition_map->end()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("Unrecognized certificate provider instance name: ", - certificate_provider_plugin_instance->instance_name)); - } - return GRPC_ERROR_NONE; -} - -grpc_error_handle CertificateValidationContextParse( - const EncodingContext& context, - const envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext* - certificate_validation_context_proto, - XdsApi::CommonTlsContext::CertificateValidationContext* - certificate_validation_context) { - std::vector<grpc_error_handle> errors; - size_t len = 0; - auto* subject_alt_names_matchers = - envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_match_subject_alt_names( - certificate_validation_context_proto, &len); - for (size_t i = 0; i < len; ++i) { - StringMatcher::Type type; - TString matcher; - if (envoy_type_matcher_v3_StringMatcher_has_exact( - subject_alt_names_matchers[i])) { - 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::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::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::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::kSafeRegex; - auto* regex_matcher = envoy_type_matcher_v3_StringMatcher_safe_regex( - subject_alt_names_matchers[i]); - matcher = UpbStringToStdString( - envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); - } else { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Invalid StringMatcher specified")); - continue; - } - bool ignore_case = envoy_type_matcher_v3_StringMatcher_ignore_case( - subject_alt_names_matchers[i]); - y_absl::StatusOr<StringMatcher> string_matcher = - StringMatcher::Create(type, matcher, - /*case_sensitive=*/!ignore_case); - if (!string_matcher.ok()) { - errors.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("string matcher: ", string_matcher.status().message()))); - continue; - } - if (type == StringMatcher::Type::kSafeRegex && ignore_case) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "StringMatcher: ignore_case has no effect for SAFE_REGEX.")); - continue; - } - certificate_validation_context->match_subject_alt_names.push_back( - std::move(string_matcher.value())); - } - auto* ca_certificate_provider_instance = - envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_ca_certificate_provider_instance( - certificate_validation_context_proto); - if (ca_certificate_provider_instance != nullptr) { - grpc_error_handle error = CertificateProviderPluginInstanceParse( - context, ca_certificate_provider_instance, - &certificate_validation_context->ca_certificate_provider_instance); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_spki( - certificate_validation_context_proto, nullptr) != nullptr) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: verify_certificate_spki " - "unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_hash( - certificate_validation_context_proto, nullptr) != nullptr) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: verify_certificate_hash " - "unsupported")); - } - auto* require_signed_certificate_timestamp = - envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_require_signed_certificate_timestamp( - certificate_validation_context_proto); - if (require_signed_certificate_timestamp != nullptr && - google_protobuf_BoolValue_value(require_signed_certificate_timestamp)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: " - "require_signed_certificate_timestamp unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_crl( - certificate_validation_context_proto)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: crl unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_custom_validator_config( - certificate_validation_context_proto)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "CertificateValidationContext: custom_validator_config " - "unsupported")); - } - return GRPC_ERROR_CREATE_FROM_VECTOR( - "Error parsing CertificateValidationContext", &errors); -} - -grpc_error_handle CommonTlsContextParse( - const EncodingContext& context, - const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext* - common_tls_context_proto, - XdsApi::CommonTlsContext* common_tls_context) { - std::vector<grpc_error_handle> errors; - // The validation context is derived from the oneof in - // 'validation_context_type'. 'validation_context_sds_secret_config' is not - // supported. - auto* combined_validation_context = - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_combined_validation_context( - common_tls_context_proto); - if (combined_validation_context != nullptr) { - auto* default_validation_context = - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CombinedCertificateValidationContext_default_validation_context( - combined_validation_context); - if (default_validation_context != nullptr) { - grpc_error_handle error = CertificateValidationContextParse( - context, default_validation_context, - &common_tls_context->certificate_validation_context); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } - // If after parsing default_validation_context, - // common_tls_context->certificate_validation_context.ca_certificate_provider_instance - // is empty, fall back onto - // 'validation_context_certificate_provider_instance' inside - // 'combined_validation_context'. Note that this way of fetching root - // certificates is deprecated and will be removed in the future. - // TODO(yashykt): Remove this once it's no longer needed. - auto* validation_context_certificate_provider_instance = - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CombinedCertificateValidationContext_validation_context_certificate_provider_instance( - combined_validation_context); - if (common_tls_context->certificate_validation_context - .ca_certificate_provider_instance.Empty() && - validation_context_certificate_provider_instance != nullptr) { - grpc_error_handle error = CertificateProviderInstanceParse( - context, validation_context_certificate_provider_instance, - &common_tls_context->certificate_validation_context - .ca_certificate_provider_instance); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } - } else { - auto* validation_context = - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_validation_context( - common_tls_context_proto); - if (validation_context != nullptr) { - grpc_error_handle error = CertificateValidationContextParse( - context, validation_context, - &common_tls_context->certificate_validation_context); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } else if ( - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_validation_context_sds_secret_config( - common_tls_context_proto)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "validation_context_sds_secret_config unsupported")); - } - } - auto* tls_certificate_provider_instance = - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_tls_certificate_provider_instance( - common_tls_context_proto); - if (tls_certificate_provider_instance != nullptr) { - grpc_error_handle error = CertificateProviderPluginInstanceParse( - context, tls_certificate_provider_instance, - &common_tls_context->tls_certificate_provider_instance); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } else { - // Fall back onto 'tls_certificate_certificate_provider_instance'. Note that - // this way of fetching identity certificates is deprecated and will be - // removed in the future. - // TODO(yashykt): Remove this once it's no longer needed. - auto* tls_certificate_certificate_provider_instance = - envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_tls_certificate_certificate_provider_instance( - common_tls_context_proto); - if (tls_certificate_certificate_provider_instance != nullptr) { - grpc_error_handle error = CertificateProviderInstanceParse( - context, tls_certificate_certificate_provider_instance, - &common_tls_context->tls_certificate_provider_instance); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } else { - if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_certificates( - common_tls_context_proto)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "tls_certificates unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_certificate_sds_secret_configs( - common_tls_context_proto)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "tls_certificate_sds_secret_configs unsupported")); - } - } - } - if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_params( - common_tls_context_proto)) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("tls_params unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_custom_handshaker( - common_tls_context_proto)) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("custom_handshaker unsupported")); - } - return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing CommonTlsContext", - &errors); -} - -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 = - DurationParse(duration); - } - } - // Parse filters. - 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_proto, &num_filters); - std::set<y_absl::string_view> names_seen; - for (size_t i = 0; i < num_filters; ++i) { - const auto* http_filter = http_filters[i]; - y_absl::string_view name = UpbStringToAbsl( - envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_name( - http_filter)); - if (name.empty()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("empty filter name at index ", i)); - } - if (names_seen.find(name) != names_seen.end()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("duplicate HTTP filter name: ", name)); - } - 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_CPP_STRING( - y_absl::StrCat("no filter config specified for filter name ", name)); - } - y_absl::string_view 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 (is_optional) continue; - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("no filter registered for config type ", filter_type)); - } - if ((is_client && !filter_impl->IsSupportedOnClients()) || - (!is_client && !filter_impl->IsSupportedOnServers())) { - if (is_optional) continue; - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrFormat("Filter %s is not supported on %s", filter_type, - is_client ? "clients" : "servers")); - } - y_absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config = - filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any), - context.arena); - if (!filter_config.ok()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "filter config for type ", filter_type, - " failed to parse: ", filter_config.status().ToString())); - } - http_connection_manager->http_filters.emplace_back( - XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter{ - TString(name), std::move(*filter_config)}); - } - if (http_connection_manager->http_filters.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Expected at least one HTTP filter"); - } - // Make sure that the last filter is terminal and non-last filters are - // non-terminal. Note that this check is being performed in a separate loop - // to take care of the case where there are two terminal filters in the list - // out of which only one gets added in the final list. - for (const auto& http_filter : http_connection_manager->http_filters) { - const XdsHttpFilterImpl* filter_impl = - XdsHttpFilterRegistry::GetFilterForType( - http_filter.config.config_proto_type_name); - if (&http_filter != &http_connection_manager->http_filters.back()) { - // Filters before the last filter must not be terminal. - if (filter_impl->IsTerminalFilter()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("terminal filter for config type ", - http_filter.config.config_proto_type_name, - " must be the last filter in the chain")); - } - } else { - // The last filter must be terminal. - if (!filter_impl->IsTerminalFilter()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("non-terminal filter for config type ", - http_filter.config.config_proto_type_name, - " is the last filter in the chain")); - } - } - } - } 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()}}); - } - // Guarding parsing of RouteConfig on the server side with the environmental - // variable since that's the first feature on the server side that will be - // using this. - if (is_client || XdsRbacEnabled()) { - // 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, is_v2, &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)); - } - return GRPC_ERROR_NONE; -} - -grpc_error_handle LdsResourceParseClient( - 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 HttpConnectionManagerParse(true /* is_client */, context, - http_connection_manager, is_v2, - &lds_update->http_connection_manager); -} - -grpc_error_handle DownstreamTlsContextParse( - const EncodingContext& context, - const envoy_config_core_v3_TransportSocket* transport_socket, - XdsApi::DownstreamTlsContext* downstream_tls_context) { - y_absl::string_view name = UpbStringToAbsl( - envoy_config_core_v3_TransportSocket_name(transport_socket)); - if (name != "envoy.transport_sockets.tls") { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("Unrecognized transport socket: ", name)); - } - auto* typed_config = - envoy_config_core_v3_TransportSocket_typed_config(transport_socket); - std::vector<grpc_error_handle> errors; - if (typed_config != nullptr) { - const upb_strview encoded_downstream_tls_context = - google_protobuf_Any_value(typed_config); - auto* downstream_tls_context_proto = - envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_parse( - encoded_downstream_tls_context.data, - encoded_downstream_tls_context.size, context.arena); - if (downstream_tls_context_proto == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Can't decode downstream tls context."); - } - auto* common_tls_context = - envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_common_tls_context( - downstream_tls_context_proto); - if (common_tls_context != nullptr) { - grpc_error_handle error = - CommonTlsContextParse(context, common_tls_context, - &downstream_tls_context->common_tls_context); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } - auto* require_client_certificate = - envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_require_client_certificate( - downstream_tls_context_proto); - if (require_client_certificate != nullptr) { - downstream_tls_context->require_client_certificate = - google_protobuf_BoolValue_value(require_client_certificate); - } - auto* require_sni = - envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_require_sni( - downstream_tls_context_proto); - if (require_sni != nullptr && - google_protobuf_BoolValue_value(require_sni)) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("require_sni: unsupported")); - } - if (envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_ocsp_staple_policy( - downstream_tls_context_proto) != - envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_LENIENT_STAPLING) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "ocsp_staple_policy: Only LENIENT_STAPLING supported")); - } - } - if (downstream_tls_context->common_tls_context - .tls_certificate_provider_instance.instance_name.empty()) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "TLS configuration provided but no " - "tls_certificate_provider_instance found.")); - } - if (downstream_tls_context->require_client_certificate && - downstream_tls_context->common_tls_context.certificate_validation_context - .ca_certificate_provider_instance.instance_name.empty()) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "TLS configuration requires client certificates but no certificate " - "provider instance specified for validation.")); - } - if (!downstream_tls_context->common_tls_context.certificate_validation_context - .match_subject_alt_names.empty()) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "match_subject_alt_names not supported on servers")); - } - return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing DownstreamTlsContext", - &errors); -} - -grpc_error_handle CidrRangeParse( - const envoy_config_core_v3_CidrRange* cidr_range_proto, - XdsApi::LdsUpdate::FilterChainMap::CidrRange* cidr_range) { - TString 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<const grpc_sockaddr*>(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<XdsApi::LdsUpdate::FilterChainMap::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++) { - 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, bool is_v2, - FilterChain* filter_chain) { - std::vector<grpc_error_handle> errors; - auto* filter_chain_match = - envoy_config_listener_v3_FilterChain_filter_chain_match( - filter_chain_proto); - if (filter_chain_match != nullptr) { - grpc_error_handle error = FilterChainMatchParse( - filter_chain_match, &filter_chain->filter_chain_match); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } - filter_chain->filter_chain_data = - std::make_shared<XdsApi::LdsUpdate::FilterChainData>(); - // 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) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "FilterChain should have exactly one filter: HttpConnectionManager; no " - "other filter is supported at the moment")); - } else { - auto* typed_config = - envoy_config_listener_v3_Filter_typed_config(filters[0]); - if (typed_config == nullptr) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "No typed_config found in filter.")); - } else { - y_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") { - errors.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("Unsupported filter type ", type_url))); - } else { - 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) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Could not parse HttpConnectionManager config from filter " - "typed_config")); - } else { - grpc_error_handle error = HttpConnectionManagerParse( - false /* is_client */, context, http_connection_manager, is_v2, - &filter_chain->filter_chain_data->http_connection_manager); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } - } - } - } - auto* transport_socket = - envoy_config_listener_v3_FilterChain_transport_socket(filter_chain_proto); - if (transport_socket != nullptr) { - grpc_error_handle error = DownstreamTlsContextParse( - context, transport_socket, - &filter_chain->filter_chain_data->downstream_tls_context); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } - return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing FilterChain", &errors); -} - -grpc_error_handle AddressParse( - const envoy_config_core_v3_Address* address_proto, TString* address) { - const auto* socket_address = - envoy_config_core_v3_Address_socket_address(address_proto); - if (socket_address == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_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; -} - -// 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<TString, XdsApi::LdsUpdate::FilterChainMap::SourceIp>; - using ConnectionSourceTypesArray = std::array<SourceIpMap, 3>; - struct DestinationIp { - y_absl::optional<XdsApi::LdsUpdate::FilterChainMap::CidrRange> prefix_range; - bool transport_protocol_raw_buffer_provided = false; - ConnectionSourceTypesArray source_types_array; - }; - using DestinationIpMap = std::map<TString, DestinationIp>; - 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_CPP_STRING(y_absl::StrCat( - "Duplicate matching rules detected when adding filter chain: ", - filter_chain.filter_chain_match.ToString())); - } - 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( - y_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<unsigned int>( - filter_chain.filter_chain_match.source_type) < 3); - return AddFilterChainDataForSourceIpRange( - filter_chain, &destination_ip->source_types_array[static_cast<int>( - 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 TString& 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( - y_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<FilterChain>& 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 LdsResourceParseServer( - const EncodingContext& context, - const envoy_config_listener_v3_Listener* listener, bool is_v2, - XdsApi::LdsUpdate* lds_update) { - lds_update->type = XdsApi::LdsUpdate::ListenerType::kTcpListener; - 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); - std::vector<FilterChain> parsed_filter_chains; - parsed_filter_chains.reserve(size); - for (size_t i = 0; i < size; i++) { - 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) { - 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) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No filter chain provided."); - } - return GRPC_ERROR_NONE; -} - -grpc_error_handle LdsResourceParse( - const EncodingContext& context, - const envoy_config_listener_v3_Listener* listener, bool is_v2, - XdsApi::LdsUpdate* lds_update) { - // 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); - const envoy_config_core_v3_Address* address = - envoy_config_listener_v3_Listener_address(listener); - if (api_listener != nullptr && address != nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Listener has both address and ApiListener"); - } - if (api_listener == nullptr && address == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Listener has neither address nor ApiListener"); - } - // Validate Listener fields. - grpc_error_handle error = GRPC_ERROR_NONE; - if (api_listener != nullptr) { - error = LdsResourceParseClient(context, api_listener, is_v2, lds_update); - } else { - error = LdsResourceParseServer(context, listener, is_v2, lds_update); - } - return error; -} - -grpc_error_handle UpstreamTlsContextParse( - const EncodingContext& context, - const envoy_config_core_v3_TransportSocket* transport_socket, - XdsApi::CommonTlsContext* common_tls_context) { - // Record Upstream tls context - y_absl::string_view name = UpbStringToAbsl( - envoy_config_core_v3_TransportSocket_name(transport_socket)); - if (name != "envoy.transport_sockets.tls") { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("Unrecognized transport socket: ", name)); - } - auto* typed_config = - envoy_config_core_v3_TransportSocket_typed_config(transport_socket); - if (typed_config != nullptr) { - const upb_strview encoded_upstream_tls_context = - google_protobuf_Any_value(typed_config); - auto* upstream_tls_context = - envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_parse( - encoded_upstream_tls_context.data, - encoded_upstream_tls_context.size, context.arena); - if (upstream_tls_context == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Can't decode upstream tls context."); - } - auto* common_tls_context_proto = - envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_common_tls_context( - upstream_tls_context); - if (common_tls_context_proto != nullptr) { - grpc_error_handle error = CommonTlsContextParse( - context, common_tls_context_proto, common_tls_context); - if (error != GRPC_ERROR_NONE) { - return grpc_error_add_child(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Error parsing UpstreamTlsContext"), - error); - } - } - } - if (common_tls_context->certificate_validation_context - .ca_certificate_provider_instance.instance_name.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "UpstreamTlsContext: TLS configuration provided but no " - "ca_certificate_provider_instance found."); - } - return GRPC_ERROR_NONE; -} - -grpc_error_handle CdsLogicalDnsParse( - const envoy_config_cluster_v3_Cluster* cluster, - XdsApi::CdsUpdate* cds_update) { - const auto* load_assignment = - envoy_config_cluster_v3_Cluster_load_assignment(cluster); - if (load_assignment == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "load_assignment not present for LOGICAL_DNS cluster"); - } - size_t num_localities; - const auto* const* localities = - envoy_config_endpoint_v3_ClusterLoadAssignment_endpoints(load_assignment, - &num_localities); - if (num_localities != 1) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("load_assignment for LOGICAL_DNS cluster must have " - "exactly one locality, found ", - num_localities)); - } - size_t num_endpoints; - const auto* const* endpoints = - envoy_config_endpoint_v3_LocalityLbEndpoints_lb_endpoints(localities[0], - &num_endpoints); - if (num_endpoints != 1) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("locality for LOGICAL_DNS cluster must have " - "exactly one endpoint, found ", - num_endpoints)); - } - const auto* endpoint = - envoy_config_endpoint_v3_LbEndpoint_endpoint(endpoints[0]); - if (endpoint == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "LbEndpoint endpoint field not set"); - } - const auto* address = envoy_config_endpoint_v3_Endpoint_address(endpoint); - if (address == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Endpoint address field not set"); - } - const auto* socket_address = - envoy_config_core_v3_Address_socket_address(address); - if (socket_address == nullptr) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Address socket_address field not set"); - } - if (envoy_config_core_v3_SocketAddress_resolver_name(socket_address).size != - 0) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "LOGICAL_DNS clusters must NOT have a custom resolver name set"); - } - y_absl::string_view address_str = UpbStringToAbsl( - envoy_config_core_v3_SocketAddress_address(socket_address)); - if (address_str.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "SocketAddress address field not set"); - } - if (!envoy_config_core_v3_SocketAddress_has_port_value(socket_address)) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "SocketAddress port_value field not set"); - } - cds_update->dns_hostname = JoinHostPort( - address_str, - envoy_config_core_v3_SocketAddress_port_value(socket_address)); - return GRPC_ERROR_NONE; -} - -grpc_error_handle CdsResourceParse( - const EncodingContext& context, - const envoy_config_cluster_v3_Cluster* cluster, bool /*is_v2*/, - XdsApi::CdsUpdate* cds_update) { - std::vector<grpc_error_handle> errors; - // Check the cluster_discovery_type. - if (!envoy_config_cluster_v3_Cluster_has_type(cluster) && - !envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType not found.")); - } else if (envoy_config_cluster_v3_Cluster_type(cluster) == - envoy_config_cluster_v3_Cluster_EDS) { - cds_update->cluster_type = XdsApi::CdsUpdate::ClusterType::EDS; - // Check the EDS config source. - const envoy_config_cluster_v3_Cluster_EdsClusterConfig* eds_cluster_config = - envoy_config_cluster_v3_Cluster_eds_cluster_config(cluster); - const envoy_config_core_v3_ConfigSource* eds_config = - envoy_config_cluster_v3_Cluster_EdsClusterConfig_eds_config( - eds_cluster_config); - if (!envoy_config_core_v3_ConfigSource_has_ads(eds_config)) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("EDS ConfigSource is not ADS.")); - } - // Record EDS service_name (if any). - upb_strview service_name = - envoy_config_cluster_v3_Cluster_EdsClusterConfig_service_name( - eds_cluster_config); - if (service_name.size != 0) { - cds_update->eds_service_name = UpbStringToStdString(service_name); - } - } else if (!XdsAggregateAndLogicalDnsClusterEnabled()) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType is not valid.")); - } else if (envoy_config_cluster_v3_Cluster_type(cluster) == - envoy_config_cluster_v3_Cluster_LOGICAL_DNS) { - cds_update->cluster_type = XdsApi::CdsUpdate::ClusterType::LOGICAL_DNS; - grpc_error_handle error = CdsLogicalDnsParse(cluster, cds_update); - if (error != GRPC_ERROR_NONE) errors.push_back(error); - } else { - if (!envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType is not valid.")); - } else { - const envoy_config_cluster_v3_Cluster_CustomClusterType* - custom_cluster_type = - envoy_config_cluster_v3_Cluster_cluster_type(cluster); - upb_strview type_name = - envoy_config_cluster_v3_Cluster_CustomClusterType_name( - custom_cluster_type); - if (UpbStringToAbsl(type_name) != "envoy.clusters.aggregate") { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "DiscoveryType is not valid.")); - } else { - cds_update->cluster_type = XdsApi::CdsUpdate::ClusterType::AGGREGATE; - // Retrieve aggregate clusters. - const google_protobuf_Any* typed_config = - envoy_config_cluster_v3_Cluster_CustomClusterType_typed_config( - custom_cluster_type); - const upb_strview aggregate_cluster_config_upb_strview = - google_protobuf_Any_value(typed_config); - const envoy_extensions_clusters_aggregate_v3_ClusterConfig* - aggregate_cluster_config = - envoy_extensions_clusters_aggregate_v3_ClusterConfig_parse( - aggregate_cluster_config_upb_strview.data, - aggregate_cluster_config_upb_strview.size, context.arena); - if (aggregate_cluster_config == nullptr) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Can't parse aggregate cluster.")); - } else { - size_t size; - const upb_strview* clusters = - envoy_extensions_clusters_aggregate_v3_ClusterConfig_clusters( - aggregate_cluster_config, &size); - for (size_t i = 0; i < size; ++i) { - const upb_strview cluster = clusters[i]; - cds_update->prioritized_cluster_names.emplace_back( - UpbStringToStdString(cluster)); - } - } - } - } - } - // Check the LB policy. - if (envoy_config_cluster_v3_Cluster_lb_policy(cluster) == - envoy_config_cluster_v3_Cluster_ROUND_ROBIN) { - cds_update->lb_policy = "ROUND_ROBIN"; - } else if (envoy_config_cluster_v3_Cluster_lb_policy(cluster) == - envoy_config_cluster_v3_Cluster_RING_HASH) { - cds_update->lb_policy = "RING_HASH"; - // Record ring hash lb config - auto* ring_hash_config = - envoy_config_cluster_v3_Cluster_ring_hash_lb_config(cluster); - if (ring_hash_config != nullptr) { - const google_protobuf_UInt64Value* max_ring_size = - envoy_config_cluster_v3_Cluster_RingHashLbConfig_maximum_ring_size( - ring_hash_config); - if (max_ring_size != nullptr) { - cds_update->max_ring_size = - google_protobuf_UInt64Value_value(max_ring_size); - if (cds_update->max_ring_size > 8388608 || - cds_update->max_ring_size == 0) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "max_ring_size is not in the range of 1 to 8388608.")); - } - } - const google_protobuf_UInt64Value* min_ring_size = - envoy_config_cluster_v3_Cluster_RingHashLbConfig_minimum_ring_size( - ring_hash_config); - if (min_ring_size != nullptr) { - cds_update->min_ring_size = - google_protobuf_UInt64Value_value(min_ring_size); - if (cds_update->min_ring_size > 8388608 || - cds_update->min_ring_size == 0) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "min_ring_size is not in the range of 1 to 8388608.")); - } - if (cds_update->min_ring_size > cds_update->max_ring_size) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "min_ring_size cannot be greater than max_ring_size.")); - } - } - if (envoy_config_cluster_v3_Cluster_RingHashLbConfig_hash_function( - ring_hash_config) != - envoy_config_cluster_v3_Cluster_RingHashLbConfig_XX_HASH) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "ring hash lb config has invalid hash function.")); - } - } - } else { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("LB policy is not supported.")); - } - auto* transport_socket = - envoy_config_cluster_v3_Cluster_transport_socket(cluster); - if (transport_socket != nullptr) { - grpc_error_handle error = UpstreamTlsContextParse( - context, transport_socket, &cds_update->common_tls_context); - if (error != GRPC_ERROR_NONE) { - errors.push_back( - grpc_error_add_child(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Error parsing security configuration"), - error)); - } - } - // Record LRS server name (if any). - const envoy_config_core_v3_ConfigSource* lrs_server = - envoy_config_cluster_v3_Cluster_lrs_server(cluster); - if (lrs_server != nullptr) { - if (!envoy_config_core_v3_ConfigSource_has_self(lrs_server)) { - errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - ": LRS ConfigSource is not self.")); - } - cds_update->lrs_load_reporting_server_name.emplace(""); - } - // The Cluster resource encodes the circuit breaking parameters in a list of - // Thresholds messages, where each message specifies the parameters for a - // particular RoutingPriority. we will look only at the first entry in the - // list for priority DEFAULT and default to 1024 if not found. - if (envoy_config_cluster_v3_Cluster_has_circuit_breakers(cluster)) { - const envoy_config_cluster_v3_CircuitBreakers* circuit_breakers = - envoy_config_cluster_v3_Cluster_circuit_breakers(cluster); - size_t num_thresholds; - const envoy_config_cluster_v3_CircuitBreakers_Thresholds* const* - thresholds = envoy_config_cluster_v3_CircuitBreakers_thresholds( - circuit_breakers, &num_thresholds); - for (size_t i = 0; i < num_thresholds; ++i) { - const auto* threshold = thresholds[i]; - if (envoy_config_cluster_v3_CircuitBreakers_Thresholds_priority( - threshold) == envoy_config_core_v3_DEFAULT) { - const google_protobuf_UInt32Value* max_requests = - envoy_config_cluster_v3_CircuitBreakers_Thresholds_max_requests( - threshold); - if (max_requests != nullptr) { - cds_update->max_concurrent_requests = - google_protobuf_UInt32Value_value(max_requests); - } - break; - } - } - } - return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing CDS resource", &errors); -} - -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. - const int32_t health_status = - envoy_config_endpoint_v3_LbEndpoint_health_status(lb_endpoint); - if (health_status != envoy_config_core_v3_UNKNOWN && - health_status != envoy_config_core_v3_HEALTHY) { - return GRPC_ERROR_NONE; - } - // Find the ip:port. - const envoy_config_endpoint_v3_Endpoint* endpoint = - envoy_config_endpoint_v3_LbEndpoint_endpoint(lb_endpoint); - const envoy_config_core_v3_Address* address = - envoy_config_endpoint_v3_Endpoint_address(endpoint); - const envoy_config_core_v3_SocketAddress* socket_address = - envoy_config_core_v3_Address_socket_address(address); - TString address_str = UpbStringToStdString( - envoy_config_core_v3_SocketAddress_address(socket_address)); - uint32_t port = envoy_config_core_v3_SocketAddress_port_value(socket_address); - if (GPR_UNLIKELY(port >> 16) != 0) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Invalid port."); - } - // Find load_balancing_weight for the endpoint. - const google_protobuf_UInt32Value* load_balancing_weight = - envoy_config_endpoint_v3_LbEndpoint_load_balancing_weight(lb_endpoint); - const int32_t weight = - load_balancing_weight != nullptr - ? google_protobuf_UInt32Value_value(load_balancing_weight) - : 500; - if (weight == 0) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Invalid endpoint weight of 0."); - } - // Populate grpc_resolved_address. - grpc_resolved_address addr; - 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. - std::map<const char*, std::unique_ptr<ServerAddress::AttributeInterface>> - attributes; - attributes[ServerAddressWeightAttribute::kServerAddressWeightAttributeKey] = - y_absl::make_unique<ServerAddressWeightAttribute>(weight); - list->emplace_back(addr, nullptr, std::move(attributes)); - return GRPC_ERROR_NONE; -} - -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. - const google_protobuf_UInt32Value* lb_weight = - envoy_config_endpoint_v3_LocalityLbEndpoints_load_balancing_weight( - locality_lb_endpoints); - // If LB weight is not specified, it means this locality is assigned no load. - // TODO(juanlishen): When we support CDS to configure the inter-locality - // policy, we should change the LB weight handling. - output_locality->lb_weight = - lb_weight != nullptr ? google_protobuf_UInt32Value_value(lb_weight) : 0; - if (output_locality->lb_weight == 0) return GRPC_ERROR_NONE; - // Parse locality name. - 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."); - } - TString region = - UpbStringToStdString(envoy_config_core_v3_Locality_region(locality)); - TString zone = - UpbStringToStdString(envoy_config_core_v3_Locality_region(locality)); - TString sub_zone = - UpbStringToStdString(envoy_config_core_v3_Locality_sub_zone(locality)); - output_locality->name = MakeRefCounted<XdsLocalityName>( - std::move(region), std::move(zone), std::move(sub_zone)); - // Parse the addresses. - size_t size; - const envoy_config_endpoint_v3_LbEndpoint* const* lb_endpoints = - envoy_config_endpoint_v3_LocalityLbEndpoints_lb_endpoints( - locality_lb_endpoints, &size); - for (size_t i = 0; i < size; ++i) { - grpc_error_handle error = ServerAddressParseAndAppend( - lb_endpoints[i], &output_locality->endpoints); - if (error != GRPC_ERROR_NONE) return error; - } - // Parse the priority. - *priority = envoy_config_endpoint_v3_LocalityLbEndpoints_priority( - locality_lb_endpoints); - return GRPC_ERROR_NONE; -} - -grpc_error_handle DropParseAndAppend( - const envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload* - drop_overload, - XdsApi::EdsUpdate::DropConfig* drop_config) { - // Get the category. - TString category = UpbStringToStdString( - envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload_category( - drop_overload)); - if (category.empty()) { - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty drop category name"); - } - // Get the drop rate (per million). - const envoy_type_v3_FractionalPercent* drop_percentage = - envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload_drop_percentage( - drop_overload); - uint32_t numerator = - envoy_type_v3_FractionalPercent_numerator(drop_percentage); - const auto denominator = - static_cast<envoy_type_v3_FractionalPercent_DenominatorType>( - envoy_type_v3_FractionalPercent_denominator(drop_percentage)); - // Normalize to million. - switch (denominator) { - case envoy_type_v3_FractionalPercent_HUNDRED: - numerator *= 10000; - break; - case envoy_type_v3_FractionalPercent_TEN_THOUSAND: - numerator *= 100; - break; - case envoy_type_v3_FractionalPercent_MILLION: - break; - default: - return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unknown denominator type"); - } - // Cap numerator to 1000000. - numerator = std::min(numerator, 1000000u); - drop_config->AddCategory(std::move(category), numerator); - return GRPC_ERROR_NONE; -} - -grpc_error_handle EdsResourceParse( - const EncodingContext& /*context*/, - const envoy_config_endpoint_v3_ClusterLoadAssignment* - cluster_load_assignment, - bool /*is_v2*/, XdsApi::EdsUpdate* eds_update) { - std::vector<grpc_error_handle> errors; - // 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); - for (size_t j = 0; j < locality_size; ++j) { - size_t priority; - XdsApi::EdsUpdate::Priority::Locality locality; - grpc_error_handle error = LocalityParse(endpoints[j], &locality, &priority); - if (error != GRPC_ERROR_NONE) { - errors.push_back(error); - continue; - } - // Filter out locality with weight 0. - if (locality.lb_weight == 0) continue; - // Make sure prorities is big enough. Note that they might not - // arrive in priority order. - while (eds_update->priorities.size() < priority + 1) { - eds_update->priorities.emplace_back(); - } - eds_update->priorities[priority].localities.emplace(locality.name.get(), - std::move(locality)); - } - for (const auto& priority : eds_update->priorities) { - if (priority.localities.empty()) { - errors.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("sparse priority list")); - } - } - // Get the drop config. - eds_update->drop_config = MakeRefCounted<XdsApi::EdsUpdate::DropConfig>(); - const envoy_config_endpoint_v3_ClusterLoadAssignment_Policy* policy = - envoy_config_endpoint_v3_ClusterLoadAssignment_policy( - cluster_load_assignment); - if (policy != nullptr) { - size_t drop_size; - const envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload* const* - drop_overload = - envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_drop_overloads( - policy, &drop_size); - for (size_t j = 0; j < drop_size; ++j) { - grpc_error_handle error = - DropParseAndAppend(drop_overload[j], eds_update->drop_config.get()); - if (error != GRPC_ERROR_NONE) { - errors.push_back( - grpc_error_add_child(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "drop config validation error"), - error)); - } - } - } - return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing EDS resource", &errors); -} - -class ListenerResourceType : public XdsResourceType { - public: - struct ListenerData : public ResourceData { - XdsApi::LdsUpdate resource; - }; - - y_absl::string_view type_url() const override { return XdsApi::kLdsTypeUrl; } - y_absl::string_view v2_type_url() const override { return kLdsV2TypeUrl; } - - y_absl::StatusOr<DecodeResult> Decode(const EncodingContext& context, - y_absl::string_view serialized_resource, - bool is_v2) const override { - // Parse serialized proto. - auto* resource = envoy_config_listener_v3_Listener_parse( - serialized_resource.data(), serialized_resource.size(), context.arena); - if (resource == nullptr) { - return y_absl::InvalidArgumentError("Can't parse Listener resource."); - } - MaybeLogListener(context, resource); - // Validate resource. - DecodeResult result; - result.name = - UpbStringToStdString(envoy_config_listener_v3_Listener_name(resource)); - auto listener_data = y_absl::make_unique<ListenerData>(); - grpc_error_handle error = - LdsResourceParse(context, resource, is_v2, &listener_data->resource); - if (error != GRPC_ERROR_NONE) { - result.resource = - y_absl::InvalidArgumentError(grpc_error_std_string(error)); - GRPC_ERROR_UNREF(error); - } else { - result.resource = std::move(listener_data); - } - return std::move(result); - } -}; - -class RouteConfigResourceType : public XdsResourceType { - public: - struct RouteConfigData : public ResourceData { - XdsApi::RdsUpdate resource; - }; - - y_absl::string_view type_url() const override { return XdsApi::kRdsTypeUrl; } - y_absl::string_view v2_type_url() const override { return kRdsV2TypeUrl; } - - y_absl::StatusOr<DecodeResult> Decode(const EncodingContext& context, - y_absl::string_view serialized_resource, - bool is_v2) const override { - // Parse serialized proto. - auto* resource = envoy_config_route_v3_RouteConfiguration_parse( - serialized_resource.data(), serialized_resource.size(), context.arena); - if (resource == nullptr) { - return y_absl::InvalidArgumentError("Can't parse Listener resource."); - } - MaybeLogRouteConfiguration(context, resource); - // Validate resource. - DecodeResult result; - result.name = UpbStringToStdString( - envoy_config_route_v3_RouteConfiguration_name(resource)); - auto route_config_data = y_absl::make_unique<RouteConfigData>(); - grpc_error_handle error = RouteConfigParse(context, resource, is_v2, - &route_config_data->resource); - if (error != GRPC_ERROR_NONE) { - result.resource = - y_absl::InvalidArgumentError(grpc_error_std_string(error)); - GRPC_ERROR_UNREF(error); - } else { - result.resource = std::move(route_config_data); - } - return std::move(result); - } -}; - -class ClusterResourceType : public XdsResourceType { - public: - struct ClusterData : public ResourceData { - XdsApi::CdsUpdate resource; - }; - - y_absl::string_view type_url() const override { return XdsApi::kCdsTypeUrl; } - y_absl::string_view v2_type_url() const override { return kCdsV2TypeUrl; } - - y_absl::StatusOr<DecodeResult> Decode(const EncodingContext& context, - y_absl::string_view serialized_resource, - bool is_v2) const override { - // Parse serialized proto. - auto* resource = envoy_config_cluster_v3_Cluster_parse( - serialized_resource.data(), serialized_resource.size(), context.arena); - if (resource == nullptr) { - return y_absl::InvalidArgumentError("Can't parse Listener resource."); - } - MaybeLogCluster(context, resource); - // Validate resource. - DecodeResult result; - result.name = - UpbStringToStdString(envoy_config_cluster_v3_Cluster_name(resource)); - auto cluster_data = y_absl::make_unique<ClusterData>(); - grpc_error_handle error = - CdsResourceParse(context, resource, is_v2, &cluster_data->resource); - if (error != GRPC_ERROR_NONE) { - result.resource = - y_absl::InvalidArgumentError(grpc_error_std_string(error)); - GRPC_ERROR_UNREF(error); - } else { - result.resource = std::move(cluster_data); - } - return std::move(result); - } -}; - -class EndpointResourceType : public XdsResourceType { - public: - struct EndpointData : public ResourceData { - XdsApi::EdsUpdate resource; - }; - - y_absl::string_view type_url() const override { return XdsApi::kEdsTypeUrl; } - y_absl::string_view v2_type_url() const override { return kEdsV2TypeUrl; } - - y_absl::StatusOr<DecodeResult> Decode(const EncodingContext& context, - y_absl::string_view serialized_resource, - bool is_v2) const override { - // Parse serialized proto. - auto* resource = envoy_config_endpoint_v3_ClusterLoadAssignment_parse( - serialized_resource.data(), serialized_resource.size(), context.arena); - if (resource == nullptr) { - return y_absl::InvalidArgumentError("Can't parse Listener resource."); - } - MaybeLogClusterLoadAssignment(context, resource); - // Validate resource. - DecodeResult result; - result.name = UpbStringToStdString( - envoy_config_endpoint_v3_ClusterLoadAssignment_cluster_name(resource)); - auto endpoint_data = y_absl::make_unique<EndpointData>(); - grpc_error_handle error = - EdsResourceParse(context, resource, is_v2, &endpoint_data->resource); - if (error != GRPC_ERROR_NONE) { - result.resource = - y_absl::InvalidArgumentError(grpc_error_std_string(error)); - GRPC_ERROR_UNREF(error); - } else { - result.resource = std::move(endpoint_data); - } - return std::move(result); - } -}; - -grpc_error_handle AdsResourceParse( - const EncodingContext& context, XdsResourceType* type, size_t idx, - const google_protobuf_Any* resource_any, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_resource_names, - std::function<grpc_error_handle( - y_absl::string_view, XdsApi::ResourceName, - std::unique_ptr<XdsResourceType::ResourceData>, TString)> - add_result_func, - std::set<XdsApi::ResourceName>* resource_names_failed) { - // Check the type_url of the resource. - y_absl::string_view type_url = y_absl::StripPrefix( - UpbStringToAbsl(google_protobuf_Any_type_url(resource_any)), - "type.googleapis.com/"); - bool is_v2 = false; - if (!type->IsType(type_url, &is_v2)) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("resource index ", idx, ": found resource type ", type_url, - " in response for type ", type->type_url())); - } - // Parse the resource. - y_absl::string_view serialized_resource = - UpbStringToAbsl(google_protobuf_Any_value(resource_any)); - y_absl::StatusOr<XdsResourceType::DecodeResult> result = - type->Decode(context, serialized_resource, is_v2); - if (!result.ok()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("resource index ", idx, ": ", result.status().ToString())); - } - // Check the resource name. - auto resource_name = ParseResourceNameInternal( - result->name, [type](y_absl::string_view type_url, bool* is_v2) { - return type->IsType(type_url, is_v2); - }); - if (!resource_name.ok()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "resource index ", idx, ": Cannot parse xDS resource name \"", - result->name, "\"")); - } - // Ignore unexpected names. - auto iter = subscribed_resource_names.find(resource_name->authority); - if (iter == subscribed_resource_names.end() || - iter->second.find(resource_name->id) == iter->second.end()) { - return GRPC_ERROR_NONE; - } - // Check that resource was valid. - if (!result->resource.ok()) { - resource_names_failed->insert(*resource_name); - return GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "resource index ", idx, ": ", result->name, - ": validation error: ", result->resource.status().ToString())); - } - // Add result. - grpc_error_handle error = add_result_func(result->name, *resource_name, - std::move(*result->resource), - TString(serialized_resource)); - if (error != GRPC_ERROR_NONE) { - resource_names_failed->insert(*resource_name); - return grpc_error_add_child( - GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "resource index ", idx, ": ", result->name, ": validation error")), - error); - } - return GRPC_ERROR_NONE; -} - -template <typename UpdateMap, typename ResourceTypeData> -grpc_error_handle AddResult( - UpdateMap* update_map, y_absl::string_view resource_name_string, - XdsApi::ResourceName resource_name, - std::unique_ptr<XdsResourceType::ResourceData> resource, - TString serialized_resource) { - // Reject duplicate names. - if (update_map->find(resource_name) != update_map->end()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("duplicate resource name \"", resource_name_string, "\"")); - } - // Save result. - auto& resource_data = (*update_map)[resource_name]; - ResourceTypeData* typed_resource = - static_cast<ResourceTypeData*>(resource.get()); - resource_data.resource = std::move(typed_resource->resource); - resource_data.serialized_proto = std::move(serialized_resource); - return GRPC_ERROR_NONE; -} - } // namespace -XdsApi::AdsParseResult XdsApi::ParseAdsResponse( - const XdsBootstrap::XdsServer& server, const grpc_slice& encoded_response, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_listener_names, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_route_config_names, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_cluster_names, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_eds_service_names) { - AdsParseResult result; +y_absl::Status XdsApi::ParseAdsResponse(const XdsBootstrap::XdsServer& server, + const grpc_slice& encoded_response, + AdsResponseParserInterface* parser) { upb::Arena arena; - const EncodingContext context = {client_, - tracer_, - symtab_.ptr(), - arena.ptr(), - server.ShouldUseV3(), - certificate_provider_definition_map_}; + const XdsEncodingContext context = {client_, + tracer_, + symtab_->ptr(), + arena.ptr(), + server.ShouldUseV3(), + certificate_provider_definition_map_}; // Decode the response. const envoy_service_discovery_v3_DiscoveryResponse* response = envoy_service_discovery_v3_DiscoveryResponse_parse( reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(encoded_response)), GRPC_SLICE_LENGTH(encoded_response), arena.ptr()); - // If decoding fails, output an empty type_url and return. + // If decoding fails, report a fatal error and return. if (response == nullptr) { - result.parse_error = - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode DiscoveryResponse."); - return result; + return y_absl::InvalidArgumentError("Can't decode DiscoveryResponse."); } MaybeLogDiscoveryResponse(context, response); - // Record the type_url, the version_info, and the nonce of the response. - result.type_url = TypeUrlInternalToExternal(y_absl::StripPrefix( + // Report the type_url, version, nonce, and number of resources to the parser. + AdsResponseParserInterface::AdsResponseFields fields; + fields.type_url = TString(y_absl::StripPrefix( UpbStringToAbsl( envoy_service_discovery_v3_DiscoveryResponse_type_url(response)), "type.googleapis.com/")); - result.version = UpbStringToStdString( + fields.version = UpbStringToStdString( envoy_service_discovery_v3_DiscoveryResponse_version_info(response)); - result.nonce = UpbStringToStdString( + fields.nonce = UpbStringToStdString( envoy_service_discovery_v3_DiscoveryResponse_nonce(response)); - // Get the resources from the response. - std::vector<grpc_error_handle> errors; - size_t size; + size_t num_resources; const google_protobuf_Any* const* resources = - envoy_service_discovery_v3_DiscoveryResponse_resources(response, &size); - for (size_t i = 0; i < size; ++i) { - // Parse the response according to the resource type. - // TODO(roth): When we have time, change the API here to avoid the need - // for templating and conditionals. - grpc_error_handle parse_error = GRPC_ERROR_NONE; - if (IsLds(result.type_url)) { - ListenerResourceType resource_type; - auto& update_map = result.lds_update_map; - parse_error = AdsResourceParse( - context, &resource_type, i, resources[i], subscribed_listener_names, - [&update_map](y_absl::string_view resource_name_string, - XdsApi::ResourceName resource_name, - std::unique_ptr<XdsResourceType::ResourceData> resource, - TString serialized_resource) { - return AddResult<LdsUpdateMap, ListenerResourceType::ListenerData>( - &update_map, resource_name_string, std::move(resource_name), - std::move(resource), std::move(serialized_resource)); - }, - &result.resource_names_failed); - } else if (IsRds(result.type_url)) { - RouteConfigResourceType resource_type; - auto& update_map = result.rds_update_map; - parse_error = AdsResourceParse( - context, &resource_type, i, resources[i], - subscribed_route_config_names, - [&update_map](y_absl::string_view resource_name_string, - XdsApi::ResourceName resource_name, - std::unique_ptr<XdsResourceType::ResourceData> resource, - TString serialized_resource) { - return AddResult<RdsUpdateMap, - RouteConfigResourceType::RouteConfigData>( - &update_map, resource_name_string, std::move(resource_name), - std::move(resource), std::move(serialized_resource)); - }, - &result.resource_names_failed); - } else if (IsCds(result.type_url)) { - ClusterResourceType resource_type; - auto& update_map = result.cds_update_map; - parse_error = AdsResourceParse( - context, &resource_type, i, resources[i], subscribed_cluster_names, - [&update_map](y_absl::string_view resource_name_string, - XdsApi::ResourceName resource_name, - std::unique_ptr<XdsResourceType::ResourceData> resource, - TString serialized_resource) { - return AddResult<CdsUpdateMap, ClusterResourceType::ClusterData>( - &update_map, resource_name_string, std::move(resource_name), - std::move(resource), std::move(serialized_resource)); - }, - &result.resource_names_failed); - } else if (IsEds(result.type_url)) { - EndpointResourceType resource_type; - auto& update_map = result.eds_update_map; - parse_error = AdsResourceParse( - context, &resource_type, i, resources[i], - subscribed_eds_service_names, - [&update_map](y_absl::string_view resource_name_string, - XdsApi::ResourceName resource_name, - std::unique_ptr<XdsResourceType::ResourceData> resource, - TString serialized_resource) { - return AddResult<EdsUpdateMap, EndpointResourceType::EndpointData>( - &update_map, resource_name_string, std::move(resource_name), - std::move(resource), std::move(serialized_resource)); - }, - &result.resource_names_failed); - } - if (parse_error != GRPC_ERROR_NONE) errors.push_back(parse_error); - } - result.parse_error = - GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing ADS response", &errors); - return result; + envoy_service_discovery_v3_DiscoveryResponse_resources(response, + &num_resources); + fields.num_resources = num_resources; + y_absl::Status status = parser->ProcessAdsResponseFields(std::move(fields)); + if (!status.ok()) return status; + // Process each resource. + for (size_t i = 0; i < num_resources; ++i) { + y_absl::string_view type_url = y_absl::StripPrefix( + UpbStringToAbsl(google_protobuf_Any_type_url(resources[i])), + "type.googleapis.com/"); + y_absl::string_view serialized_resource = + UpbStringToAbsl(google_protobuf_Any_value(resources[i])); + parser->ParseResource(context, i, type_url, serialized_resource); + } + return y_absl::OkStatus(); } namespace { void MaybeLogLrsRequest( - const EncodingContext& context, + const XdsEncodingContext& context, const envoy_service_load_stats_v3_LoadStatsRequest* request) { if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { @@ -3794,7 +417,7 @@ void MaybeLogLrsRequest( } grpc_slice SerializeLrsRequest( - const EncodingContext& context, + const XdsEncodingContext& context, const envoy_service_load_stats_v3_LoadStatsRequest* request) { size_t output_length; char* output = envoy_service_load_stats_v3_LoadStatsRequest_serialize( @@ -3807,12 +430,12 @@ grpc_slice SerializeLrsRequest( grpc_slice XdsApi::CreateLrsInitialRequest( const XdsBootstrap::XdsServer& server) { upb::Arena arena; - const EncodingContext context = {client_, - tracer_, - symtab_.ptr(), - arena.ptr(), - server.ShouldUseV3(), - certificate_provider_definition_map_}; + const XdsEncodingContext context = {client_, + tracer_, + symtab_->ptr(), + arena.ptr(), + server.ShouldUseV3(), + certificate_provider_definition_map_}; // Create a request. envoy_service_load_stats_v3_LoadStatsRequest* request = envoy_service_load_stats_v3_LoadStatsRequest_new(arena.ptr()); @@ -3832,7 +455,7 @@ grpc_slice XdsApi::CreateLrsInitialRequest( namespace { void LocalityStatsPopulate( - const EncodingContext& context, + const XdsEncodingContext& context, envoy_config_endpoint_v3_UpstreamLocalityStats* output, const XdsLocalityName& locality_name, const XdsClusterLocalityStats::Snapshot& snapshot) { @@ -3882,8 +505,8 @@ void LocalityStatsPopulate( grpc_slice XdsApi::CreateLrsRequest( ClusterLoadReportMap cluster_load_report_map) { upb::Arena arena; - const EncodingContext context = { - client_, tracer_, symtab_.ptr(), + const XdsEncodingContext context = { + client_, tracer_, symtab_->ptr(), arena.ptr(), false, certificate_provider_definition_map_}; // Create a request. envoy_service_load_stats_v3_LoadStatsRequest* request = @@ -3986,8 +609,8 @@ grpc_error_handle XdsApi::ParseLrsResponse( namespace { -google_protobuf_Timestamp* GrpcMillisToTimestamp(const EncodingContext& context, - grpc_millis value) { +google_protobuf_Timestamp* GrpcMillisToTimestamp( + const XdsEncodingContext& 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); @@ -4006,8 +629,8 @@ TString XdsApi::AssembleClientConfig( // 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(), + const XdsEncodingContext context = { + client_, tracer_, symtab_->ptr(), arena.ptr(), true, certificate_provider_definition_map_}; PopulateNode(context, node_, build_version_, user_agent_name_, user_agent_version_, node); diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_api.h b/contrib/libs/grpc/src/core/ext/xds/xds_api.h index dd3c97ea22..5824dc7fe3 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_api.h +++ b/contrib/libs/grpc/src/core/ext/xds/xds_api.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_XDS_XDS_API_H #define GRPC_CORE_EXT_XDS_XDS_API_H @@ -25,561 +23,53 @@ #include <set> -#include "y_absl/container/inlined_vector.h" -#include "y_absl/types/optional.h" -#include "y_absl/types/variant.h" #include "envoy/admin/v3/config_dump.upb.h" -#include "re2/re2.h" #include "upb/def.hpp" -#include <grpc/slice_buffer.h> +#include <grpc/slice.h> -#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/ext/xds/upb_utils.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/channel/status_util.h" #include "src/core/lib/matchers/matchers.h" +#include "src/core/lib/resolver/server_address.h" namespace grpc_core { -bool XdsRbacEnabled(); - class XdsClient; +// TODO(roth): When we have time, split this into multiple pieces: +// - a common upb-based parsing framework (combine with XdsEncodingContext) +// - ADS request/response handling +// - LRS request/response handling +// - CSDS response generation class XdsApi { public: - static const char* kLdsTypeUrl; - static const char* kRdsTypeUrl; - static const char* kCdsTypeUrl; - static const char* kEdsTypeUrl; - - struct Duration { - Duration() {} - int64_t seconds = 0; - int32_t nanos = 0; - bool operator==(const Duration& other) const { - return seconds == other.seconds && nanos == other.nanos; - } - TString ToString() const { - return y_absl::StrFormat("Duration seconds: %ld, nanos %d", seconds, nanos); - } - }; - - using TypedPerFilterConfig = - std::map<TString, XdsHttpFilterImpl::FilterConfig>; - - struct RetryPolicy { - internal::StatusCodeSet retry_on; - uint32_t num_retries; - - struct RetryBackOff { - Duration base_interval; - Duration max_interval; - - bool operator==(const RetryBackOff& other) const { - return base_interval == other.base_interval && - max_interval == other.max_interval; - } - TString ToString() const; - }; - RetryBackOff retry_back_off; - - bool operator==(const RetryPolicy& other) const { - return (retry_on == other.retry_on && num_retries == other.num_retries && - retry_back_off == other.retry_back_off); - } - TString ToString() const; - }; - - // TODO(donnadionne): When we can use y_absl::variant<>, consider using that - // for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters - struct Route { - // Matchers for this route. - struct Matchers { - StringMatcher path_matcher; - std::vector<HeaderMatcher> header_matchers; - y_absl::optional<uint32_t> fraction_per_million; - - bool operator==(const Matchers& other) const { - return path_matcher == other.path_matcher && - header_matchers == other.header_matchers && - fraction_per_million == other.fraction_per_million; - } - TString ToString() const; - }; - - Matchers matchers; - - struct UnknownAction { - bool operator==(const UnknownAction& /* other */) const { return true; } - }; - - struct RouteAction { - struct HashPolicy { - enum Type { HEADER, CHANNEL_ID }; - Type type; - bool terminal = false; - // Fields used for type HEADER. - TString header_name; - std::unique_ptr<RE2> regex = nullptr; - TString 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; - TString ToString() const; - }; - - struct ClusterWeight { - TString name; - uint32_t weight; - TypedPerFilterConfig typed_per_filter_config; - - bool operator==(const ClusterWeight& other) const { - return name == other.name && weight == other.weight && - typed_per_filter_config == other.typed_per_filter_config; - } - TString ToString() const; - }; - - std::vector<HashPolicy> hash_policies; - y_absl::optional<RetryPolicy> retry_policy; - - // Action for this route. - // TODO(roth): When we can use y_absl::variant<>, consider using that - // here, to enforce the fact that only one of the two fields can be set. - TString cluster_name; - std::vector<ClusterWeight> weighted_clusters; - // Storing the timeout duration from route action: - // RouteAction.max_stream_duration.grpc_timeout_header_max or - // RouteAction.max_stream_duration.max_stream_duration if the former is - // not set. - y_absl::optional<Duration> max_stream_duration; - - bool operator==(const RouteAction& other) const { - return hash_policies == other.hash_policies && - retry_policy == other.retry_policy && - cluster_name == other.cluster_name && - weighted_clusters == other.weighted_clusters && - max_stream_duration == other.max_stream_duration; - } - TString ToString() const; - }; - - struct NonForwardingAction { - bool operator==(const NonForwardingAction& /* other */) const { - return true; - } - }; - - y_absl::variant<UnknownAction, RouteAction, NonForwardingAction> action; - TypedPerFilterConfig typed_per_filter_config; - - bool operator==(const Route& other) const { - return matchers == other.matchers && action == other.action && - typed_per_filter_config == other.typed_per_filter_config; - } - TString ToString() const; - }; - - struct RdsUpdate { - struct VirtualHost { - std::vector<TString> domains; - std::vector<Route> routes; - TypedPerFilterConfig typed_per_filter_config; - - bool operator==(const VirtualHost& other) const { - return domains == other.domains && routes == other.routes && - typed_per_filter_config == other.typed_per_filter_config; - } - }; - - std::vector<VirtualHost> virtual_hosts; - - bool operator==(const RdsUpdate& other) const { - return virtual_hosts == other.virtual_hosts; - } - TString ToString() const; - }; - - struct CommonTlsContext { - struct CertificateProviderPluginInstance { - TString instance_name; - TString certificate_name; - - bool operator==(const CertificateProviderPluginInstance& other) const { - return instance_name == other.instance_name && - certificate_name == other.certificate_name; - } - - TString ToString() const; - bool Empty() const; - }; - - struct CertificateValidationContext { - CertificateProviderPluginInstance ca_certificate_provider_instance; - std::vector<StringMatcher> match_subject_alt_names; - - bool operator==(const CertificateValidationContext& other) const { - return ca_certificate_provider_instance == - other.ca_certificate_provider_instance && - match_subject_alt_names == other.match_subject_alt_names; - } - - TString ToString() const; - bool Empty() const; - }; - - CertificateValidationContext certificate_validation_context; - CertificateProviderPluginInstance tls_certificate_provider_instance; - - bool operator==(const CommonTlsContext& other) const { - return certificate_validation_context == - other.certificate_validation_context && - tls_certificate_provider_instance == - other.tls_certificate_provider_instance; - } - - TString ToString() const; - bool Empty() const; - }; - - struct DownstreamTlsContext { - CommonTlsContext common_tls_context; - bool require_client_certificate = false; - - bool operator==(const DownstreamTlsContext& other) const { - return common_tls_context == other.common_tls_context && - require_client_certificate == other.require_client_certificate; - } - - TString ToString() const; - bool Empty() const; - }; - - // TODO(roth): When we can use y_absl::variant<>, consider using that - // here, to enforce the fact that only one of the two fields can be set. - struct LdsUpdate { - enum class ListenerType { - kTcpListener = 0, - kHttpApiListener, - } type; - - struct HttpConnectionManager { - // The name to use in the RDS request. - TString 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. - y_absl::optional<RdsUpdate> rds_update; - - struct HttpFilter { - TString name; - XdsHttpFilterImpl::FilterConfig config; - - bool operator==(const HttpFilter& other) const { - return name == other.name && config == other.config; - } - - TString ToString() const; - }; - std::vector<HttpFilter> 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; - } - - TString ToString() const; - }; - - // Populated for type=kHttpApiListener. - HttpConnectionManager http_connection_manager; - - // Populated for type=kTcpListener. - // host:port listening_address set when type is kTcpListener - TString 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 FilterChainData& other) const { - return downstream_tls_context == other.downstream_tls_context && - http_connection_manager == other.http_connection_manager; - } - - TString ToString() const; + // Interface defined by caller and passed to ParseAdsResponse(). + class AdsResponseParserInterface { + public: + struct AdsResponseFields { + TString type_url; + TString version; + TString nonce; + size_t num_resources; }; - // 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<FilterChainData> 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; - } - - TString ToString() const; - }; - using SourcePortsMap = std::map<uint16_t, FilterChainDataSharedPtr>; - struct SourceIp { - y_absl::optional<CidrRange> 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<SourceIp>; - enum class ConnectionSourceType { - kAny = 0, - kSameIpOrLoopback, - kExternal - }; - using ConnectionSourceTypesArray = std::array<SourceIpVector, 3>; - struct DestinationIp { - y_absl::optional<CidrRange> 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<DestinationIp>; - DestinationIpVector destination_ip_vector; - - bool operator==(const FilterChainMap& other) const { - return destination_ip_vector == other.destination_ip_vector; - } - - TString ToString() const; - } filter_chain_map; - - y_absl::optional<FilterChainData> default_filter_chain; - - bool operator==(const LdsUpdate& other) const { - 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; - } - - TString ToString() const; - }; - - struct ResourceName { - TString authority; - TString id; - - bool operator<(const ResourceName& other) const { - if (authority < other.authority) return true; - if (id < other.id) return true; - return false; - } - }; - - struct LdsResourceData { - LdsUpdate resource; - TString serialized_proto; - }; - - using LdsUpdateMap = std::map<ResourceName, LdsResourceData>; - - struct RdsResourceData { - RdsUpdate resource; - TString serialized_proto; - }; + virtual ~AdsResponseParserInterface() = default; - using RdsUpdateMap = std::map<ResourceName, RdsResourceData>; + // Called when the top-level ADS fields are parsed. + // If this returns non-OK, parsing will stop, and the individual + // resources will not be processed. + virtual y_absl::Status ProcessAdsResponseFields(AdsResponseFields fields) = 0; - struct CdsUpdate { - enum ClusterType { EDS, LOGICAL_DNS, AGGREGATE }; - ClusterType cluster_type; - // For cluster type EDS. - // The name to use in the EDS request. - // If empty, the cluster name will be used. - TString eds_service_name; - // For cluster type LOGICAL_DNS. - // The hostname to lookup in DNS. - TString dns_hostname; - // For cluster type AGGREGATE. - // The prioritized list of cluster names. - std::vector<TString> prioritized_cluster_names; - - // Tls Context used by clients - CommonTlsContext common_tls_context; - - // The LRS server to use for load reporting. - // If not set, load reporting will be disabled. - // If set to the empty string, will use the same server we obtained the CDS - // data from. - y_absl::optional<TString> lrs_load_reporting_server_name; - - // The LB policy to use (e.g., "ROUND_ROBIN" or "RING_HASH"). - TString lb_policy; - // Used for RING_HASH LB policy only. - uint64_t min_ring_size = 1024; - uint64_t max_ring_size = 8388608; - // Maximum number of outstanding requests can be made to the upstream - // cluster. - uint32_t max_concurrent_requests = 1024; - - bool operator==(const CdsUpdate& other) const { - return cluster_type == other.cluster_type && - eds_service_name == other.eds_service_name && - dns_hostname == other.dns_hostname && - prioritized_cluster_names == other.prioritized_cluster_names && - common_tls_context == other.common_tls_context && - lrs_load_reporting_server_name == - other.lrs_load_reporting_server_name && - lb_policy == other.lb_policy && - min_ring_size == other.min_ring_size && - max_ring_size == other.max_ring_size && - max_concurrent_requests == other.max_concurrent_requests; - } - - TString ToString() const; - }; - - struct CdsResourceData { - CdsUpdate resource; - TString serialized_proto; + // Called to parse each individual resource in the ADS response. + virtual void ParseResource(const XdsEncodingContext& context, size_t idx, + y_absl::string_view type_url, + y_absl::string_view serialized_resource) = 0; }; - using CdsUpdateMap = std::map<ResourceName, CdsResourceData>; - - struct EdsUpdate { - struct Priority { - struct Locality { - RefCountedPtr<XdsLocalityName> name; - uint32_t lb_weight; - ServerAddressList endpoints; - - bool operator==(const Locality& other) const { - return *name == *other.name && lb_weight == other.lb_weight && - endpoints == other.endpoints; - } - bool operator!=(const Locality& other) const { - return !(*this == other); - } - TString ToString() const; - }; - - std::map<XdsLocalityName*, Locality, XdsLocalityName::Less> localities; - - bool operator==(const Priority& other) const; - TString ToString() const; - }; - using PriorityList = y_absl::InlinedVector<Priority, 2>; - - // There are two phases of accessing this class's content: - // 1. to initialize in the control plane combiner; - // 2. to use in the data plane combiner. - // So no additional synchronization is needed. - class DropConfig : public RefCounted<DropConfig> { - public: - struct DropCategory { - bool operator==(const DropCategory& other) const { - return name == other.name && - parts_per_million == other.parts_per_million; - } - - TString name; - const uint32_t parts_per_million; - }; - - using DropCategoryList = y_absl::InlinedVector<DropCategory, 2>; - - void AddCategory(TString name, uint32_t parts_per_million) { - drop_category_list_.emplace_back( - DropCategory{std::move(name), parts_per_million}); - if (parts_per_million == 1000000) drop_all_ = true; - } - - // The only method invoked from outside the WorkSerializer (used in - // the data plane). - bool ShouldDrop(const TString** category_name) const; - - const DropCategoryList& drop_category_list() const { - return drop_category_list_; - } - - bool drop_all() const { return drop_all_; } - - bool operator==(const DropConfig& other) const { - return drop_category_list_ == other.drop_category_list_; - } - bool operator!=(const DropConfig& other) const { - return !(*this == other); - } - - TString ToString() const; - - private: - DropCategoryList drop_category_list_; - bool drop_all_ = false; - }; - - PriorityList priorities; - RefCountedPtr<DropConfig> drop_config; - - bool operator==(const EdsUpdate& other) const { - return priorities == other.priorities && - *drop_config == *other.drop_config; - } - TString ToString() const; - }; - - struct EdsResourceData { - EdsUpdate resource; - TString serialized_proto; - }; - - using EdsUpdateMap = std::map<ResourceName, EdsResourceData>; - struct ClusterLoadReport { XdsClusterDropStats::Snapshot dropped_requests; std::map<RefCountedPtr<XdsLocalityName>, XdsClusterLocalityStats::Snapshot, @@ -647,69 +137,24 @@ class XdsApi { ResourceMetadata::ClientResourceStatus::NACKED, ""); - // 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 - // field will be set to something other than GRPC_ERROR_NONE and the - // resource_names_failed field will be populated. - // Otherwise, one of the *_update_map fields will be populated, based - // on the type_url field. - struct AdsParseResult { - grpc_error_handle parse_error = GRPC_ERROR_NONE; - TString version; - TString nonce; - TString type_url; - LdsUpdateMap lds_update_map; - RdsUpdateMap rds_update_map; - CdsUpdateMap cds_update_map; - EdsUpdateMap eds_update_map; - std::set<ResourceName> resource_names_failed; - }; - XdsApi(XdsClient* client, TraceFlag* tracer, const XdsBootstrap::Node* node, - const CertificateProviderStore::PluginDefinitionMap* map); - - static bool IsLds(y_absl::string_view type_url); - static bool IsRds(y_absl::string_view type_url); - static bool IsCds(y_absl::string_view type_url); - static bool IsEds(y_absl::string_view type_url); - - // A helper method to parse the resource name and return back a ResourceName - // struct. Optionally the parser can check the resource type portion of the - // resource name. - static y_absl::StatusOr<ResourceName> ParseResourceName( - y_absl::string_view name, - bool (*is_expected_type)(y_absl::string_view) = nullptr); - - // A helper method to construct the resource name from parts. - static TString ConstructFullResourceName(y_absl::string_view authority, - y_absl::string_view resource_type, - y_absl::string_view name); + const CertificateProviderStore::PluginDefinitionMap* map, + upb::SymbolTable* symtab); // Creates an ADS request. // Takes ownership of \a error. - grpc_slice CreateAdsRequest( - const XdsBootstrap::XdsServer& server, const TString& type_url, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& resource_names, - const TString& version, const TString& 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::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_listener_names, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_route_config_names, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_cluster_names, - const std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>>& - subscribed_eds_service_names); + grpc_slice CreateAdsRequest(const XdsBootstrap::XdsServer& server, + y_absl::string_view type_url, + y_absl::string_view version, + y_absl::string_view nonce, + const std::vector<TString>& resource_names, + grpc_error_handle error, bool populate_node); + + // Returns non-OK when failing to deserialize response message. + // Otherwise, all events are reported to the parser. + y_absl::Status ParseAdsResponse(const XdsBootstrap::XdsServer& server, + const grpc_slice& encoded_response, + AdsResponseParserInterface* parser); // Creates an initial LRS request. grpc_slice CreateLrsInitialRequest(const XdsBootstrap::XdsServer& server); @@ -735,7 +180,7 @@ class XdsApi { const XdsBootstrap::Node* node_; // Do not own. const CertificateProviderStore::PluginDefinitionMap* certificate_provider_definition_map_; // Do not own. - upb::SymbolTable symtab_; + upb::SymbolTable* symtab_; // Do not own. const TString build_version_; const TString user_agent_name_; const TString user_agent_version_; @@ -743,4 +188,4 @@ class XdsApi { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_XDS_XDS_API_H */ +#endif // GRPC_CORE_EXT_XDS_XDS_API_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.cc b/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.cc index 625f19238c..1cb9f1652d 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.cc +++ b/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.cc @@ -28,53 +28,115 @@ #include "y_absl/strings/str_join.h" #include "y_absl/strings/string_view.h" +#include <grpc/grpc_security.h> + #include "src/core/ext/xds/certificate_provider_registry.h" #include "src/core/ext/xds/xds_api.h" +#include "src/core/ext/xds/xds_channel_creds.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/json/json_util.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/credentials/fake/fake_credentials.h" #include "src/core/lib/slice/slice_internal.h" namespace grpc_core { -// -// XdsChannelCredsRegistry -// +namespace { -bool XdsChannelCredsRegistry::IsSupported(const TString& creds_type) { - return creds_type == "google_default" || creds_type == "insecure" || - creds_type == "fake"; +// TODO(donnadionne): check to see if federation is enabled, this will be +// removed once federation is fully integrated and enabled by default. +bool XdsFederationEnabled() { + char* value = gpr_getenv("GRPC_EXPERIMENTAL_XDS_FEDERATION"); + bool parsed_value; + bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); + gpr_free(value); + return parse_succeeded && parsed_value; } -bool XdsChannelCredsRegistry::IsValidConfig(const TString& /*creds_type*/, - const Json& /*config*/) { - // Currently, none of the creds types actually take a config, but we - // ignore whatever might be specified in the bootstrap file for - // forward compatibility reasons. - return true; +grpc_error_handle ParseChannelCreds(const Json::Object& json, size_t idx, + XdsBootstrap::XdsServer* server) { + std::vector<grpc_error_handle> error_list; + TString type; + ParseJsonObjectField(json, "type", &type, &error_list); + const Json::Object* config_ptr = nullptr; + ParseJsonObjectField(json, "config", &config_ptr, &error_list, + /*required=*/false); + // Select the first channel creds type that we support. + if (server->channel_creds_type.empty() && + XdsChannelCredsRegistry::IsSupported(type)) { + Json config; + if (config_ptr != nullptr) config = *config_ptr; + if (!XdsChannelCredsRegistry::IsValidConfig(type, config)) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( + "invalid config for channel creds type \"", type, "\""))); + } + server->channel_creds_type = std::move(type); + server->channel_creds_config = std::move(config); + } + return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrCat("errors parsing index ", idx), &error_list); } -RefCountedPtr<grpc_channel_credentials> -XdsChannelCredsRegistry::MakeChannelCreds(const TString& creds_type, - const Json& /*config*/) { - if (creds_type == "google_default") { - return RefCountedPtr<grpc_channel_credentials>( - grpc_google_default_credentials_create(nullptr)); - } else if (creds_type == "insecure") { - return RefCountedPtr<grpc_channel_credentials>( - grpc_insecure_credentials_create()); - } else if (creds_type == "fake") { - return RefCountedPtr<grpc_channel_credentials>( - grpc_fake_transport_security_credentials_create()); +grpc_error_handle ParseChannelCredsArray(const Json::Array& json, + XdsBootstrap::XdsServer* server) { + std::vector<grpc_error_handle> error_list; + for (size_t i = 0; i < json.size(); ++i) { + const Json& child = json.at(i); + if (child.type() != Json::Type::OBJECT) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("array element ", i, " is not an object"))); + } else { + grpc_error_handle parse_error = + ParseChannelCreds(child.object_value(), i, server); + if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); + } } - return nullptr; + if (server->channel_creds_type.empty()) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "no known creds type found in \"channel_creds\"")); + } + return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"channel_creds\" array", + &error_list); } +} // namespace + // // XdsBootstrap::XdsServer // +XdsBootstrap::XdsServer XdsBootstrap::XdsServer::Parse( + const Json& json, grpc_error_handle* error) { + std::vector<grpc_error_handle> error_list; + XdsServer server; + ParseJsonObjectField(json.object_value(), "server_uri", &server.server_uri, + &error_list); + const Json::Array* creds_array = nullptr; + ParseJsonObjectField(json.object_value(), "channel_creds", &creds_array, + &error_list); + if (creds_array != nullptr) { + grpc_error_handle parse_error = + ParseChannelCredsArray(*creds_array, &server); + if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); + } + const Json::Array* server_features_array = nullptr; + ParseJsonObjectField(json.object_value(), "server_features", + &server_features_array, &error_list, /*required=*/false); + if (server_features_array != nullptr) { + for (const Json& feature_json : *server_features_array) { + if (feature_json.type() == Json::Type::STRING && + feature_json.string_value() == "xds_v3") { + server.server_features.insert(feature_json.string_value()); + } + } + } + *error = GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + "errors parsing xds server", &error_list); + return server; +} + bool XdsBootstrap::XdsServer::ShouldUseV3() const { return server_features.find("xds_v3") != server_features.end(); } @@ -112,7 +174,7 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error_handle* error) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( "\"xds_servers\" field is not an array")); } else { - grpc_error_handle parse_error = ParseXdsServerList(&it->second); + grpc_error_handle parse_error = ParseXdsServerList(&it->second, &servers_); if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } it = json.mutable_object()->find("node"); @@ -125,6 +187,30 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error_handle* error) { if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } } + if (XdsFederationEnabled()) { + it = json.mutable_object()->find("authorities"); + if (it != json.mutable_object()->end()) { + if (it->second.type() != Json::Type::OBJECT) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "\"authorities\" field is not an object")); + } else { + grpc_error_handle parse_error = ParseAuthorities(&it->second); + if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); + } + } + it = json.mutable_object()->find( + "client_default_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( + "\"client_default_listener_resource_name_template\" field is not a " + "string")); + } else { + client_default_listener_resource_name_template_ = + std::move(*it->second.mutable_string_value()); + } + } + } it = json.mutable_object()->find("server_listener_resource_name_template"); if (it != json.mutable_object()->end()) { if (it->second.type() != Json::Type::STRING) { @@ -149,7 +235,17 @@ XdsBootstrap::XdsBootstrap(Json json, grpc_error_handle* error) { &error_list); } -grpc_error_handle XdsBootstrap::ParseXdsServerList(Json* json) { +const XdsBootstrap::Authority* XdsBootstrap::LookupAuthority( + const TString& name) const { + auto it = authorities_.find(name); + if (it != authorities_.end()) { + return &it->second; + } + return nullptr; +} + +grpc_error_handle XdsBootstrap::ParseXdsServerList( + Json* json, y_absl::InlinedVector<XdsServer, 1>* servers) { std::vector<grpc_error_handle> error_list; for (size_t i = 0; i < json->mutable_array()->size(); ++i) { Json& child = json->mutable_array()->at(i); @@ -157,126 +253,73 @@ grpc_error_handle XdsBootstrap::ParseXdsServerList(Json* json) { error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( y_absl::StrCat("array element ", i, " is not an object"))); } else { - grpc_error_handle parse_error = ParseXdsServer(&child, i); - if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); + grpc_error_handle parse_error; + servers->emplace_back(XdsServer::Parse(child, &parse_error)); + if (parse_error != GRPC_ERROR_NONE) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("errors parsing index ", i))); + error_list.push_back(parse_error); + } } } return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"xds_servers\" array", &error_list); } -grpc_error_handle XdsBootstrap::ParseXdsServer(Json* json, size_t idx) { +grpc_error_handle XdsBootstrap::ParseAuthorities(Json* json) { std::vector<grpc_error_handle> error_list; - servers_.emplace_back(); - XdsServer& server = servers_[servers_.size() - 1]; - auto it = json->mutable_object()->find("server_uri"); - if (it == json->mutable_object()->end()) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "\"server_uri\" field not present")); - } else if (it->second.type() != Json::Type::STRING) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "\"server_uri\" field is not a string")); - } else { - server.server_uri = std::move(*it->second.mutable_string_value()); - } - it = json->mutable_object()->find("channel_creds"); - if (it == json->mutable_object()->end()) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "\"channel_creds\" field not present")); - } else if (it->second.type() != Json::Type::ARRAY) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "\"channel_creds\" field is not an array")); - } else { - 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"); - if (it != json->mutable_object()->end()) { - if (it->second.type() != Json::Type::ARRAY) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "\"server_features\" field is not an array")); - } else { - grpc_error_handle parse_error = - ParseServerFeaturesArray(&it->second, &server); - if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); - } - } - return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( - y_absl::StrCat("errors parsing index ", idx), &error_list); -} - -grpc_error_handle XdsBootstrap::ParseChannelCredsArray(Json* json, - XdsServer* server) { - std::vector<grpc_error_handle> 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) { + for (auto& p : *(json->mutable_object())) { + if (p.second.type() != Json::Type::OBJECT) { error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("array element ", i, " is not an object"))); - } else { - grpc_error_handle parse_error = ParseChannelCreds(&child, i, server); - if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); + "field:authorities element error: element is not a object")); + continue; } + grpc_error_handle parse_error = ParseAuthority(&p.second, p.first); + if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } - if (server->channel_creds_type.empty()) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "no known creds type found in \"channel_creds\"")); - } - return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"channel_creds\" array", + return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing \"authorities\"", &error_list); } -grpc_error_handle XdsBootstrap::ParseChannelCreds(Json* json, size_t idx, - XdsServer* server) { +grpc_error_handle XdsBootstrap::ParseAuthority(Json* json, + const TString& name) { std::vector<grpc_error_handle> error_list; - TString type; - auto it = json->mutable_object()->find("type"); - if (it == json->mutable_object()->end()) { - error_list.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("\"type\" field not present")); - } else if (it->second.type() != Json::Type::STRING) { - error_list.push_back( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("\"type\" field is not a string")); - } else { - type = std::move(*it->second.mutable_string_value()); - } - Json config; - it = json->mutable_object()->find("config"); + Authority authority; + auto it = + json->mutable_object()->find("client_listener_resource_name_template"); if (it != json->mutable_object()->end()) { - if (it->second.type() != Json::Type::OBJECT) { + if (it->second.type() != Json::Type::STRING) { error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "\"config\" field is not an object")); + "\"client_listener_resource_name_template\" field is not a string")); } else { - config = std::move(it->second); + TString expected_prefix = y_absl::StrCat("xdstp://", name, "/"); + if (!y_absl::StartsWith(it->second.string_value(), expected_prefix)) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("\"client_listener_resource_name_template\" field " + "must begin with \"", + expected_prefix, "\""))); + } else { + authority.client_listener_resource_name_template = + std::move(*it->second.mutable_string_value()); + } } } - // Select the first channel creds type that we support. - if (server->channel_creds_type.empty() && - XdsChannelCredsRegistry::IsSupported(type)) { - if (!XdsChannelCredsRegistry::IsValidConfig(type, config)) { - error_list.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "invalid config for channel creds type \"", type, "\""))); + it = json->mutable_object()->find("xds_servers"); + if (it != json->mutable_object()->end()) { + if (it->second.type() != Json::Type::ARRAY) { + error_list.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "\"xds_servers\" field is not an array")); + } else { + grpc_error_handle parse_error = + ParseXdsServerList(&it->second, &authority.xds_servers); + if (parse_error != GRPC_ERROR_NONE) error_list.push_back(parse_error); } - server->channel_creds_type = std::move(type); - server->channel_creds_config = std::move(config); } - return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( - y_absl::StrCat("errors parsing index ", idx), &error_list); -} - -grpc_error_handle XdsBootstrap::ParseServerFeaturesArray(Json* json, - XdsServer* server) { - std::vector<grpc_error_handle> 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 && - child.string_value() == "xds_v3") { - server->server_features.insert(std::move(*child.mutable_string_value())); - } + if (error_list.empty()) { + authorities_[name] = std::move(authority); } - return GRPC_ERROR_CREATE_FROM_VECTOR( - "errors parsing \"server_features\" array", &error_list); + return GRPC_ERROR_CREATE_FROM_VECTOR_AND_CPP_STRING( + y_absl::StrCat("errors parsing authority ", name), &error_list); } grpc_error_handle XdsBootstrap::ParseNode(Json* json) { @@ -452,11 +495,32 @@ TString XdsBootstrap::ToString() const { "],\n")); } parts.push_back(" }\n],\n"); + if (!client_default_listener_resource_name_template_.empty()) { + parts.push_back(y_absl::StrFormat( + "client_default_listener_resource_name_template=\"%s\",\n", + client_default_listener_resource_name_template_)); + } if (!server_listener_resource_name_template_.empty()) { parts.push_back( y_absl::StrFormat("server_listener_resource_name_template=\"%s\",\n", server_listener_resource_name_template_)); } + parts.push_back("authorities={\n"); + for (const auto& entry : authorities_) { + parts.push_back(y_absl::StrFormat(" %s={\n", entry.first)); + parts.push_back( + y_absl::StrFormat(" client_listener_resource_name_template=\"%s\",\n", + entry.second.client_listener_resource_name_template)); + parts.push_back( + y_absl::StrFormat(" servers=[\n" + " {\n" + " uri=\"%s\",\n" + " creds_type=%s,\n", + entry.second.xds_servers[0].server_uri, + entry.second.xds_servers[0].channel_creds_type)); + parts.push_back(" },\n"); + } + parts.push_back("}"); parts.push_back("certificate_providers={\n"); for (const auto& entry : certificate_providers_) { parts.push_back( diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.h b/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.h index 2aa6db01cb..b65b6f7424 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.h +++ b/contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.h @@ -39,14 +39,6 @@ namespace grpc_core { class XdsClient; -class XdsChannelCredsRegistry { - public: - static bool IsSupported(const TString& creds_type); - static bool IsValidConfig(const TString& creds_type, const Json& config); - static RefCountedPtr<grpc_channel_credentials> MakeChannelCreds( - const TString& creds_type, const Json& config); -}; - class XdsBootstrap { public: struct Node { @@ -64,6 +56,8 @@ class XdsBootstrap { Json channel_creds_config; std::set<TString> server_features; + static XdsServer Parse(const Json& json, grpc_error_handle* error); + bool operator<(const XdsServer& other) const { if (server_uri < other.server_uri) return true; if (channel_creds_type < other.channel_creds_type) return true; @@ -77,6 +71,11 @@ class XdsBootstrap { bool ShouldUseV3() const; }; + struct Authority { + TString client_listener_resource_name_template; + y_absl::InlinedVector<XdsServer, 1> xds_servers; + }; + // Creates bootstrap object from json_string. // If *error is not GRPC_ERROR_NONE after returning, then there was an // error parsing the contents. @@ -92,22 +91,26 @@ class XdsBootstrap { // add support for fallback for the xds channel. const XdsServer& server() const { return servers_[0]; } const Node* node() const { return node_.get(); } + const TString& client_default_listener_resource_name_template() const { + return client_default_listener_resource_name_template_; + } const TString& server_listener_resource_name_template() const { return server_listener_resource_name_template_; } - + const std::map<TString, Authority>& authorities() const { + return authorities_; + } + const Authority* LookupAuthority(const TString& name) const; const CertificateProviderStore::PluginDefinitionMap& certificate_providers() const { return certificate_providers_; } private: - 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 ParseXdsServerList( + Json* json, y_absl::InlinedVector<XdsServer, 1>* servers); + grpc_error_handle ParseAuthorities(Json* json); + grpc_error_handle ParseAuthority(Json* json, const TString& name); grpc_error_handle ParseNode(Json* json); grpc_error_handle ParseLocality(Json* json); grpc_error_handle ParseCertificateProviders(Json* json); @@ -116,7 +119,9 @@ class XdsBootstrap { y_absl::InlinedVector<XdsServer, 1> servers_; std::unique_ptr<Node> node_; + TString client_default_listener_resource_name_template_; TString server_listener_resource_name_template_; + std::map<TString, Authority> authorities_; CertificateProviderStore::PluginDefinitionMap certificate_providers_; }; diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_certificate_provider.h b/contrib/libs/grpc/src/core/ext/xds/xds_certificate_provider.h index f38c8f361f..fea32008db 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_certificate_provider.h +++ b/contrib/libs/grpc/src/core/ext/xds/xds_certificate_provider.h @@ -22,6 +22,7 @@ #include <grpc/support/port_platform.h> #include "src/core/ext/xds/xds_api.h" +#include "src/core/lib/matchers/matchers.h" #include "src/core/lib/security/credentials/tls/grpc_tls_certificate_provider.h" #define GRPC_ARG_XDS_CERTIFICATE_PROVIDER \ diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.cc b/contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.cc new file mode 100644 index 0000000000..0e98efcf5d --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.cc @@ -0,0 +1,108 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_channel_creds.h" + +#include "src/core/lib/security/credentials/fake/fake_credentials.h" + +namespace grpc_core { + +namespace { + +using ChannelCredsMap = + std::map<y_absl::string_view, std::unique_ptr<XdsChannelCredsImpl>>; +ChannelCredsMap* g_creds = nullptr; + +} // namespace + +// +// XdsChannelCredsImpl implementations for default-supported cred types. +// + +class GoogleDefaultXdsChannelCredsImpl : public XdsChannelCredsImpl { + public: + y_absl::string_view creds_type() const override { return "google_default"; } + RefCountedPtr<grpc_channel_credentials> CreateXdsChannelCreds( + const Json& /*config*/) const override { + return RefCountedPtr<grpc_channel_credentials>( + grpc_google_default_credentials_create(nullptr)); + } + bool IsValidConfig(const Json& /*config*/) const override { return true; } +}; + +class InsecureXdsChannelCredsImpl : public XdsChannelCredsImpl { + public: + y_absl::string_view creds_type() const override { return "insecure"; } + RefCountedPtr<grpc_channel_credentials> CreateXdsChannelCreds( + const Json& /*config*/) const override { + return RefCountedPtr<grpc_channel_credentials>( + grpc_insecure_credentials_create()); + } + bool IsValidConfig(const Json& /*config*/) const override { return true; } +}; + +class FakeXdsChannelCredsImpl : public XdsChannelCredsImpl { + public: + y_absl::string_view creds_type() const override { return "fake"; } + RefCountedPtr<grpc_channel_credentials> CreateXdsChannelCreds( + const Json& /*config*/) const override { + return RefCountedPtr<grpc_channel_credentials>( + grpc_fake_transport_security_credentials_create()); + } + bool IsValidConfig(const Json& /*config*/) const override { return true; } +}; + +// +// XdsChannelCredsRegistry +// + +bool XdsChannelCredsRegistry::IsSupported(const TString& creds_type) { + return g_creds->find(creds_type) != g_creds->end(); +} + +bool XdsChannelCredsRegistry::IsValidConfig(const TString& creds_type, + const Json& config) { + const auto iter = g_creds->find(creds_type); + if (iter == g_creds->cend()) return false; + return iter->second->IsValidConfig(config); +} + +RefCountedPtr<grpc_channel_credentials> +XdsChannelCredsRegistry::CreateXdsChannelCreds(const TString& creds_type, + const Json& config) { + const auto iter = g_creds->find(creds_type); + if (iter == g_creds->cend()) return nullptr; + return iter->second->CreateXdsChannelCreds(config); +} + +void XdsChannelCredsRegistry::Init() { + g_creds = new ChannelCredsMap(); + RegisterXdsChannelCreds( + y_absl::make_unique<GoogleDefaultXdsChannelCredsImpl>()); + RegisterXdsChannelCreds(y_absl::make_unique<InsecureXdsChannelCredsImpl>()); + RegisterXdsChannelCreds(y_absl::make_unique<FakeXdsChannelCredsImpl>()); +} + +void XdsChannelCredsRegistry::Shutdown() { delete g_creds; } + +void XdsChannelCredsRegistry::RegisterXdsChannelCreds( + std::unique_ptr<XdsChannelCredsImpl> creds) { + (*g_creds)[creds->creds_type()] = std::move(creds); +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.h b/contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.h new file mode 100644 index 0000000000..04d7eb5874 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.h @@ -0,0 +1,50 @@ +// +// Copyright 2022 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_CORE_EXT_XDS_XDS_CHANNEL_CREDS_H +#define GRPC_CORE_EXT_XDS_XDS_CHANNEL_CREDS_H + +#include <grpc/support/port_platform.h> + +#include "src/core/lib/json/json.h" +#include "src/core/lib/security/credentials/credentials.h" + +namespace grpc_core { + +class XdsChannelCredsImpl { + public: + virtual ~XdsChannelCredsImpl() {} + virtual y_absl::string_view creds_type() const = 0; + virtual bool IsValidConfig(const Json& config) const = 0; + virtual RefCountedPtr<grpc_channel_credentials> CreateXdsChannelCreds( + const Json& config) const = 0; +}; + +class XdsChannelCredsRegistry { + public: + static bool IsSupported(const TString& creds_type); + static bool IsValidConfig(const TString& creds_type, const Json& config); + static RefCountedPtr<grpc_channel_credentials> CreateXdsChannelCreds( + const TString& creds_type, const Json& config); + static void Init(); + static void Shutdown(); + static void RegisterXdsChannelCreds( + std::unique_ptr<XdsChannelCredsImpl> creds); +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_CHANNEL_CREDS_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_client.cc b/contrib/libs/grpc/src/core/ext/xds/xds_client.cc index 94106e4e25..cc3be00a5a 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_client.cc +++ b/contrib/libs/grpc/src/core/ext/xds/xds_client.cc @@ -36,8 +36,12 @@ #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_channel_creds.h" #include "src/core/ext/xds/xds_client_stats.h" +#include "src/core/ext/xds/xds_cluster.h" +#include "src/core/ext/xds/xds_endpoint.h" #include "src/core/ext/xds/xds_http_filters.h" +#include "src/core/ext/xds/xds_listener.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" @@ -54,7 +58,6 @@ #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" -#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/uri/uri_parser.h" #define GRPC_XDS_INITIAL_CONNECT_BACKOFF_SECONDS 1 @@ -172,21 +175,53 @@ class XdsClient::ChannelState::AdsCallState XdsClient* xds_client() const { return chand()->xds_client(); } bool seen_response() const { return seen_response_; } - void SubscribeLocked(const TString& type_url, - const XdsApi::ResourceName& name) + void SubscribeLocked(const XdsResourceType* type, const XdsResourceName& name) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - void UnsubscribeLocked(const TString& type_url, - const XdsApi::ResourceName& name, - bool delay_unsubscription) + void UnsubscribeLocked(const XdsResourceType* type, + const XdsResourceName& name, bool delay_unsubscription) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); bool HasSubscribedResources() const; private: - class ResourceState : public InternallyRefCounted<ResourceState> { + class AdsResponseParser : public XdsApi::AdsResponseParserInterface { public: - ResourceState(const TString& type_url, const XdsApi::ResourceName& name) - : type_url_(type_url), name_(name) { + struct Result { + const XdsResourceType* type; + TString type_url; + TString version; + TString nonce; + std::vector<TString> errors; + std::map<TString /*authority*/, std::set<XdsResourceKey>> + resources_seen; + bool have_valid_resources = false; + }; + + explicit AdsResponseParser(AdsCallState* ads_call_state) + : ads_call_state_(ads_call_state) {} + + y_absl::Status ProcessAdsResponseFields(AdsResponseFields fields) override + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + + void ParseResource(const XdsEncodingContext& context, size_t idx, + y_absl::string_view type_url, + y_absl::string_view serialized_resource) override + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); + + Result TakeResult() { return std::move(result_); } + + private: + XdsClient* xds_client() const { return ads_call_state_->xds_client(); } + + AdsCallState* ads_call_state_; + const grpc_millis update_time_ = ExecCtx::Get()->Now(); + Result result_; + }; + + class ResourceTimer : public InternallyRefCounted<ResourceTimer> { + public: + ResourceTimer(const XdsResourceType* type, const XdsResourceName& name) + : type_(type), name_(name) { GRPC_CLOSURE_INIT(&timer_callback_, OnTimer, this, grpc_schedule_on_exec_ctx); } @@ -217,7 +252,7 @@ class XdsClient::ChannelState::AdsCallState private: static void OnTimer(void* arg, grpc_error_handle error) { - ResourceState* self = static_cast<ResourceState*>(arg); + ResourceTimer* self = static_cast<ResourceTimer*>(arg); { MutexLock lock(&self->ads_calld_->xds_client()->mu_); self->OnTimerLocked(GRPC_ERROR_REF(error)); @@ -234,51 +269,30 @@ class XdsClient::ChannelState::AdsCallState grpc_error_handle watcher_error = GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrFormat( "timeout obtaining resource {type=%s name=%s} from xds server", - type_url_, - XdsApi::ConstructFullResourceName(name_.authority, type_url_, - name_.id))); + type_->type_url(), + XdsClient::ConstructFullXdsResourceName( + name_.authority, type_->type_url(), name_.key))); 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(), + gpr_log(GPR_INFO, "[xds_client %p] xds server %s: %s", + ads_calld_->xds_client(), + ads_calld_->chand()->server_.server_uri.c_str(), grpc_error_std_string(watcher_error).c_str()); } auto& authority_state = ads_calld_->xds_client()->authority_state_map_[name_.authority]; - if (type_url_ == XdsApi::kLdsTypeUrl) { - ListenerState& state = authority_state.listener_map[name_.id]; - state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; - Notifier::ScheduleNotifyWatchersOnErrorInWorkSerializer( - ads_calld_->xds_client(), state.watchers, - GRPC_ERROR_REF(watcher_error), DEBUG_LOCATION); - } else if (type_url_ == XdsApi::kRdsTypeUrl) { - RouteConfigState& state = authority_state.route_config_map[name_.id]; - state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; - Notifier::ScheduleNotifyWatchersOnErrorInWorkSerializer( - ads_calld_->xds_client(), state.watchers, - GRPC_ERROR_REF(watcher_error), DEBUG_LOCATION); - } else if (type_url_ == XdsApi::kCdsTypeUrl) { - ClusterState& state = authority_state.cluster_map[name_.id]; - state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; - Notifier::ScheduleNotifyWatchersOnErrorInWorkSerializer( - ads_calld_->xds_client(), state.watchers, - GRPC_ERROR_REF(watcher_error), DEBUG_LOCATION); - } else if (type_url_ == XdsApi::kEdsTypeUrl) { - EndpointState& state = authority_state.endpoint_map[name_.id]; - state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; - Notifier::ScheduleNotifyWatchersOnErrorInWorkSerializer( - ads_calld_->xds_client(), state.watchers, - GRPC_ERROR_REF(watcher_error), DEBUG_LOCATION); - } else { - GPR_UNREACHABLE_CODE(return ); - } - GRPC_ERROR_UNREF(watcher_error); + ResourceState& state = authority_state.resource_map[type_][name_.key]; + state.meta.client_status = XdsApi::ResourceMetadata::DOES_NOT_EXIST; + Notifier::ScheduleNotifyWatchersOnErrorInWorkSerializer( + ads_calld_->xds_client(), state.watchers, watcher_error, + DEBUG_LOCATION); } GRPC_ERROR_UNREF(error); } - const TString type_url_; - const XdsApi::ResourceName name_; + const XdsResourceType* type_; + const XdsResourceName name_; RefCountedPtr<AdsCallState> ads_calld_; bool timer_started_ = false; @@ -296,40 +310,11 @@ class XdsClient::ChannelState::AdsCallState // Subscribed resources of this type. std::map<TString /*authority*/, - std::map<TString /*name*/, OrphanablePtr<ResourceState>>> + std::map<XdsResourceKey, OrphanablePtr<ResourceTimer>>> subscribed_resources; }; - void SendMessageLocked(const TString& type_url) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - - void AcceptLdsUpdateLocked( - TString version, grpc_millis update_time, - XdsApi::LdsUpdateMap lds_update_map, - const std::set<XdsApi::ResourceName>& resource_names_failed) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - void AcceptRdsUpdateLocked(TString version, grpc_millis update_time, - XdsApi::RdsUpdateMap rds_update_map) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - void AcceptCdsUpdateLocked( - TString version, grpc_millis update_time, - XdsApi::CdsUpdateMap cds_update_map, - const std::set<XdsApi::ResourceName>& resource_names_failed) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - void AcceptEdsUpdateLocked(TString version, grpc_millis update_time, - XdsApi::EdsUpdateMap eds_update_map) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - - template <typename StateMap> - void RejectAdsUpdateHelperLocked(const TString& resource_name, - grpc_millis update_time, - const XdsApi::AdsParseResult& result, - const TString& error_details, - StateMap* state_map) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - - void RejectAdsUpdateLocked(grpc_millis update_time, - const XdsApi::AdsParseResult& result) + void SendMessageLocked(const XdsResourceType* type) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); static void OnRequestSent(void* arg, grpc_error_handle error); @@ -344,9 +329,9 @@ class XdsClient::ChannelState::AdsCallState bool IsCurrentCallOnChannel() const; - std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>> - ResourceNamesForRequest(const TString& type_url); + // Constructs a list of resource names of a given type for an ADS + // request. Also starts the timer for each resource if needed. + std::vector<TString> ResourceNamesForRequest(const XdsResourceType* type); // The owning RetryableCall<>. RefCountedPtr<RetryableCall<AdsCallState>> parent_; @@ -375,10 +360,10 @@ class XdsClient::ChannelState::AdsCallState grpc_closure on_status_received_; // Resource types for which requests need to be sent. - std::set<TString /*type_url*/> buffered_requests_; + std::set<const XdsResourceType*> buffered_requests_; // State for each resource type. - std::map<TString /*type_url*/, ResourceTypeState> state_map_; + std::map<const XdsResourceType*, ResourceTypeState> state_map_; }; // Contains an LRS call to the xds server. @@ -503,9 +488,10 @@ class XdsClient::ChannelState::StateWatcher new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) { // In TRANSIENT_FAILURE. Notify all watchers of error. gpr_log(GPR_INFO, - "[xds_client %p] xds channel in state:TRANSIENT_FAILURE " - "status_message:(%s)", - parent_->xds_client(), status.ToString().c_str()); + "[xds_client %p] xds channel for server %s in " + "state TRANSIENT_FAILURE: %s", + parent_->xds_client(), parent_->server_.server_uri.c_str(), + status.ToString().c_str()); parent_->xds_client_->NotifyOnErrorLocked( GRPC_ERROR_CREATE_FROM_STATIC_STRING( "xds channel in TRANSIENT_FAILURE")); @@ -526,8 +512,8 @@ namespace { grpc_channel* CreateXdsChannel(grpc_channel_args* args, const XdsBootstrap::XdsServer& server) { RefCountedPtr<grpc_channel_credentials> channel_creds = - XdsChannelCredsRegistry::MakeChannelCreds(server.channel_creds_type, - server.channel_creds_config); + XdsChannelCredsRegistry::CreateXdsChannelCreds( + server.channel_creds_type, server.channel_creds_config); return grpc_secure_channel_create(channel_creds.get(), server.server_uri.c_str(), args, nullptr); } @@ -553,8 +539,8 @@ XdsClient::ChannelState::ChannelState(WeakRefCountedPtr<XdsClient> xds_client, XdsClient::ChannelState::~ChannelState() { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, "[xds_client %p] Destroying xds channel %p", xds_client(), - this); + gpr_log(GPR_INFO, "[xds_client %p] destroying xds channel %p for server %s", + xds_client(), this, server_.server_uri.c_str()); } grpc_channel_destroy(channel_); xds_client_.reset(DEBUG_LOCATION, "ChannelState"); @@ -612,8 +598,8 @@ void XdsClient::ChannelState::CancelConnectivityWatchLocked() { client_channel->RemoveConnectivityWatcher(watcher_); } -void XdsClient::ChannelState::SubscribeLocked( - const TString& type_url, const XdsApi::ResourceName& name) { +void XdsClient::ChannelState::SubscribeLocked(const XdsResourceType* type, + const XdsResourceName& name) { if (ads_calld_ == nullptr) { // Start the ADS call if this is the first request. ads_calld_.reset(new RetryableCall<AdsCallState>( @@ -627,16 +613,16 @@ void XdsClient::ChannelState::SubscribeLocked( // 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()->SubscribeLocked(type_url, name); + ads_calld()->SubscribeLocked(type, name); } -void XdsClient::ChannelState::UnsubscribeLocked( - const TString& type_url, const XdsApi::ResourceName& name, - bool delay_unsubscription) { +void XdsClient::ChannelState::UnsubscribeLocked(const XdsResourceType* type, + const XdsResourceName& name, + bool delay_unsubscription) { if (ads_calld_ != nullptr) { auto* calld = ads_calld_->calld(); if (calld != nullptr) { - calld->UnsubscribeLocked(type_url, name, delay_unsubscription); + calld->UnsubscribeLocked(type, name, delay_unsubscription); if (!calld->HasSubscribedResources()) { ads_calld_.reset(); } @@ -694,10 +680,10 @@ void XdsClient::ChannelState::RetryableCall<T>::StartNewCallLocked() { GPR_ASSERT(chand_->channel_ != nullptr); GPR_ASSERT(calld_ == nullptr); if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] Start new call from retryable call (chand: %p, " - "retryable call: %p)", - chand()->xds_client(), chand(), this); + gpr_log( + GPR_INFO, + "[xds_client %p] xds server %s: start new call from retryable call %p", + chand()->xds_client(), chand()->server_.server_uri.c_str(), this); } calld_ = MakeOrphanable<T>( this->Ref(DEBUG_LOCATION, "RetryableCall+start_new_call")); @@ -711,9 +697,10 @@ void XdsClient::ChannelState::RetryableCall<T>::StartRetryTimerLocked() { grpc_millis timeout = std::max(next_attempt_time - ExecCtx::Get()->Now(), grpc_millis(0)); gpr_log(GPR_INFO, - "[xds_client %p] Failed to connect to xds server (chand: %p) " + "[xds_client %p] xds server %s: call attempt failed; " "retry timer will fire in %" PRId64 "ms.", - chand()->xds_client(), chand(), timeout); + chand()->xds_client(), chand()->server_.server_uri.c_str(), + timeout); } this->Ref(DEBUG_LOCATION, "RetryableCall+retry_timer_start").release(); grpc_timer_init(&retry_timer_, next_attempt_time, &on_retry_timer_); @@ -737,10 +724,10 @@ void XdsClient::ChannelState::RetryableCall<T>::OnRetryTimerLocked( retry_timer_callback_pending_ = false; if (!shutting_down_ && error == GRPC_ERROR_NONE) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log( - GPR_INFO, - "[xds_client %p] Retry timer fires (chand: %p, retryable call: %p)", - chand()->xds_client(), chand(), this); + gpr_log(GPR_INFO, + "[xds_client %p] xds server %s: retry timer fired (retryable " + "call: %p)", + chand()->xds_client(), chand()->server_.server_uri.c_str(), this); } StartNewCallLocked(); } @@ -748,6 +735,173 @@ void XdsClient::ChannelState::RetryableCall<T>::OnRetryTimerLocked( } // +// XdsClient::ChannelState::AdsCallState::AdsResponseParser +// + +y_absl::Status XdsClient::ChannelState::AdsCallState::AdsResponseParser:: + ProcessAdsResponseFields(AdsResponseFields fields) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { + gpr_log( + GPR_INFO, + "[xds_client %p] xds server %s: received ADS response: type_url=%s, " + "version=%s, nonce=%s, num_resources=%" PRIuPTR, + ads_call_state_->xds_client(), + ads_call_state_->chand()->server_.server_uri.c_str(), + fields.type_url.c_str(), fields.version.c_str(), fields.nonce.c_str(), + fields.num_resources); + } + result_.type = + ads_call_state_->xds_client()->GetResourceTypeLocked(fields.type_url); + if (result_.type == nullptr) { + return y_absl::InvalidArgumentError( + y_absl::StrCat("unknown resource type ", fields.type_url)); + } + result_.type_url = std::move(fields.type_url); + result_.version = std::move(fields.version); + result_.nonce = std::move(fields.nonce); + return y_absl::OkStatus(); +} + +namespace { + +// Build a resource metadata struct for ADS result accepting methods and CSDS. +XdsApi::ResourceMetadata CreateResourceMetadataAcked( + TString serialized_proto, TString 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; +} + +// Update resource_metadata for NACK. +void UpdateResourceMetadataNacked(const TString& version, + const TString& details, + grpc_millis update_time, + XdsApi::ResourceMetadata* resource_metadata) { + resource_metadata->client_status = XdsApi::ResourceMetadata::NACKED; + resource_metadata->failed_version = version; + resource_metadata->failed_details = details; + resource_metadata->failed_update_time = update_time; +} + +} // namespace + +void XdsClient::ChannelState::AdsCallState::AdsResponseParser::ParseResource( + const XdsEncodingContext& context, size_t idx, y_absl::string_view type_url, + y_absl::string_view serialized_resource) { + // Check the type_url of the resource. + bool is_v2 = false; + if (!result_.type->IsType(type_url, &is_v2)) { + result_.errors.emplace_back( + y_absl::StrCat("resource index ", idx, ": incorrect resource type ", + type_url, " (should be ", result_.type_url, ")")); + return; + } + // Parse the resource. + y_absl::StatusOr<XdsResourceType::DecodeResult> result = + result_.type->Decode(context, serialized_resource, is_v2); + if (!result.ok()) { + result_.errors.emplace_back( + y_absl::StrCat("resource index ", idx, ": ", result.status().ToString())); + return; + } + // Check the resource name. + auto resource_name = + XdsClient::ParseXdsResourceName(result->name, result_.type); + if (!resource_name.ok()) { + result_.errors.emplace_back(y_absl::StrCat( + "resource index ", idx, ": Cannot parse xDS resource name \"", + result->name, "\"")); + return; + } + // Cancel resource-does-not-exist timer, if needed. + auto timer_it = ads_call_state_->state_map_.find(result_.type); + if (timer_it != ads_call_state_->state_map_.end()) { + auto it = + timer_it->second.subscribed_resources.find(resource_name->authority); + if (it != timer_it->second.subscribed_resources.end()) { + auto res_it = it->second.find(resource_name->key); + if (res_it != it->second.end()) { + res_it->second->MaybeCancelTimer(); + } + } + } + // Lookup the authority in the cache. + auto authority_it = + xds_client()->authority_state_map_.find(resource_name->authority); + if (authority_it == xds_client()->authority_state_map_.end()) { + return; // Skip resource -- we don't have a subscription for it. + } + // Found authority, so look up type. + AuthorityState& authority_state = authority_it->second; + auto type_it = authority_state.resource_map.find(result_.type); + if (type_it == authority_state.resource_map.end()) { + return; // Skip resource -- we don't have a subscription for it. + } + auto& type_map = type_it->second; + // Found type, so look up resource key. + auto it = type_map.find(resource_name->key); + if (it == type_map.end()) { + return; // Skip resource -- we don't have a subscription for it. + } + ResourceState& resource_state = it->second; + // If needed, record that we've seen this resource. + if (result_.type->AllResourcesRequiredInSotW()) { + result_.resources_seen[resource_name->authority].insert(resource_name->key); + } + // Update resource state based on whether the resource is valid. + if (!result->resource.ok()) { + result_.errors.emplace_back(y_absl::StrCat( + "resource index ", idx, ": ", result->name, + ": validation error: ", result->resource.status().ToString())); + Notifier::ScheduleNotifyWatchersOnErrorInWorkSerializer( + xds_client(), resource_state.watchers, + grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( + "invalid resource: ", result->resource.status().ToString())), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE), + DEBUG_LOCATION); + UpdateResourceMetadataNacked(result_.version, + result->resource.status().ToString(), + update_time_, &resource_state.meta); + return; + } + // Resource is valid. + result_.have_valid_resources = true; + // If it didn't change, ignore it. + if (resource_state.resource != nullptr && + result_.type->ResourcesEqual(resource_state.resource.get(), + result->resource->get())) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { + gpr_log(GPR_INFO, + "[xds_client %p] %s resource %s identical to current, ignoring.", + xds_client(), result_.type_url.c_str(), result->name.c_str()); + } + return; + } + // Update the resource state. + resource_state.resource = std::move(*result->resource); + resource_state.meta = CreateResourceMetadataAcked( + TString(serialized_resource), result_.version, update_time_); + // Notify watchers. + auto& watchers_list = resource_state.watchers; + auto* value = + result_.type->CopyResource(resource_state.resource.get()).release(); + xds_client()->work_serializer_.Schedule( + [watchers_list, value]() + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&xds_client()->work_serializer_) { + for (const auto& p : watchers_list) { + p.first->OnGenericResourceChanged(value); + } + delete value; + }, + DEBUG_LOCATION); +} + +// // XdsClient::ChannelState::AdsCallState // @@ -763,13 +917,16 @@ XdsClient::ChannelState::AdsCallState::AdsCallState( // the polling entities from client_channel. GPR_ASSERT(xds_client() != nullptr); // Create a call with the specified method name. - const auto& method = + const char* method = chand()->server_.ShouldUseV3() - ? GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V3_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES - : GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES; + ? "/envoy.service.discovery.v3.AggregatedDiscoveryService/" + "StreamAggregatedResources" + : "/envoy.service.discovery.v2.AggregatedDiscoveryService/" + "StreamAggregatedResources"; call_ = grpc_channel_create_pollset_set_call( chand()->channel_, nullptr, GRPC_PROPAGATE_DEFAULTS, - xds_client()->interested_parties_, method, nullptr, + xds_client()->interested_parties_, + StaticSlice::FromStaticString(method).c_slice(), nullptr, GRPC_MILLIS_INF_FUTURE, nullptr); GPR_ASSERT(call_ != nullptr); // Init data associated with the call. @@ -778,9 +935,9 @@ XdsClient::ChannelState::AdsCallState::AdsCallState( // Start the call. if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, - "[xds_client %p] Starting ADS call (chand: %p, calld: %p, " - "call: %p)", - xds_client(), chand(), this, call_); + "[xds_client %p] xds server %s: starting ADS call " + "(calld: %p, call: %p)", + xds_client(), chand()->server_.server_uri.c_str(), this, call_); } // Create the ops. grpc_call_error call_error; @@ -804,21 +961,12 @@ XdsClient::ChannelState::AdsCallState::AdsCallState( const TString& authority = a.first; // Skip authorities that are not using this xDS channel. if (a.second.channel_state != chand()) continue; - for (const auto& l : a.second.listener_map) { - const TString& listener_name = l.first; - SubscribeLocked(XdsApi::kLdsTypeUrl, {authority, listener_name}); - } - for (const auto& r : a.second.route_config_map) { - const TString& route_config_name = r.first; - SubscribeLocked(XdsApi::kRdsTypeUrl, {authority, route_config_name}); - } - for (const auto& c : a.second.cluster_map) { - const TString& cluster_name = c.first; - SubscribeLocked(XdsApi::kCdsTypeUrl, {authority, cluster_name}); - } - for (const auto& e : a.second.endpoint_map) { - const TString& endpoint_name = e.first; - SubscribeLocked(XdsApi::kEdsTypeUrl, {authority, endpoint_name}); + for (const auto& t : a.second.resource_map) { + const XdsResourceType* type = t.first; + for (const auto& r : t.second) { + const XdsResourceKey& resource_key = r.first; + SubscribeLocked(type, {authority, resource_key}); + } } } // Op: recv initial metadata. @@ -883,33 +1031,29 @@ void XdsClient::ChannelState::AdsCallState::Orphan() { } void XdsClient::ChannelState::AdsCallState::SendMessageLocked( - const TString& type_url) + const XdsResourceType* type) Y_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); + buffered_requests_.insert(type); return; } - auto& state = state_map_[type_url]; + auto& state = state_map_[type]; grpc_slice request_payload_slice; - std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>> - resource_map = ResourceNamesForRequest(type_url); request_payload_slice = xds_client()->api_.CreateAdsRequest( - chand()->server_, type_url, resource_map, - chand()->resource_type_version_map_[type_url], state.nonce, - GRPC_ERROR_REF(state.error), !sent_initial_message_); - if (type_url != XdsApi::kLdsTypeUrl && type_url != XdsApi::kRdsTypeUrl && - type_url != XdsApi::kCdsTypeUrl && type_url != XdsApi::kEdsTypeUrl) { - state_map_.erase(type_url); - } + chand()->server_, + chand()->server_.ShouldUseV3() ? type->type_url() : type->v2_type_url(), + chand()->resource_type_version_map_[type], state.nonce, + ResourceNamesForRequest(type), GRPC_ERROR_REF(state.error), + !sent_initial_message_); sent_initial_message_ = true; if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, - "[xds_client %p] sending ADS request: type=%s version=%s nonce=%s " - "error=%s", - xds_client(), type_url.c_str(), - chand()->resource_type_version_map_[type_url].c_str(), + "[xds_client %p] xds server %s: sending ADS request: type=%s " + "version=%s nonce=%s error=%s", + xds_client(), chand()->server_.server_uri.c_str(), + TString(type->type_url()).c_str(), + chand()->resource_type_version_map_[type].c_str(), state.nonce.c_str(), grpc_error_std_string(state.error).c_str()); } GRPC_ERROR_UNREF(state.error); @@ -930,32 +1074,33 @@ void XdsClient::ChannelState::AdsCallState::SendMessageLocked( grpc_call_start_batch_and_execute(call_, &op, 1, &on_request_sent_); if (GPR_UNLIKELY(call_error != GRPC_CALL_OK)) { gpr_log(GPR_ERROR, - "[xds_client %p] calld=%p call_error=%d sending ADS message", - xds_client(), this, call_error); + "[xds_client %p] xds server %s: error starting ADS send_message " + "batch on calld=%p: call_error=%d", + xds_client(), chand()->server_.server_uri.c_str(), this, + call_error); GPR_ASSERT(GRPC_CALL_OK == call_error); } } void XdsClient::ChannelState::AdsCallState::SubscribeLocked( - const TString& type_url, const XdsApi::ResourceName& name) { - auto& state = - state_map_[type_url].subscribed_resources[name.authority][name.id]; + const XdsResourceType* type, const XdsResourceName& name) { + auto& state = state_map_[type].subscribed_resources[name.authority][name.key]; if (state == nullptr) { - state = MakeOrphanable<ResourceState>(type_url, name); - SendMessageLocked(type_url); + state = MakeOrphanable<ResourceTimer>(type, name); + SendMessageLocked(type); } } void XdsClient::ChannelState::AdsCallState::UnsubscribeLocked( - const TString& type_url, const XdsApi::ResourceName& name, + const XdsResourceType* type, const XdsResourceName& name, bool delay_unsubscription) { - auto& type_state_map = state_map_[type_url]; + auto& type_state_map = state_map_[type]; auto& authority_map = type_state_map.subscribed_resources[name.authority]; - authority_map.erase(name.id); + authority_map.erase(name.key); if (authority_map.empty()) { type_state_map.subscribed_resources.erase(name.authority); } - if (!delay_unsubscription) SendMessageLocked(type_url); + if (!delay_unsubscription) SendMessageLocked(type); } bool XdsClient::ChannelState::AdsCallState::HasSubscribedResources() const { @@ -965,395 +1110,6 @@ bool XdsClient::ChannelState::AdsCallState::HasSubscribedResources() const { return false; } -namespace { - -// Build a resource metadata struct for ADS result accepting methods and CSDS. -XdsApi::ResourceMetadata CreateResourceMetadataAcked( - TString serialized_proto, TString 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( - TString version, grpc_millis update_time, - XdsApi::LdsUpdateMap lds_update_map, - const std::set<XdsApi::ResourceName>& resource_names_failed) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] LDS update received containing %" PRIuPTR - " resources", - xds_client(), lds_update_map.size()); - } - auto& lds_state = state_map_[XdsApi::kLdsTypeUrl]; - for (auto& p : lds_update_map) { - const XdsApi::ResourceName& name = p.first; - XdsApi::LdsUpdate& lds_update = p.second.resource; - auto it = lds_state.subscribed_resources.find(name.authority); - if (it != lds_state.subscribed_resources.end()) { - auto res_it = it->second.find(name.id); - if (res_it != it->second.end()) { - res_it->second->MaybeCancelTimer(); - } - } - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, "[xds_client %p] LDS resource %s: %s", xds_client(), - XdsApi::ConstructFullResourceName(name.authority, - XdsApi::kLdsTypeUrl, name.id) - .c_str(), - lds_update.ToString().c_str()); - } - ListenerState& listener_state = xds_client() - ->authority_state_map_[name.authority] - .listener_map[name.id]; - // Ignore identical update. - if (listener_state.update.has_value() && - *listener_state.update == lds_update) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] LDS update for %s identical to current, " - "ignoring.", - xds_client(), - XdsApi::ConstructFullResourceName(name.authority, - XdsApi::kLdsTypeUrl, name.id) - .c_str()); - } - continue; - } - // 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. - auto& watchers_list = listener_state.watchers; - auto& value = listener_state.update.value(); - xds_client()->work_serializer_.Schedule( - [watchers_list, value]() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&xds_client()->work_serializer_) { - for (const auto& p : watchers_list) { - p.first->OnListenerChanged(value); - } - }, - DEBUG_LOCATION); - } - // For invalid resources in the update, if they are already in the - // cache, pretend that they are present in the update, so that we - // don't incorrectly consider them deleted below. - for (const auto& name : resource_names_failed) { - auto& listener_map = - xds_client()->authority_state_map_[name.authority].listener_map; - auto it = listener_map.find(name.id); - if (it != listener_map.end()) { - auto& update = it->second.update; - if (!update.has_value()) continue; - lds_update_map[name]; - } - } - // For any subscribed resource that is not present in the update, - // remove it from the cache and notify watchers that it does not exist. - for (const auto& a : lds_state.subscribed_resources) { - const TString& authority_name = a.first; - for (const auto& p : a.second) { - const TString& listener_name = p.first; - if (lds_update_map.find({authority_name, listener_name}) == - lds_update_map.end()) { - ListenerState& listener_state = - xds_client() - ->authority_state_map_[authority_name] - .listener_map[listener_name]; - // If the resource was newly requested but has not yet been received, - // we don't want to generate an error for the watchers, because this LDS - // response may be in reaction to an earlier request that did not yet - // request the new resource, so its absence from the response does not - // necessarily indicate that the resource does not exist. - // For that case, we rely on the request timeout instead. - if (!listener_state.update.has_value()) continue; - listener_state.update.reset(); - Notifier::ScheduleNotifyWatchersOnResourceDoesNotExistInWorkSerializer( - xds_client(), listener_state.watchers, DEBUG_LOCATION); - } - } - } -} - -void XdsClient::ChannelState::AdsCallState::AcceptRdsUpdateLocked( - TString version, grpc_millis update_time, - XdsApi::RdsUpdateMap rds_update_map) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] RDS update received containing %" PRIuPTR - " resources", - xds_client(), rds_update_map.size()); - } - auto& rds_state = state_map_[XdsApi::kRdsTypeUrl]; - for (auto& p : rds_update_map) { - const XdsApi::ResourceName& name = p.first; - XdsApi::RdsUpdate& rds_update = p.second.resource; - auto it = rds_state.subscribed_resources.find(name.authority); - if (it != rds_state.subscribed_resources.end()) { - auto res_it = it->second.find(name.id); - if (res_it != it->second.end()) { - res_it->second->MaybeCancelTimer(); - } - } - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, "[xds_client %p] RDS resource:\n%s", xds_client(), - rds_update.ToString().c_str()); - } - RouteConfigState& route_config_state = - xds_client() - ->authority_state_map_[name.authority] - .route_config_map[name.id]; - // Ignore identical update. - if (route_config_state.update.has_value() && - *route_config_state.update == rds_update) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] RDS resource identical to current, ignoring", - xds_client()); - } - continue; - } - // 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. - auto& watchers_list = route_config_state.watchers; - auto& value = route_config_state.update.value(); - xds_client()->work_serializer_.Schedule( - [watchers_list, value]() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&xds_client()->work_serializer_) { - for (const auto& p : watchers_list) { - p.first->OnRouteConfigChanged(value); - } - }, - DEBUG_LOCATION); - } -} - -void XdsClient::ChannelState::AdsCallState::AcceptCdsUpdateLocked( - TString version, grpc_millis update_time, - XdsApi::CdsUpdateMap cds_update_map, - const std::set<XdsApi::ResourceName>& resource_names_failed) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] CDS update received containing %" PRIuPTR - " resources", - xds_client(), cds_update_map.size()); - } - auto& cds_state = state_map_[XdsApi::kCdsTypeUrl]; - for (auto& p : cds_update_map) { - const XdsApi::ResourceName& name = p.first; - XdsApi::CdsUpdate& cds_update = p.second.resource; - auto it = cds_state.subscribed_resources.find(name.authority); - if (it != cds_state.subscribed_resources.end()) { - auto res_it = it->second.find(name.id); - if (res_it != it->second.end()) { - res_it->second->MaybeCancelTimer(); - } - } - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, "[xds_client %p] cluster=%s: %s", xds_client(), - XdsApi::ConstructFullResourceName(name.authority, - XdsApi::kCdsTypeUrl, name.id) - .c_str(), - cds_update.ToString().c_str()); - } - ClusterState& cluster_state = - xds_client()->authority_state_map_[name.authority].cluster_map[name.id]; - // Ignore identical update. - if (cluster_state.update.has_value() && - *cluster_state.update == cds_update) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] CDS update identical to current, ignoring.", - xds_client()); - } - continue; - } - // 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. - auto& watchers_list = cluster_state.watchers; - auto& value = cluster_state.update.value(); - xds_client()->work_serializer_.Schedule( - [watchers_list, value]() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&xds_client()->work_serializer_) { - for (const auto& p : watchers_list) { - p.first->OnClusterChanged(value); - } - }, - DEBUG_LOCATION); - } - // For invalid resources in the update, if they are already in the - // cache, pretend that they are present in the update, so that we - // don't incorrectly consider them deleted below. - for (const auto& name : resource_names_failed) { - auto& cluster_map = - xds_client()->authority_state_map_[name.authority].cluster_map; - auto it = cluster_map.find(name.id); - if (it != cluster_map.end()) { - auto& update = it->second.update; - if (!update.has_value()) continue; - cds_update_map[name]; - } - } - // For any subscribed resource that is not present in the update, - // remove it from the cache and notify watchers that it does not exist. - for (const auto& a : cds_state.subscribed_resources) { - const TString& authority = a.first; - for (const auto& p : a.second) { - const TString& cluster_name = p.first; - if (cds_update_map.find({authority, cluster_name}) == - cds_update_map.end()) { - ClusterState& cluster_state = xds_client() - ->authority_state_map_[authority] - .cluster_map[cluster_name]; - // If the resource was newly requested but has not yet been received, - // we don't want to generate an error for the watchers, because this CDS - // response may be in reaction to an earlier request that did not yet - // request the new resource, so its absence from the response does not - // necessarily indicate that the resource does not exist. - // For that case, we rely on the request timeout instead. - if (!cluster_state.update.has_value()) continue; - cluster_state.update.reset(); - Notifier::ScheduleNotifyWatchersOnResourceDoesNotExistInWorkSerializer( - xds_client(), cluster_state.watchers, DEBUG_LOCATION); - } - } - } -} - -void XdsClient::ChannelState::AdsCallState::AcceptEdsUpdateLocked( - TString version, grpc_millis update_time, - XdsApi::EdsUpdateMap eds_update_map) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] EDS update received containing %" PRIuPTR - " resources", - xds_client(), eds_update_map.size()); - } - auto& eds_state = state_map_[XdsApi::kEdsTypeUrl]; - for (auto& p : eds_update_map) { - const XdsApi::ResourceName& name = p.first; - XdsApi::EdsUpdate& eds_update = p.second.resource; - auto it = eds_state.subscribed_resources.find(name.authority); - if (it != eds_state.subscribed_resources.end()) { - auto res_it = it->second.find(name.id); - if (res_it != it->second.end()) { - res_it->second->MaybeCancelTimer(); - } - } - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, "[xds_client %p] EDS resource %s: %s", xds_client(), - XdsApi::ConstructFullResourceName(name.authority, - XdsApi::kCdsTypeUrl, name.id) - .c_str(), - eds_update.ToString().c_str()); - } - EndpointState& endpoint_state = xds_client() - ->authority_state_map_[name.authority] - .endpoint_map[name.id]; - // Ignore identical update. - if (endpoint_state.update.has_value() && - *endpoint_state.update == eds_update) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] EDS update identical to current, ignoring.", - xds_client()); - } - continue; - } - // 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. - auto& watchers_list = endpoint_state.watchers; - auto& value = endpoint_state.update.value(); - xds_client()->work_serializer_.Schedule( - [watchers_list, value]() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&xds_client()->work_serializer_) { - for (const auto& p : watchers_list) { - p.first->OnEndpointChanged(value); - } - }, - DEBUG_LOCATION); - } -} - -namespace { - -// Update resource_metadata for NACK. -void UpdateResourceMetadataNacked(const TString& version, - const TString& details, - grpc_millis update_time, - XdsApi::ResourceMetadata* resource_metadata) { - resource_metadata->client_status = XdsApi::ResourceMetadata::NACKED; - resource_metadata->failed_version = version; - resource_metadata->failed_details = details; - resource_metadata->failed_update_time = update_time; -} - -} // namespace - -template <typename StateMap> -void XdsClient::ChannelState::AdsCallState::RejectAdsUpdateHelperLocked( - const TString& resource_name, grpc_millis update_time, - const XdsApi::AdsParseResult& result, const TString& error_details, - StateMap* state_map) { - auto it = state_map->find(resource_name); - if (it == state_map->end()) return; - auto& state = it->second; - Notifier::ScheduleNotifyWatchersOnErrorInWorkSerializer( - xds_client(), state.watchers, GRPC_ERROR_REF(result.parse_error), - DEBUG_LOCATION); - UpdateResourceMetadataNacked(result.version, error_details, update_time, - &state.meta); -} - -void XdsClient::ChannelState::AdsCallState::RejectAdsUpdateLocked( - grpc_millis update_time, const XdsApi::AdsParseResult& result) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] %s update NACKed containing %" PRIuPTR - " invalid resources", - xds_client(), result.type_url.c_str(), - result.resource_names_failed.size()); - } - TString details = grpc_error_std_string(result.parse_error); - for (auto& resource : result.resource_names_failed) { - auto authority_it = - xds_client()->authority_state_map_.find(resource.authority); - if (authority_it == xds_client()->authority_state_map_.end()) continue; - AuthorityState& authority_state = authority_it->second; - if (result.type_url == XdsApi::kLdsTypeUrl) { - RejectAdsUpdateHelperLocked(resource.id, update_time, result, details, - &authority_state.listener_map); - } else if (result.type_url == XdsApi::kRdsTypeUrl) { - RejectAdsUpdateHelperLocked(resource.id, update_time, result, details, - &authority_state.route_config_map); - } else if (result.type_url == XdsApi::kCdsTypeUrl) { - RejectAdsUpdateHelperLocked(resource.id, update_time, result, details, - &authority_state.cluster_map); - } else if (result.type_url == XdsApi::kEdsTypeUrl) { - RejectAdsUpdateHelperLocked(resource.id, update_time, result, details, - &authority_state.endpoint_map); - } else { - GPR_ASSERT(0); - } - } -} - void XdsClient::ChannelState::AdsCallState::OnRequestSent( void* arg, grpc_error_handle error) { AdsCallState* ads_calld = static_cast<AdsCallState*>(arg); @@ -1413,63 +1169,76 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() { grpc_byte_buffer_destroy(recv_message_payload_); recv_message_payload_ = nullptr; // Parse and validate the response. - XdsApi::AdsParseResult result = xds_client()->api_.ParseAdsResponse( - chand()->server_, response_slice, - ResourceNamesForRequest(XdsApi::kLdsTypeUrl), - ResourceNamesForRequest(XdsApi::kRdsTypeUrl), - ResourceNamesForRequest(XdsApi::kCdsTypeUrl), - ResourceNamesForRequest(XdsApi::kEdsTypeUrl)); + AdsResponseParser parser(this); + y_absl::Status status = xds_client()->api_.ParseAdsResponse( + chand()->server_, response_slice, &parser); grpc_slice_unref_internal(response_slice); - if (result.type_url.empty()) { + if (!status.ok()) { // Ignore unparsable response. gpr_log(GPR_ERROR, - "[xds_client %p] Error parsing ADS response (%s) -- ignoring", - xds_client(), grpc_error_std_string(result.parse_error).c_str()); - GRPC_ERROR_UNREF(result.parse_error); + "[xds_client %p] xds server %s: error parsing ADS response (%s) " + "-- ignoring", + xds_client(), chand()->server_.server_uri.c_str(), + status.ToString().c_str()); } else { - grpc_millis update_time = ExecCtx::Get()->Now(); + AdsResponseParser::Result result = parser.TakeResult(); // Update nonce. - auto& state = state_map_[result.type_url]; - state.nonce = std::move(result.nonce); - // If we got an error, we'll NACK the update. - if (result.parse_error != GRPC_ERROR_NONE) { - gpr_log(GPR_ERROR, - "[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_std_string(result.parse_error).c_str()); - result.parse_error = - grpc_error_set_int(result.parse_error, GRPC_ERROR_INT_GRPC_STATUS, - GRPC_STATUS_UNAVAILABLE); + auto& state = state_map_[result.type]; + state.nonce = result.nonce; + // If we got an error, set state.error so that we'll NACK the update. + if (!result.errors.empty()) { + TString error = y_absl::StrJoin(result.errors, "; "); + gpr_log( + GPR_ERROR, + "[xds_client %p] xds server %s: ADS response invalid for resource " + "type %s version %s, will NACK: nonce=%s error=%s", + xds_client(), chand()->server_.server_uri.c_str(), + result.type_url.c_str(), result.version.c_str(), state.nonce.c_str(), + error.c_str()); GRPC_ERROR_UNREF(state.error); - state.error = result.parse_error; - RejectAdsUpdateLocked(update_time, result); - } - // Process any valid resources. - bool have_valid_resources = false; - if (result.type_url == XdsApi::kLdsTypeUrl) { - have_valid_resources = !result.lds_update_map.empty(); - AcceptLdsUpdateLocked(result.version, update_time, - std::move(result.lds_update_map), - result.resource_names_failed); - } else if (result.type_url == XdsApi::kRdsTypeUrl) { - have_valid_resources = !result.rds_update_map.empty(); - AcceptRdsUpdateLocked(result.version, update_time, - std::move(result.rds_update_map)); - } else if (result.type_url == XdsApi::kCdsTypeUrl) { - have_valid_resources = !result.cds_update_map.empty(); - AcceptCdsUpdateLocked(result.version, update_time, - std::move(result.cds_update_map), - result.resource_names_failed); - } else if (result.type_url == XdsApi::kEdsTypeUrl) { - have_valid_resources = !result.eds_update_map.empty(); - AcceptEdsUpdateLocked(result.version, update_time, - std::move(result.eds_update_map)); + state.error = grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_CPP_STRING(std::move(error)), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE); + } + // Delete resources not seen in update if needed. + if (result.type->AllResourcesRequiredInSotW()) { + for (auto& a : xds_client()->authority_state_map_) { + const TString& authority = a.first; + AuthorityState& authority_state = a.second; + // Skip authorities that are not using this xDS channel. + if (authority_state.channel_state != chand()) continue; + auto seen_authority_it = result.resources_seen.find(authority); + // Find this resource type. + auto type_it = authority_state.resource_map.find(result.type); + if (type_it == authority_state.resource_map.end()) continue; + // Iterate over resource ids. + for (auto& r : type_it->second) { + const XdsResourceKey& resource_key = r.first; + ResourceState& resource_state = r.second; + if (seen_authority_it == result.resources_seen.end() || + seen_authority_it->second.find(resource_key) == + seen_authority_it->second.end()) { + // If the resource was newly requested but has not yet been + // received, we don't want to generate an error for the watchers, + // because this ADS response may be in reaction to an earlier + // request that did not yet request the new resource, so its absence + // from the response does not necessarily indicate that the resource + // does not exist. For that case, we rely on the request timeout + // instead. + if (resource_state.resource == nullptr) continue; + resource_state.resource.reset(); + Notifier:: + ScheduleNotifyWatchersOnResourceDoesNotExistInWorkSerializer( + xds_client(), resource_state.watchers, DEBUG_LOCATION); + } + } + } } - if (have_valid_resources) { + // If we had valid resources, update the version. + if (result.have_valid_resources) { seen_response_ = true; - chand()->resource_type_version_map_[result.type_url] = result.version; + chand()->resource_type_version_map_[result.type] = + std::move(result.version); // Start load reporting if needed. auto& lrs_call = chand()->lrs_calld_; if (lrs_call != nullptr) { @@ -1478,7 +1247,7 @@ bool XdsClient::ChannelState::AdsCallState::OnResponseReceivedLocked() { } } // Send ACK or NACK. - SendMessageLocked(result.type_url); + SendMessageLocked(result.type); } if (xds_client()->shutting_down_) return true; // Keep listening for updates. @@ -1512,9 +1281,11 @@ void XdsClient::ChannelState::AdsCallState::OnStatusReceivedLocked( 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_, + "[xds_client %p] xds server %s: ADS call status received " + "(chand=%p, ads_calld=%p, call=%p): " + "status=%d, details='%s', error='%s'", + xds_client(), chand()->server_.server_uri.c_str(), chand(), this, + call_, status_code_, status_details, grpc_error_std_string(error).c_str()); gpr_free(status_details); } @@ -1536,23 +1307,24 @@ bool XdsClient::ChannelState::AdsCallState::IsCurrentCallOnChannel() const { return this == chand()->ads_calld_->calld(); } -std::map<y_absl::string_view /*authority*/, std::set<y_absl::string_view /*name*/>> +std::vector<TString> XdsClient::ChannelState::AdsCallState::ResourceNamesForRequest( - const TString& type_url) { - std::map<y_absl::string_view /*authority*/, - std::set<y_absl::string_view /*name*/>> - resource_map; - auto it = state_map_.find(type_url); + const XdsResourceType* type) { + std::vector<TString> resource_names; + auto it = state_map_.find(type); if (it != state_map_.end()) { for (auto& a : it->second.subscribed_resources) { + const TString& authority = a.first; for (auto& p : a.second) { - resource_map[a.first].insert(p.first); - OrphanablePtr<ResourceState>& state = p.second; - state->MaybeStartTimer(Ref(DEBUG_LOCATION, "ResourceState")); + const XdsResourceKey& resource_key = p.first; + resource_names.emplace_back(XdsClient::ConstructFullXdsResourceName( + authority, type->type_url(), resource_key)); + OrphanablePtr<ResourceTimer>& resource_timer = p.second; + resource_timer->MaybeStartTimer(Ref(DEBUG_LOCATION, "ResourceTimer")); } } } - return resource_map; + return resource_names; } // @@ -1642,8 +1414,10 @@ bool XdsClient::ChannelState::LrsCallState::Reporter::SendReportLocked() { parent_->call_, &op, 1, &on_report_done_); if (GPR_UNLIKELY(call_error != GRPC_CALL_OK)) { gpr_log(GPR_ERROR, - "[xds_client %p] calld=%p call_error=%d sending client load report", - xds_client(), this, call_error); + "[xds_client %p] xds server %s: error starting LRS send_message " + "batch on calld=%p: call_error=%d", + xds_client(), parent_->chand()->server_.server_uri.c_str(), this, + call_error); GPR_ASSERT(GRPC_CALL_OK == call_error); } return false; @@ -1698,13 +1472,14 @@ XdsClient::ChannelState::LrsCallState::LrsCallState( // activity in xds_client()->interested_parties_, which is comprised of // the polling entities from client_channel. GPR_ASSERT(xds_client() != nullptr); - const auto& method = + const char* method = chand()->server_.ShouldUseV3() - ? GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V3_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS - : GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V2_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS; + ? "/envoy.service.load_stats.v3.LoadReportingService/StreamLoadStats" + : "/envoy.service.load_stats.v2.LoadReportingService/StreamLoadStats"; call_ = grpc_channel_create_pollset_set_call( chand()->channel_, nullptr, GRPC_PROPAGATE_DEFAULTS, - xds_client()->interested_parties_, method, nullptr, + xds_client()->interested_parties_, + StaticSlice::FromStaticString(method).c_slice(), nullptr, GRPC_MILLIS_INF_FUTURE, nullptr); GPR_ASSERT(call_ != nullptr); // Init the request payload. @@ -1718,10 +1493,10 @@ XdsClient::ChannelState::LrsCallState::LrsCallState( grpc_metadata_array_init(&trailing_metadata_recv_); // Start the call. if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] Starting LRS call (chand: %p, calld: %p, " - "call: %p)", - xds_client(), chand(), this, call_); + gpr_log( + GPR_INFO, + "[xds_client %p] xds server %s: starting LRS call (calld=%p, call=%p)", + xds_client(), chand()->server_.server_uri.c_str(), this, call_); } // Create the ops. grpc_call_error call_error; @@ -1881,8 +1656,9 @@ bool XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() { &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_std_string(parse_error).c_str()); + "[xds_client %p] xds server %s: LRS response parsing failed: %s", + xds_client(), chand()->server_.server_uri.c_str(), + grpc_error_std_string(parse_error).c_str()); GRPC_ERROR_UNREF(parse_error); return; } @@ -1890,10 +1666,11 @@ bool XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log( GPR_INFO, - "[xds_client %p] LRS response received, %" PRIuPTR + "[xds_client %p] xds server %s: LRS response received, %" PRIuPTR " cluster names, send_all_clusters=%d, load_report_interval=%" PRId64 "ms", - xds_client(), new_cluster_names.size(), send_all_clusters, + xds_client(), chand()->server_.server_uri.c_str(), + new_cluster_names.size(), send_all_clusters, new_load_reporting_interval); size_t i = 0; for (const auto& name : new_cluster_names) { @@ -1907,9 +1684,10 @@ bool XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() { GRPC_XDS_MIN_CLIENT_LOAD_REPORTING_INTERVAL_MS; if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, - "[xds_client %p] Increased load_report_interval to minimum " - "value %dms", - xds_client(), GRPC_XDS_MIN_CLIENT_LOAD_REPORTING_INTERVAL_MS); + "[xds_client %p] xds server %s: increased load_report_interval " + "to minimum value %dms", + xds_client(), chand()->server_.server_uri.c_str(), + GRPC_XDS_MIN_CLIENT_LOAD_REPORTING_INTERVAL_MS); } } // Ignore identical update. @@ -1917,10 +1695,11 @@ bool XdsClient::ChannelState::LrsCallState::OnResponseReceivedLocked() { cluster_names_ == new_cluster_names && load_reporting_interval_ == new_load_reporting_interval) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] Incoming LRS response identical to current, " - "ignoring.", - xds_client()); + gpr_log( + GPR_INFO, + "[xds_client %p] xds server %s: incoming LRS response identical " + "to current, ignoring.", + xds_client(), chand()->server_.server_uri.c_str()); } return; } @@ -1966,9 +1745,11 @@ void XdsClient::ChannelState::LrsCallState::OnStatusReceivedLocked( 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] 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_, + "[xds_client %p] xds server %s: LRS call status received " + "(chand=%p, calld=%p, call=%p): " + "status=%d, details='%s', error='%s'", + xds_client(), chand()->server_.server_uri.c_str(), chand(), this, + call_, status_code_, status_details, grpc_error_std_string(error).c_str()); gpr_free(status_details); } @@ -2024,7 +1805,7 @@ XdsClient::XdsClient(std::unique_ptr<XdsBootstrap> bootstrap, certificate_provider_store_(MakeOrphanable<CertificateProviderStore>( bootstrap_->certificate_providers())), api_(this, &grpc_xds_client_trace, bootstrap_->node(), - &bootstrap_->certificate_providers()) { + &bootstrap_->certificate_providers(), &symtab_) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, "[xds_client %p] creating xds client", this); } @@ -2055,24 +1836,9 @@ void XdsClient::Orphan() { { MutexLock lock(&mu_); shutting_down_ = true; - // We do not clear cluster_map_ and endpoint_map_ if the xds client was - // created by the XdsResolver because the maps contain refs for watchers - // which in turn hold refs to the loadbalancing policies. At this point, it - // is possible for ADS calls to be in progress. Unreffing the loadbalancing - // policies before those calls are done would lead to issues such as - // https://github.com/grpc/grpc/issues/20928. - for (auto& a : authority_state_map_) { - a.second.channel_state.reset(); - if (!a.second.listener_map.empty()) { - a.second.cluster_map.clear(); - a.second.endpoint_map.clear(); - } - } - // We clear these invalid resource watchers as cancel never came. - invalid_listener_watchers_.clear(); - invalid_route_config_watchers_.clear(); - invalid_cluster_watchers_.clear(); - invalid_endpoint_watchers_.clear(); + // Clear cache and any remaining watchers that may not have been cancelled. + authority_state_map_.clear(); + invalid_watchers_.clear(); } } @@ -2089,19 +1855,17 @@ RefCountedPtr<XdsClient::ChannelState> XdsClient::GetOrCreateChannelStateLocked( return channel_state; } -void XdsClient::WatchListenerData( - y_absl::string_view listener_name, - RefCountedPtr<ListenerWatcherInterface> watcher) { - TString listener_name_str = TString(listener_name); - ListenerWatcherInterface* w = watcher.get(); - auto resource = XdsApi::ParseResourceName(listener_name, XdsApi::IsLds); - if (!resource.ok()) { +void XdsClient::WatchResource(const XdsResourceType* type, + y_absl::string_view name, + RefCountedPtr<ResourceWatcherInterface> watcher) { + ResourceWatcherInterface* w = watcher.get(); + // Lambda for handling failure cases. + auto fail = [&](grpc_error_handle error) mutable { { MutexLock lock(&mu_); - invalid_listener_watchers_[w] = watcher; + MaybeRegisterResourceTypeLocked(type); + invalid_watchers_[w] = watcher; } - grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrFormat( - "Unable to parse resource name for listener %s", listener_name)); work_serializer_.Run( // TODO(yashykt): When we move to C++14, capture watcher using // std::move() @@ -2109,107 +1873,52 @@ void XdsClient::WatchListenerData( watcher->OnError(error); }, DEBUG_LOCATION); + }; + auto resource_name = ParseXdsResourceName(name, type); + if (!resource_name.ok()) { + fail(GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrFormat( + "Unable to parse resource name for listener %s", name))); return; } - { - MutexLock lock(&mu_); - AuthorityState& authority_state = authority_state_map_[resource->authority]; - ListenerState& listener_state = authority_state.listener_map[resource->id]; - listener_state.watchers[w] = watcher; - // If we've already received an LDS update, notify the new watcher - // immediately. - if (listener_state.update.has_value()) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] returning cached listener data for %s", this, - listener_name_str.c_str()); - } - auto& value = listener_state.update.value(); - work_serializer_.Schedule( - // TODO(yashykt): When we move to C++14, capture watcher using - // std::move() - [watcher, value]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_) { - watcher->OnListenerChanged(value); - }, - DEBUG_LOCATION); + // Find server to use. + const XdsBootstrap::XdsServer* xds_server = nullptr; + y_absl::string_view authority_name = resource_name->authority; + if (y_absl::ConsumePrefix(&authority_name, "xdstp:")) { + auto* authority = bootstrap_->LookupAuthority(TString(authority_name)); + if (authority == nullptr) { + fail(GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("authority \"", authority_name, + "\" not present in bootstrap config"))); + return; } - // If the authority doesn't yet have a channel, set it, creating it if - // needed. - if (authority_state.channel_state == nullptr) { - authority_state.channel_state = - GetOrCreateChannelStateLocked(bootstrap_->server()); + if (!authority->xds_servers.empty()) { + xds_server = &authority->xds_servers[0]; } - authority_state.channel_state->SubscribeLocked(XdsApi::kLdsTypeUrl, - *resource); - } - work_serializer_.DrainQueue(); -} - -void XdsClient::CancelListenerDataWatch(y_absl::string_view listener_name, - ListenerWatcherInterface* watcher, - bool delay_unsubscription) { - MutexLock lock(&mu_); - if (shutting_down_) return; - auto resource = XdsApi::ParseResourceName(listener_name, XdsApi::IsLds); - if (!resource.ok()) return; - auto& authority_state = authority_state_map_[resource->authority]; - ListenerState& listener_state = authority_state.listener_map[resource->id]; - auto it = listener_state.watchers.find(watcher); - if (it == listener_state.watchers.end()) { - invalid_listener_watchers_.erase(watcher); - return; - } - listener_state.watchers.erase(it); - if (!listener_state.watchers.empty()) return; - authority_state.listener_map.erase(resource->id); - xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked( - XdsApi::kLdsTypeUrl, *resource, delay_unsubscription); - if (!authority_state.HasSubscribedResources()) { - authority_state.channel_state.reset(); - } -} - -void XdsClient::WatchRouteConfigData( - y_absl::string_view route_config_name, - RefCountedPtr<RouteConfigWatcherInterface> watcher) { - TString route_config_name_str = TString(route_config_name); - RouteConfigWatcherInterface* w = watcher.get(); - auto resource = XdsApi::ParseResourceName(route_config_name, XdsApi::IsRds); - if (!resource.ok()) { - { - MutexLock lock(&mu_); - invalid_route_config_watchers_[w] = watcher; - } - grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrFormat("Unable to parse resource name for route config %s", - route_config_name)); - work_serializer_.Run( - // TODO(yashykt): When we move to C++14, capture watcher using - // std::move() - [watcher, error]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) { - watcher->OnError(error); - }, - DEBUG_LOCATION); - return; } + if (xds_server == nullptr) xds_server = &bootstrap_->server(); { MutexLock lock(&mu_); - auto& authority_state = authority_state_map_[resource->authority]; - RouteConfigState& route_config_state = - authority_state.route_config_map[resource->id]; - route_config_state.watchers[w] = watcher; - // If we've already received an RDS update, notify the new watcher - // immediately. - if (route_config_state.update.has_value()) { + MaybeRegisterResourceTypeLocked(type); + // TODO(donnadionne): If we get a request for an authority that is not + // configured in the bootstrap file, reject it. + AuthorityState& authority_state = + authority_state_map_[resource_name->authority]; + ResourceState& resource_state = + authority_state.resource_map[type][resource_name->key]; + resource_state.watchers[w] = watcher; + // If we already have a cached value for the resource, notify the new + // watcher immediately. + if (resource_state.resource != nullptr) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { gpr_log(GPR_INFO, - "[xds_client %p] returning cached route config data for %s", - this, route_config_name_str.c_str()); + "[xds_client %p] returning cached listener data for %s", this, + TString(name).c_str()); } - auto& value = route_config_state.update.value(); + auto* value = type->CopyResource(resource_state.resource.get()).release(); work_serializer_.Schedule( - [watcher, value]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_) { - watcher->OnRouteConfigChanged(value); + [watcher, value]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) { + watcher->OnGenericResourceChanged(value); + delete value; }, DEBUG_LOCATION); } @@ -2217,188 +1926,113 @@ void XdsClient::WatchRouteConfigData( // needed. if (authority_state.channel_state == nullptr) { authority_state.channel_state = - GetOrCreateChannelStateLocked(bootstrap_->server()); + GetOrCreateChannelStateLocked(*xds_server); } - authority_state.channel_state->SubscribeLocked(XdsApi::kRdsTypeUrl, - *resource); + authority_state.channel_state->SubscribeLocked(type, *resource_name); } work_serializer_.DrainQueue(); } -void XdsClient::CancelRouteConfigDataWatch(y_absl::string_view route_config_name, - RouteConfigWatcherInterface* watcher, - bool delay_unsubscription) { +void XdsClient::CancelResourceWatch(const XdsResourceType* type, + y_absl::string_view name, + ResourceWatcherInterface* watcher, + bool delay_unsubscription) { + auto resource_name = ParseXdsResourceName(name, type); MutexLock lock(&mu_); - if (shutting_down_) return; - auto resource = XdsApi::ParseResourceName(route_config_name, XdsApi::IsRds); - if (!resource.ok()) return; - auto& authority_state = authority_state_map_[resource->authority]; - RouteConfigState& route_config_state = - authority_state.route_config_map[resource->id]; - auto it = route_config_state.watchers.find(watcher); - if (it == route_config_state.watchers.end()) { - invalid_route_config_watchers_.erase(watcher); - return; - } - route_config_state.watchers.erase(it); - if (!route_config_state.watchers.empty()) return; - authority_state.route_config_map.erase(resource->id); - xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked( - XdsApi::kRdsTypeUrl, *resource, delay_unsubscription); - if (!authority_state.HasSubscribedResources()) { - authority_state.channel_state.reset(); - } -} - -void XdsClient::WatchClusterData( - y_absl::string_view cluster_name, - RefCountedPtr<ClusterWatcherInterface> watcher) { - TString cluster_name_str = TString(cluster_name); - ClusterWatcherInterface* w = watcher.get(); - auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds); - if (!resource.ok()) { - { - MutexLock lock(&mu_); - invalid_cluster_watchers_[w] = watcher; - } - grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrFormat( - "Unable to parse resource name for cluster %s", cluster_name)); - work_serializer_.Run([watcher, error]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED( - work_serializer_) { watcher->OnError(error); }, - DEBUG_LOCATION); + if (!resource_name.ok()) { + invalid_watchers_.erase(watcher); return; } - { - MutexLock lock(&mu_); - auto& authority_state = authority_state_map_[resource->authority]; - ClusterState& cluster_state = authority_state.cluster_map[resource->id]; - cluster_state.watchers[w] = watcher; - // If we've already received a CDS update, notify the new watcher - // immediately. - if (cluster_state.update.has_value()) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] returning cached cluster data for %s", this, - cluster_name_str.c_str()); - } - auto& value = cluster_state.update.value(); - work_serializer_.Schedule( - // TODO(yashykt): When we move to C++14, capture watcher using - // std::move() - [watcher, value]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_) { - watcher->OnClusterChanged(value); - }, - DEBUG_LOCATION); - } - // If the authority doesn't yet have a channel, set it, creating it if - // needed. - if (authority_state.channel_state == nullptr) { - authority_state.channel_state = - GetOrCreateChannelStateLocked(bootstrap_->server()); - } - authority_state.channel_state->SubscribeLocked(XdsApi::kCdsTypeUrl, - *resource); - } - work_serializer_.DrainQueue(); -} - -void XdsClient::CancelClusterDataWatch(y_absl::string_view cluster_name, - ClusterWatcherInterface* watcher, - bool delay_unsubscription) { - MutexLock lock(&mu_); if (shutting_down_) return; - auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds); - if (!resource.ok()) return; - auto& authority_state = authority_state_map_[resource->authority]; - ClusterState& cluster_state = authority_state.cluster_map[resource->id]; - auto it = cluster_state.watchers.find(watcher); - if (it == cluster_state.watchers.end()) { - invalid_cluster_watchers_.erase(watcher); - return; - } - cluster_state.watchers.erase(it); - if (!cluster_state.watchers.empty()) return; - authority_state.cluster_map.erase(resource->id); - xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked( - XdsApi::kCdsTypeUrl, *resource, delay_unsubscription); - if (!authority_state.HasSubscribedResources()) { - authority_state.channel_state.reset(); - } -} - -void XdsClient::WatchEndpointData( - y_absl::string_view eds_service_name, - RefCountedPtr<EndpointWatcherInterface> watcher) { - TString eds_service_name_str = TString(eds_service_name); - EndpointWatcherInterface* w = watcher.get(); - auto resource = XdsApi::ParseResourceName(eds_service_name, XdsApi::IsEds); - if (!resource.ok()) { - { - MutexLock lock(&mu_); - invalid_endpoint_watchers_[w] = watcher; - } - grpc_error_handle error = GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrFormat("Unable to parse resource name for endpoint service %s", - eds_service_name)); - work_serializer_.Run([watcher, error]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED( - work_serializer_) { watcher->OnError(error); }, - DEBUG_LOCATION); - return; - } - { - MutexLock lock(&mu_); - auto& authority_state = authority_state_map_[resource->authority]; - EndpointState& endpoint_state = authority_state.endpoint_map[resource->id]; - endpoint_state.watchers[w] = watcher; - // If we've already received an EDS update, notify the new watcher - // immediately. - if (endpoint_state.update.has_value()) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_client_trace)) { - gpr_log(GPR_INFO, - "[xds_client %p] returning cached endpoint data for %s", this, - eds_service_name_str.c_str()); + // Find authority. + auto authority_it = authority_state_map_.find(resource_name->authority); + if (authority_it == authority_state_map_.end()) return; + AuthorityState& authority_state = authority_it->second; + // Find type map. + auto type_it = authority_state.resource_map.find(type); + if (type_it == authority_state.resource_map.end()) return; + auto& type_map = type_it->second; + // Find resource key. + auto resource_it = type_map.find(resource_name->key); + if (resource_it == type_map.end()) return; + ResourceState& resource_state = resource_it->second; + // Remove watcher. + resource_state.watchers.erase(watcher); + // Clean up empty map entries, if any. + if (resource_state.watchers.empty()) { + authority_state.channel_state->UnsubscribeLocked(type, *resource_name, + delay_unsubscription); + type_map.erase(resource_it); + if (type_map.empty()) { + authority_state.resource_map.erase(type_it); + if (authority_state.resource_map.empty()) { + authority_state.channel_state.reset(); } - auto& value = endpoint_state.update.value(); - work_serializer_.Schedule( - [watcher, value]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_) { - watcher->OnEndpointChanged(value); - }, - DEBUG_LOCATION); - } - // If the authority doesn't yet have a channel, set it, creating it if - // needed. - if (authority_state.channel_state == nullptr) { - authority_state.channel_state = - GetOrCreateChannelStateLocked(bootstrap_->server()); } - authority_state.channel_state->SubscribeLocked(XdsApi::kEdsTypeUrl, - *resource); } - work_serializer_.DrainQueue(); } -void XdsClient::CancelEndpointDataWatch(y_absl::string_view eds_service_name, - EndpointWatcherInterface* watcher, - bool delay_unsubscription) { - MutexLock lock(&mu_); - if (shutting_down_) return; - auto resource = XdsApi::ParseResourceName(eds_service_name, XdsApi::IsEds); - if (!resource.ok()) return; - auto& authority_state = authority_state_map_[resource->authority]; - EndpointState& endpoint_state = authority_state.endpoint_map[resource->id]; - auto it = endpoint_state.watchers.find(watcher); - if (it == endpoint_state.watchers.end()) { - invalid_endpoint_watchers_.erase(watcher); +void XdsClient::MaybeRegisterResourceTypeLocked( + const XdsResourceType* resource_type) { + auto it = resource_types_.find(resource_type->type_url()); + if (it != resource_types_.end()) { + GPR_ASSERT(it->second == resource_type); return; } - endpoint_state.watchers.erase(it); - if (!endpoint_state.watchers.empty()) return; - authority_state.endpoint_map.erase(resource->id); - xds_server_channel_map_[bootstrap_->server()]->UnsubscribeLocked( - XdsApi::kEdsTypeUrl, *resource, delay_unsubscription); - if (!authority_state.HasSubscribedResources()) { - authority_state.channel_state.reset(); - } + resource_types_.emplace(resource_type->type_url(), resource_type); + v2_resource_types_.emplace(resource_type->v2_type_url(), resource_type); + resource_type->InitUpbSymtab(symtab_.ptr()); +} + +const XdsResourceType* XdsClient::GetResourceTypeLocked( + y_absl::string_view resource_type) { + auto it = resource_types_.find(resource_type); + if (it != resource_types_.end()) return it->second; + auto it2 = v2_resource_types_.find(resource_type); + if (it2 != v2_resource_types_.end()) return it2->second; + return nullptr; +} + +y_absl::StatusOr<XdsClient::XdsResourceName> XdsClient::ParseXdsResourceName( + y_absl::string_view name, const XdsResourceType* type) { + // Old-style names use the empty string for authority. + // authority is prefixed with "old:" to indicate that it's an old-style name. + if (!y_absl::StartsWith(name, "xdstp:")) { + return XdsResourceName{"old:", {TString(name), {}}}; + } + // New style name. Parse URI. + auto uri = URI::Parse(name); + if (!uri.ok()) return uri.status(); + // Split the resource type off of the path to get the id. + std::pair<y_absl::string_view, y_absl::string_view> path_parts = y_absl::StrSplit( + y_absl::StripPrefix(uri->path(), "/"), y_absl::MaxSplits('/', 1)); + if (!type->IsType(path_parts.first, nullptr)) { + return y_absl::InvalidArgumentError( + "xdstp URI path must indicate valid xDS resource type"); + } + // Canonicalize order of query params. + std::vector<URI::QueryParam> query_params; + for (const auto& p : uri->query_parameter_map()) { + query_params.emplace_back( + URI::QueryParam{TString(p.first), TString(p.second)}); + } + return XdsResourceName{ + y_absl::StrCat("xdstp:", uri->authority()), + {TString(path_parts.second), std::move(query_params)}}; +} + +TString XdsClient::ConstructFullXdsResourceName( + y_absl::string_view authority, y_absl::string_view resource_type, + const XdsResourceKey& key) { + if (y_absl::ConsumePrefix(&authority, "xdstp:")) { + auto uri = URI::Create("xdstp", TString(authority), + y_absl::StrCat("/", resource_type, "/", key.id), + key.query_params, /*fragment=*/""); + GPR_ASSERT(uri.ok()); + return uri->ToString(); + } + // Old-style name. + return key.id; } RefCountedPtr<XdsClusterDropStats> XdsClient::AddClusterDropStats( @@ -2431,9 +2065,10 @@ RefCountedPtr<XdsClusterDropStats> XdsClient::AddClusterDropStats( it->first.second /*eds_service_name*/); load_report_state.drop_stats = cluster_drop_stats.get(); } - auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds); - GPR_ASSERT(resource.ok()); - auto a = authority_state_map_.find(resource->authority); + auto resource_name = + ParseXdsResourceName(cluster_name, XdsClusterResourceType::Get()); + GPR_ASSERT(resource_name.ok()); + auto a = authority_state_map_.find(resource_name->authority); if (a != authority_state_map_.end()) { a->second.channel_state->MaybeStartLrsCall(); } @@ -2493,9 +2128,10 @@ RefCountedPtr<XdsClusterLocalityStats> XdsClient::AddClusterLocalityStats( std::move(locality)); locality_state.locality_stats = cluster_locality_stats.get(); } - auto resource = XdsApi::ParseResourceName(cluster_name, XdsApi::IsCds); - GPR_ASSERT(resource.ok()); - auto a = authority_state_map_.find(resource->authority); + auto resource_name = + ParseXdsResourceName(cluster_name, XdsClusterResourceType::Get()); + GPR_ASSERT(resource_name.ok()); + auto a = authority_state_map_.find(resource_name->authority); if (a != authority_state_map_.end()) { a->second.channel_state->MaybeStartLrsCall(); } @@ -2534,56 +2170,25 @@ void XdsClient::ResetBackoff() { } void XdsClient::NotifyOnErrorLocked(grpc_error_handle error) { - std::set<RefCountedPtr<ListenerWatcherInterface>> listener_watchers; - std::set<RefCountedPtr<RouteConfigWatcherInterface>> route_config_watchers; - std::set<RefCountedPtr<ClusterWatcherInterface>> cluster_watchers; - std::set<RefCountedPtr<EndpointWatcherInterface>> endpoint_watchers; - for (const auto& a : authority_state_map_) { - for (const auto& p : a.second.listener_map) { - const ListenerState& listener_state = p.second; - for (const auto& q : listener_state.watchers) { - listener_watchers.insert(q.second); - } - } - for (const auto& p : a.second.route_config_map) { - const RouteConfigState& route_config_state = p.second; - for (const auto& q : route_config_state.watchers) { - route_config_watchers.insert(q.second); - } - } - for (const auto& p : a.second.cluster_map) { - const ClusterState& cluster_state = p.second; - for (const auto& q : cluster_state.watchers) { - cluster_watchers.insert(q.second); - } - } - for (const auto& p : a.second.endpoint_map) { - const EndpointState& endpoint_state = p.second; - for (const auto& q : endpoint_state.watchers) { - endpoint_watchers.insert(q.second); + std::set<RefCountedPtr<ResourceWatcherInterface>> watchers; + for (const auto& a : authority_state_map_) { // authority + for (const auto& t : a.second.resource_map) { // type + for (const auto& r : t.second) { // resource id + for (const auto& w : r.second.watchers) { // watchers + watchers.insert(w.second); + } } } } work_serializer_.Schedule( - // TODO(yashykt): When we move to C++14, capture *_watchers using + // TODO(yashykt): When we move to C++14, capture watchers using // std::move() - [listener_watchers, route_config_watchers, cluster_watchers, - endpoint_watchers, error]() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_) { - for (const auto& watcher : listener_watchers) { - watcher->OnError(GRPC_ERROR_REF(error)); - } - for (const auto& watcher : route_config_watchers) { - watcher->OnError(GRPC_ERROR_REF(error)); - } - for (const auto& watcher : cluster_watchers) { - watcher->OnError(GRPC_ERROR_REF(error)); - } - for (const auto& watcher : endpoint_watchers) { - watcher->OnError(GRPC_ERROR_REF(error)); - } - GRPC_ERROR_UNREF(error); - }, + [watchers, error]() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(work_serializer_) { + for (const auto& watcher : watchers) { + watcher->OnError(GRPC_ERROR_REF(error)); + } + GRPC_ERROR_UNREF(error); + }, DEBUG_LOCATION); } @@ -2671,35 +2276,18 @@ XdsApi::ClusterLoadReportMap XdsClient::BuildLoadReportSnapshotLocked( TString XdsClient::DumpClientConfigBinary() { MutexLock lock(&mu_); XdsApi::ResourceTypeMetadataMap resource_type_metadata_map; - auto& lds_map = resource_type_metadata_map[XdsApi::kLdsTypeUrl]; - auto& rds_map = resource_type_metadata_map[XdsApi::kRdsTypeUrl]; - auto& cds_map = resource_type_metadata_map[XdsApi::kCdsTypeUrl]; - auto& eds_map = resource_type_metadata_map[XdsApi::kEdsTypeUrl]; - for (auto& a : authority_state_map_) { + for (const auto& a : authority_state_map_) { // authority const TString& authority = a.first; - // Collect resource metadata from listeners - for (auto& p : a.second.listener_map) { - const TString& listener_name = p.first; - lds_map[XdsApi::ConstructFullResourceName( - authority, XdsApi::kLdsTypeUrl, listener_name)] = &p.second.meta; - } - // Collect resource metadata from route configs - for (auto& p : a.second.route_config_map) { - const TString& route_config_name = p.first; - rds_map[XdsApi::ConstructFullResourceName( - authority, XdsApi::kRdsTypeUrl, route_config_name)] = &p.second.meta; - } - // Collect resource metadata from clusters - for (auto& p : a.second.cluster_map) { - const TString& cluster_name = p.first; - cds_map[XdsApi::ConstructFullResourceName(authority, XdsApi::kCdsTypeUrl, - cluster_name)] = &p.second.meta; - } - // Collect resource metadata from endpoints - for (auto& p : a.second.endpoint_map) { - const TString& endpoint_name = p.first; - eds_map[XdsApi::ConstructFullResourceName( - authority, XdsApi::kEdsTypeUrl, endpoint_name)] = &p.second.meta; + for (const auto& t : a.second.resource_map) { // type + const XdsResourceType* type = t.first; + auto& resource_metadata_map = + resource_type_metadata_map[type->type_url()]; + for (const auto& r : t.second) { // resource id + const XdsResourceKey& resource_key = r.first; + const ResourceState& resource_state = r.second; + resource_metadata_map[ConstructFullXdsResourceName( + authority, type->type_url(), resource_key)] = &resource_state.meta; + } } } // Assemble config dump messages @@ -2713,6 +2301,7 @@ TString XdsClient::DumpClientConfigBinary() { void XdsClientGlobalInit() { g_mu = new Mutex; XdsHttpFilterRegistry::Init(); + XdsChannelCredsRegistry::Init(); } // TODO(roth): Find a better way to clear the fallback config that does @@ -2722,6 +2311,7 @@ void XdsClientGlobalShutdown() Y_ABSL_NO_THREAD_SAFETY_ANALYSIS { g_fallback_bootstrap_config = nullptr; delete g_mu; g_mu = nullptr; + XdsChannelCredsRegistry::Shutdown(); XdsHttpFilterRegistry::Shutdown(); } diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_client.h b/contrib/libs/grpc/src/core/ext/xds/xds_client.h index eb0538f956..507b962dc6 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_client.h +++ b/contrib/libs/grpc/src/core/ext/xds/xds_client.h @@ -28,6 +28,7 @@ #include "src/core/ext/xds/xds_api.h" #include "src/core/ext/xds/xds_bootstrap.h" #include "src/core/ext/xds/xds_client_stats.h" +#include "src/core/ext/xds/xds_resource_type.h" #include "src/core/lib/channel/channelz.h" #include "src/core/lib/gprpp/dual_ref_counted.h" #include "src/core/lib/gprpp/memory.h" @@ -35,6 +36,8 @@ #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/gprpp/sync.h" +#include "src/core/lib/iomgr/work_serializer.h" +#include "src/core/lib/uri/uri_parser.h" namespace grpc_core { @@ -43,44 +46,14 @@ extern TraceFlag grpc_xds_client_refcount_trace; class XdsClient : public DualRefCounted<XdsClient> { public: - // Listener data watcher interface. Implemented by callers. - class ListenerWatcherInterface : public RefCounted<ListenerWatcherInterface> { + // Resource watcher interface. Implemented by callers. + // Note: Most callers will not use this API directly but rather via a + // resource-type-specific wrapper API provided by the relevant + // XdsResourceType implementation. + class ResourceWatcherInterface : public RefCounted<ResourceWatcherInterface> { public: - virtual void OnListenerChanged(XdsApi::LdsUpdate listener) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - virtual void OnError(grpc_error_handle error) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - virtual void OnResourceDoesNotExist() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - }; - - // RouteConfiguration data watcher interface. Implemented by callers. - class RouteConfigWatcherInterface - : public RefCounted<RouteConfigWatcherInterface> { - public: - virtual void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - virtual void OnError(grpc_error_handle error) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - virtual void OnResourceDoesNotExist() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - }; - - // Cluster data watcher interface. Implemented by callers. - class ClusterWatcherInterface : public RefCounted<ClusterWatcherInterface> { - public: - virtual void OnClusterChanged(XdsApi::CdsUpdate cluster_data) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - virtual void OnError(grpc_error_handle error) - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - virtual void OnResourceDoesNotExist() - Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; - }; - - // Endpoint data watcher interface. Implemented by callers. - class EndpointWatcherInterface : public RefCounted<EndpointWatcherInterface> { - public: - virtual void OnEndpointChanged(XdsApi::EdsUpdate update) + virtual void OnGenericResourceChanged( + const XdsResourceType::ResourceData* resource) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; virtual void OnError(grpc_error_handle error) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&work_serializer_) = 0; @@ -113,57 +86,31 @@ class XdsClient : public DualRefCounted<XdsClient> { void Orphan() override; - // Start and cancel listener data watch for a listener. - // The XdsClient takes ownership of the watcher, but the caller may - // keep a raw pointer to the watcher, which may be used only for - // cancellation. (Because the caller does not own the watcher, the - // pointer must not be used for any other purpose.) - // If the caller is going to start a new watch after cancelling the - // old one, it should set delay_unsubscription to true. - void WatchListenerData(y_absl::string_view listener_name, - RefCountedPtr<ListenerWatcherInterface> watcher); - void CancelListenerDataWatch(y_absl::string_view listener_name, - ListenerWatcherInterface* watcher, - bool delay_unsubscription = false); - - // Start and cancel route config data watch for a listener. - // The XdsClient takes ownership of the watcher, but the caller may - // keep a raw pointer to the watcher, which may be used only for - // cancellation. (Because the caller does not own the watcher, the - // pointer must not be used for any other purpose.) - // If the caller is going to start a new watch after cancelling the - // old one, it should set delay_unsubscription to true. - void WatchRouteConfigData(y_absl::string_view route_config_name, - RefCountedPtr<RouteConfigWatcherInterface> watcher); - void CancelRouteConfigDataWatch(y_absl::string_view route_config_name, - RouteConfigWatcherInterface* watcher, - bool delay_unsubscription = false); - - // Start and cancel cluster data watch for a cluster. - // The XdsClient takes ownership of the watcher, but the caller may - // keep a raw pointer to the watcher, which may be used only for - // cancellation. (Because the caller does not own the watcher, the - // pointer must not be used for any other purpose.) - // If the caller is going to start a new watch after cancelling the - // old one, it should set delay_unsubscription to true. - void WatchClusterData(y_absl::string_view cluster_name, - RefCountedPtr<ClusterWatcherInterface> watcher); - void CancelClusterDataWatch(y_absl::string_view cluster_name, - ClusterWatcherInterface* watcher, - bool delay_unsubscription = false); - - // Start and cancel endpoint data watch for a cluster. + // Start and cancel watch for a resource. + // // The XdsClient takes ownership of the watcher, but the caller may // keep a raw pointer to the watcher, which may be used only for // cancellation. (Because the caller does not own the watcher, the // pointer must not be used for any other purpose.) // If the caller is going to start a new watch after cancelling the // old one, it should set delay_unsubscription to true. - void WatchEndpointData(y_absl::string_view eds_service_name, - RefCountedPtr<EndpointWatcherInterface> watcher); - void CancelEndpointDataWatch(y_absl::string_view eds_service_name, - EndpointWatcherInterface* watcher, - bool delay_unsubscription = false); + // + // The resource type object must be a global singleton, since the first + // time the XdsClient sees a particular resource type object, it will + // store the pointer to that object as the authoritative implementation for + // its type URLs. The resource type object must outlive the XdsClient object, + // and it is illegal to start a subsequent watch for the same type URLs using + // a different resource type object. + // + // Note: Most callers will not use this API directly but rather via a + // resource-type-specific wrapper API provided by the relevant + // XdsResourceType implementation. + void WatchResource(const XdsResourceType* type, y_absl::string_view name, + RefCountedPtr<ResourceWatcherInterface> watcher); + void CancelResourceWatch(const XdsResourceType* type, + y_absl::string_view listener_name, + ResourceWatcherInterface* watcher, + bool delay_unsubscription = false); // Adds and removes drop stats for cluster_name and eds_service_name. RefCountedPtr<XdsClusterDropStats> AddClusterDropStats( @@ -204,6 +151,22 @@ class XdsClient : public DualRefCounted<XdsClient> { const grpc_channel_args& args); private: + struct XdsResourceKey { + TString id; + std::vector<URI::QueryParam> query_params; + + bool operator<(const XdsResourceKey& other) const { + int c = id.compare(other.id); + if (c != 0) return c < 0; + return query_params < other.query_params; + } + }; + + struct XdsResourceName { + TString authority; + XdsResourceKey key; + }; + // Contains a channel to the xds server and all the data related to the // channel. Holds a ref to the xds client object. class ChannelState : public DualRefCounted<ChannelState> { @@ -234,11 +197,11 @@ class XdsClient : public DualRefCounted<XdsClient> { void StartConnectivityWatchLocked(); void CancelConnectivityWatchLocked(); - void SubscribeLocked(const TString& type_url, - const XdsApi::ResourceName& name) + void SubscribeLocked(const XdsResourceType* type, + const XdsResourceName& name) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); - void UnsubscribeLocked(const TString& type_url, - const XdsApi::ResourceName& name, + void UnsubscribeLocked(const XdsResourceType* type, + const XdsResourceName& name, bool delay_unsubscription) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&XdsClient::mu_); @@ -260,55 +223,22 @@ class XdsClient : public DualRefCounted<XdsClient> { OrphanablePtr<RetryableCall<LrsCallState>> lrs_calld_; // Stores the most recent accepted resource version for each resource type. - std::map<TString /*type*/, TString /*version*/> + std::map<const XdsResourceType*, TString /*version*/> resource_type_version_map_; }; - struct ListenerState { - std::map<ListenerWatcherInterface*, RefCountedPtr<ListenerWatcherInterface>> - watchers; - // The latest data seen from LDS. - y_absl::optional<XdsApi::LdsUpdate> update; - XdsApi::ResourceMetadata meta; - }; - - struct RouteConfigState { - std::map<RouteConfigWatcherInterface*, - RefCountedPtr<RouteConfigWatcherInterface>> - watchers; - // The latest data seen from RDS. - y_absl::optional<XdsApi::RdsUpdate> update; - XdsApi::ResourceMetadata meta; - }; - - struct ClusterState { - std::map<ClusterWatcherInterface*, RefCountedPtr<ClusterWatcherInterface>> - watchers; - // The latest data seen from CDS. - y_absl::optional<XdsApi::CdsUpdate> update; - XdsApi::ResourceMetadata meta; - }; - - struct EndpointState { - std::map<EndpointWatcherInterface*, RefCountedPtr<EndpointWatcherInterface>> + struct ResourceState { + std::map<ResourceWatcherInterface*, RefCountedPtr<ResourceWatcherInterface>> watchers; - // The latest data seen from EDS. - y_absl::optional<XdsApi::EdsUpdate> update; + // The latest data seen for the resource. + std::unique_ptr<XdsResourceType::ResourceData> resource; XdsApi::ResourceMetadata meta; }; struct AuthorityState { RefCountedPtr<ChannelState> channel_state; - std::map<TString /*listener_name*/, ListenerState> listener_map; - std::map<TString /*route_config_name*/, RouteConfigState> - route_config_map; - std::map<TString /*cluster_name*/, ClusterState> cluster_map; - std::map<TString /*eds_service_name*/, EndpointState> endpoint_map; - - bool HasSubscribedResources() { - return !listener_map.empty() || !route_config_map.empty() || - !cluster_map.empty() || !endpoint_map.empty(); - } + std::map<const XdsResourceType*, std::map<XdsResourceKey, ResourceState>> + resource_map; }; struct LoadReportState { @@ -331,6 +261,19 @@ class XdsClient : public DualRefCounted<XdsClient> { void NotifyOnErrorLocked(grpc_error_handle error) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + void MaybeRegisterResourceTypeLocked(const XdsResourceType* resource_type) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + + // Gets the type for resource_type, or null if the type is unknown. + const XdsResourceType* GetResourceTypeLocked(y_absl::string_view resource_type) + Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); + + static y_absl::StatusOr<XdsResourceName> ParseXdsResourceName( + y_absl::string_view name, const XdsResourceType* type); + static TString ConstructFullXdsResourceName( + y_absl::string_view authority, y_absl::string_view resource_type, + const XdsResourceKey& key); + XdsApi::ClusterLoadReportMap BuildLoadReportSnapshotLocked( bool send_all_clusters, const std::set<TString>& clusters) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); @@ -348,6 +291,13 @@ class XdsClient : public DualRefCounted<XdsClient> { Mutex mu_; + // Stores resource type objects seen by type URL. + std::map<y_absl::string_view /*resource_type*/, const XdsResourceType*> + resource_types_ Y_ABSL_GUARDED_BY(mu_); + std::map<y_absl::string_view /*v2_resource_type*/, const XdsResourceType*> + v2_resource_types_ Y_ABSL_GUARDED_BY(mu_); + upb::SymbolTable symtab_ Y_ABSL_GUARDED_BY(mu_); + // Map of existing xDS server channels. std::map<XdsBootstrap::XdsServer, ChannelState*> xds_server_channel_map_ Y_ABSL_GUARDED_BY(mu_); @@ -363,15 +313,8 @@ class XdsClient : public DualRefCounted<XdsClient> { // Stores started watchers whose resource name was not parsed successfully, // waiting to be cancelled or reset in Orphan(). - std::map<ListenerWatcherInterface*, RefCountedPtr<ListenerWatcherInterface>> - invalid_listener_watchers_ Y_ABSL_GUARDED_BY(mu_); - std::map<RouteConfigWatcherInterface*, - RefCountedPtr<RouteConfigWatcherInterface>> - invalid_route_config_watchers_ Y_ABSL_GUARDED_BY(mu_); - std::map<ClusterWatcherInterface*, RefCountedPtr<ClusterWatcherInterface>> - invalid_cluster_watchers_ Y_ABSL_GUARDED_BY(mu_); - std::map<EndpointWatcherInterface*, RefCountedPtr<EndpointWatcherInterface>> - invalid_endpoint_watchers_ Y_ABSL_GUARDED_BY(mu_); + std::map<ResourceWatcherInterface*, RefCountedPtr<ResourceWatcherInterface>> + invalid_watchers_ Y_ABSL_GUARDED_BY(mu_); bool shutting_down_ Y_ABSL_GUARDED_BY(mu_) = false; }; diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_cluster.cc b/contrib/libs/grpc/src/core/ext/xds/xds_cluster.cc new file mode 100644 index 0000000000..0ed98927a8 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_cluster.cc @@ -0,0 +1,451 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_cluster.h" + +#include "y_absl/container/inlined_vector.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_join.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/config_source.upb.h" +#include "envoy/config/endpoint/v3/endpoint.upb.h" +#include "envoy/config/endpoint/v3/endpoint_components.upb.h" +#include "envoy/extensions/clusters/aggregate/v3/cluster.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/wrappers.upb.h" + +#include <grpc/support/alloc.h> + +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/gprpp/host_port.h" + +namespace grpc_core { + +// +// XdsClusterResource +// + +TString XdsClusterResource::ToString() const { + y_absl::InlinedVector<TString, 8> contents; + switch (cluster_type) { + case EDS: + contents.push_back("cluster_type=EDS"); + if (!eds_service_name.empty()) { + contents.push_back( + y_absl::StrFormat("eds_service_name=%s", eds_service_name)); + } + break; + case LOGICAL_DNS: + contents.push_back("cluster_type=LOGICAL_DNS"); + contents.push_back(y_absl::StrFormat("dns_hostname=%s", dns_hostname)); + break; + case AGGREGATE: + contents.push_back("cluster_type=AGGREGATE"); + contents.push_back( + y_absl::StrFormat("prioritized_cluster_names=[%s]", + y_absl::StrJoin(prioritized_cluster_names, ", "))); + } + if (!common_tls_context.Empty()) { + contents.push_back(y_absl::StrFormat("common_tls_context=%s", + common_tls_context.ToString())); + } + if (lrs_load_reporting_server_name.has_value()) { + contents.push_back(y_absl::StrFormat("lrs_load_reporting_server_name=%s", + lrs_load_reporting_server_name.value())); + } + contents.push_back(y_absl::StrCat("lb_policy=", lb_policy)); + if (lb_policy == "RING_HASH") { + contents.push_back(y_absl::StrCat("min_ring_size=", min_ring_size)); + contents.push_back(y_absl::StrCat("max_ring_size=", max_ring_size)); + } + contents.push_back( + y_absl::StrFormat("max_concurrent_requests=%d", max_concurrent_requests)); + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsClusterResourceType +// + +namespace { + +grpc_error_handle UpstreamTlsContextParse( + const XdsEncodingContext& context, + const envoy_config_core_v3_TransportSocket* transport_socket, + CommonTlsContext* common_tls_context) { + // Record Upstream tls context + y_absl::string_view name = UpbStringToAbsl( + envoy_config_core_v3_TransportSocket_name(transport_socket)); + if (name != "envoy.transport_sockets.tls") { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Unrecognized transport socket: ", name)); + } + auto* typed_config = + envoy_config_core_v3_TransportSocket_typed_config(transport_socket); + if (typed_config != nullptr) { + const upb_strview encoded_upstream_tls_context = + google_protobuf_Any_value(typed_config); + auto* upstream_tls_context = + envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_parse( + encoded_upstream_tls_context.data, + encoded_upstream_tls_context.size, context.arena); + if (upstream_tls_context == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Can't decode upstream tls context."); + } + auto* common_tls_context_proto = + envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_common_tls_context( + upstream_tls_context); + if (common_tls_context_proto != nullptr) { + grpc_error_handle error = CommonTlsContext::Parse( + context, common_tls_context_proto, common_tls_context); + if (error != GRPC_ERROR_NONE) { + return grpc_error_add_child(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Error parsing UpstreamTlsContext"), + error); + } + } + } + if (common_tls_context->certificate_validation_context + .ca_certificate_provider_instance.instance_name.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "UpstreamTlsContext: TLS configuration provided but no " + "ca_certificate_provider_instance found."); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle CdsLogicalDnsParse( + const envoy_config_cluster_v3_Cluster* cluster, + XdsClusterResource* cds_update) { + const auto* load_assignment = + envoy_config_cluster_v3_Cluster_load_assignment(cluster); + if (load_assignment == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "load_assignment not present for LOGICAL_DNS cluster"); + } + size_t num_localities; + const auto* const* localities = + envoy_config_endpoint_v3_ClusterLoadAssignment_endpoints(load_assignment, + &num_localities); + if (num_localities != 1) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("load_assignment for LOGICAL_DNS cluster must have " + "exactly one locality, found ", + num_localities)); + } + size_t num_endpoints; + const auto* const* endpoints = + envoy_config_endpoint_v3_LocalityLbEndpoints_lb_endpoints(localities[0], + &num_endpoints); + if (num_endpoints != 1) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("locality for LOGICAL_DNS cluster must have " + "exactly one endpoint, found ", + num_endpoints)); + } + const auto* endpoint = + envoy_config_endpoint_v3_LbEndpoint_endpoint(endpoints[0]); + if (endpoint == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "LbEndpoint endpoint field not set"); + } + const auto* address = envoy_config_endpoint_v3_Endpoint_address(endpoint); + if (address == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Endpoint address field not set"); + } + const auto* socket_address = + envoy_config_core_v3_Address_socket_address(address); + if (socket_address == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Address socket_address field not set"); + } + if (envoy_config_core_v3_SocketAddress_resolver_name(socket_address).size != + 0) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "LOGICAL_DNS clusters must NOT have a custom resolver name set"); + } + y_absl::string_view address_str = UpbStringToAbsl( + envoy_config_core_v3_SocketAddress_address(socket_address)); + if (address_str.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "SocketAddress address field not set"); + } + if (!envoy_config_core_v3_SocketAddress_has_port_value(socket_address)) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "SocketAddress port_value field not set"); + } + cds_update->dns_hostname = JoinHostPort( + address_str, + envoy_config_core_v3_SocketAddress_port_value(socket_address)); + return GRPC_ERROR_NONE; +} + +// 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 +// default. +bool XdsAggregateAndLogicalDnsClusterEnabled() { + char* value = gpr_getenv( + "GRPC_XDS_EXPERIMENTAL_ENABLE_AGGREGATE_AND_LOGICAL_DNS_CLUSTER"); + bool parsed_value; + bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); + gpr_free(value); + return parse_succeeded && parsed_value; +} + +grpc_error_handle CdsResourceParse( + const XdsEncodingContext& context, + const envoy_config_cluster_v3_Cluster* cluster, bool /*is_v2*/, + XdsClusterResource* cds_update) { + std::vector<grpc_error_handle> errors; + // Check the cluster_discovery_type. + if (!envoy_config_cluster_v3_Cluster_has_type(cluster) && + !envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType not found.")); + } else if (envoy_config_cluster_v3_Cluster_type(cluster) == + envoy_config_cluster_v3_Cluster_EDS) { + cds_update->cluster_type = XdsClusterResource::ClusterType::EDS; + // Check the EDS config source. + const envoy_config_cluster_v3_Cluster_EdsClusterConfig* eds_cluster_config = + envoy_config_cluster_v3_Cluster_eds_cluster_config(cluster); + const envoy_config_core_v3_ConfigSource* eds_config = + envoy_config_cluster_v3_Cluster_EdsClusterConfig_eds_config( + eds_cluster_config); + if (!envoy_config_core_v3_ConfigSource_has_ads(eds_config)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("EDS ConfigSource is not ADS.")); + } + // Record EDS service_name (if any). + upb_strview service_name = + envoy_config_cluster_v3_Cluster_EdsClusterConfig_service_name( + eds_cluster_config); + if (service_name.size != 0) { + cds_update->eds_service_name = UpbStringToStdString(service_name); + } + } else if (!XdsAggregateAndLogicalDnsClusterEnabled()) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType is not valid.")); + } else if (envoy_config_cluster_v3_Cluster_type(cluster) == + envoy_config_cluster_v3_Cluster_LOGICAL_DNS) { + cds_update->cluster_type = XdsClusterResource::ClusterType::LOGICAL_DNS; + grpc_error_handle error = CdsLogicalDnsParse(cluster, cds_update); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } else { + if (!envoy_config_cluster_v3_Cluster_has_cluster_type(cluster)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType is not valid.")); + } else { + const envoy_config_cluster_v3_Cluster_CustomClusterType* + custom_cluster_type = + envoy_config_cluster_v3_Cluster_cluster_type(cluster); + upb_strview type_name = + envoy_config_cluster_v3_Cluster_CustomClusterType_name( + custom_cluster_type); + if (UpbStringToAbsl(type_name) != "envoy.clusters.aggregate") { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "DiscoveryType is not valid.")); + } else { + cds_update->cluster_type = XdsClusterResource::ClusterType::AGGREGATE; + // Retrieve aggregate clusters. + const google_protobuf_Any* typed_config = + envoy_config_cluster_v3_Cluster_CustomClusterType_typed_config( + custom_cluster_type); + const upb_strview aggregate_cluster_config_upb_strview = + google_protobuf_Any_value(typed_config); + const envoy_extensions_clusters_aggregate_v3_ClusterConfig* + aggregate_cluster_config = + envoy_extensions_clusters_aggregate_v3_ClusterConfig_parse( + aggregate_cluster_config_upb_strview.data, + aggregate_cluster_config_upb_strview.size, context.arena); + if (aggregate_cluster_config == nullptr) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Can't parse aggregate cluster.")); + } else { + size_t size; + const upb_strview* clusters = + envoy_extensions_clusters_aggregate_v3_ClusterConfig_clusters( + aggregate_cluster_config, &size); + for (size_t i = 0; i < size; ++i) { + const upb_strview cluster = clusters[i]; + cds_update->prioritized_cluster_names.emplace_back( + UpbStringToStdString(cluster)); + } + } + } + } + } + // Check the LB policy. + if (envoy_config_cluster_v3_Cluster_lb_policy(cluster) == + envoy_config_cluster_v3_Cluster_ROUND_ROBIN) { + cds_update->lb_policy = "ROUND_ROBIN"; + } else if (envoy_config_cluster_v3_Cluster_lb_policy(cluster) == + envoy_config_cluster_v3_Cluster_RING_HASH) { + cds_update->lb_policy = "RING_HASH"; + // Record ring hash lb config + auto* ring_hash_config = + envoy_config_cluster_v3_Cluster_ring_hash_lb_config(cluster); + if (ring_hash_config != nullptr) { + const google_protobuf_UInt64Value* max_ring_size = + envoy_config_cluster_v3_Cluster_RingHashLbConfig_maximum_ring_size( + ring_hash_config); + if (max_ring_size != nullptr) { + cds_update->max_ring_size = + google_protobuf_UInt64Value_value(max_ring_size); + if (cds_update->max_ring_size > 8388608 || + cds_update->max_ring_size == 0) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "max_ring_size is not in the range of 1 to 8388608.")); + } + } + const google_protobuf_UInt64Value* min_ring_size = + envoy_config_cluster_v3_Cluster_RingHashLbConfig_minimum_ring_size( + ring_hash_config); + if (min_ring_size != nullptr) { + cds_update->min_ring_size = + google_protobuf_UInt64Value_value(min_ring_size); + if (cds_update->min_ring_size > 8388608 || + cds_update->min_ring_size == 0) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "min_ring_size is not in the range of 1 to 8388608.")); + } + if (cds_update->min_ring_size > cds_update->max_ring_size) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "min_ring_size cannot be greater than max_ring_size.")); + } + } + if (envoy_config_cluster_v3_Cluster_RingHashLbConfig_hash_function( + ring_hash_config) != + envoy_config_cluster_v3_Cluster_RingHashLbConfig_XX_HASH) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "ring hash lb config has invalid hash function.")); + } + } + } else { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("LB policy is not supported.")); + } + auto* transport_socket = + envoy_config_cluster_v3_Cluster_transport_socket(cluster); + if (transport_socket != nullptr) { + grpc_error_handle error = UpstreamTlsContextParse( + context, transport_socket, &cds_update->common_tls_context); + if (error != GRPC_ERROR_NONE) { + errors.push_back( + grpc_error_add_child(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Error parsing security configuration"), + error)); + } + } + // Record LRS server name (if any). + const envoy_config_core_v3_ConfigSource* lrs_server = + envoy_config_cluster_v3_Cluster_lrs_server(cluster); + if (lrs_server != nullptr) { + if (!envoy_config_core_v3_ConfigSource_has_self(lrs_server)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + ": LRS ConfigSource is not self.")); + } + cds_update->lrs_load_reporting_server_name.emplace(""); + } + // The Cluster resource encodes the circuit breaking parameters in a list of + // Thresholds messages, where each message specifies the parameters for a + // particular RoutingPriority. we will look only at the first entry in the + // list for priority DEFAULT and default to 1024 if not found. + if (envoy_config_cluster_v3_Cluster_has_circuit_breakers(cluster)) { + const envoy_config_cluster_v3_CircuitBreakers* circuit_breakers = + envoy_config_cluster_v3_Cluster_circuit_breakers(cluster); + size_t num_thresholds; + const envoy_config_cluster_v3_CircuitBreakers_Thresholds* const* + thresholds = envoy_config_cluster_v3_CircuitBreakers_thresholds( + circuit_breakers, &num_thresholds); + for (size_t i = 0; i < num_thresholds; ++i) { + const auto* threshold = thresholds[i]; + if (envoy_config_cluster_v3_CircuitBreakers_Thresholds_priority( + threshold) == envoy_config_core_v3_DEFAULT) { + const google_protobuf_UInt32Value* max_requests = + envoy_config_cluster_v3_CircuitBreakers_Thresholds_max_requests( + threshold); + if (max_requests != nullptr) { + cds_update->max_concurrent_requests = + google_protobuf_UInt32Value_value(max_requests); + } + break; + } + } + } + return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing CDS resource", &errors); +} + +void MaybeLogCluster(const XdsEncodingContext& context, + const envoy_config_cluster_v3_Cluster* cluster) { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && + gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + const upb_msgdef* msg_type = + envoy_config_cluster_v3_Cluster_getmsgdef(context.symtab); + char buf[10240]; + upb_text_encode(cluster, msg_type, nullptr, 0, buf, sizeof(buf)); + gpr_log(GPR_DEBUG, "[xds_client %p] Cluster: %s", context.client, buf); + } +} + +} // namespace + +y_absl::StatusOr<XdsResourceType::DecodeResult> XdsClusterResourceType::Decode( + const XdsEncodingContext& context, y_absl::string_view serialized_resource, + bool is_v2) const { + // Parse serialized proto. + auto* resource = envoy_config_cluster_v3_Cluster_parse( + serialized_resource.data(), serialized_resource.size(), context.arena); + if (resource == nullptr) { + return y_absl::InvalidArgumentError("Can't parse Cluster resource."); + } + MaybeLogCluster(context, resource); + // Validate resource. + DecodeResult result; + result.name = + UpbStringToStdString(envoy_config_cluster_v3_Cluster_name(resource)); + auto cluster_data = y_absl::make_unique<ResourceDataSubclass>(); + grpc_error_handle error = + CdsResourceParse(context, resource, is_v2, &cluster_data->resource); + if (error != GRPC_ERROR_NONE) { + TString error_str = grpc_error_std_string(error); + GRPC_ERROR_UNREF(error); + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_ERROR, "[xds_client %p] invalid Cluster %s: %s", + context.client, result.name.c_str(), error_str.c_str()); + } + result.resource = y_absl::InvalidArgumentError(error_str); + } else { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_INFO, "[xds_client %p] parsed Cluster %s: %s", context.client, + result.name.c_str(), cluster_data->resource.ToString().c_str()); + } + result.resource = std::move(cluster_data); + } + return std::move(result); +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_cluster.h b/contrib/libs/grpc/src/core/ext/xds/xds_cluster.h new file mode 100644 index 0000000000..e65143cf6c --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_cluster.h @@ -0,0 +1,111 @@ +// +// 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_XDS_XDS_CLUSTER_H +#define GRPC_CORE_EXT_XDS_XDS_CLUSTER_H + +#include <grpc/support/port_platform.h> + +#include <util/generic/string.h> +#include <vector> + +#include "y_absl/types/optional.h" +#include "envoy/config/cluster/v3/cluster.upbdefs.h" +#include "envoy/extensions/clusters/aggregate/v3/cluster.upbdefs.h" +#include "envoy/extensions/transport_sockets/tls/v3/tls.upbdefs.h" + +#include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_common_types.h" +#include "src/core/ext/xds/xds_resource_type_impl.h" + +namespace grpc_core { + +struct XdsClusterResource { + enum ClusterType { EDS, LOGICAL_DNS, AGGREGATE }; + ClusterType cluster_type; + // For cluster type EDS. + // The name to use in the EDS request. + // If empty, the cluster name will be used. + TString eds_service_name; + // For cluster type LOGICAL_DNS. + // The hostname to lookup in DNS. + TString dns_hostname; + // For cluster type AGGREGATE. + // The prioritized list of cluster names. + std::vector<TString> prioritized_cluster_names; + + // Tls Context used by clients + CommonTlsContext common_tls_context; + + // The LRS server to use for load reporting. + // If not set, load reporting will be disabled. + // If set to the empty string, will use the same server we obtained the CDS + // data from. + y_absl::optional<TString> lrs_load_reporting_server_name; + + // The LB policy to use (e.g., "ROUND_ROBIN" or "RING_HASH"). + TString lb_policy; + // Used for RING_HASH LB policy only. + uint64_t min_ring_size = 1024; + uint64_t max_ring_size = 8388608; + // Maximum number of outstanding requests can be made to the upstream + // cluster. + uint32_t max_concurrent_requests = 1024; + + bool operator==(const XdsClusterResource& other) const { + return cluster_type == other.cluster_type && + eds_service_name == other.eds_service_name && + dns_hostname == other.dns_hostname && + prioritized_cluster_names == other.prioritized_cluster_names && + common_tls_context == other.common_tls_context && + lrs_load_reporting_server_name == + other.lrs_load_reporting_server_name && + lb_policy == other.lb_policy && + min_ring_size == other.min_ring_size && + max_ring_size == other.max_ring_size && + max_concurrent_requests == other.max_concurrent_requests; + } + + TString ToString() const; +}; + +class XdsClusterResourceType + : public XdsResourceTypeImpl<XdsClusterResourceType, XdsClusterResource> { + public: + y_absl::string_view type_url() const override { + return "envoy.config.cluster.v3.Cluster"; + } + y_absl::string_view v2_type_url() const override { + return "envoy.api.v2.Cluster"; + } + + y_absl::StatusOr<DecodeResult> Decode(const XdsEncodingContext& context, + y_absl::string_view serialized_resource, + bool is_v2) const override; + + bool AllResourcesRequiredInSotW() const override { return true; } + + void InitUpbSymtab(upb_symtab* symtab) const override { + envoy_config_cluster_v3_Cluster_getmsgdef(symtab); + envoy_extensions_clusters_aggregate_v3_ClusterConfig_getmsgdef(symtab); + envoy_extensions_transport_sockets_tls_v3_UpstreamTlsContext_getmsgdef( + symtab); + } +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_CLUSTER_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_common_types.cc b/contrib/libs/grpc/src/core/ext/xds/xds_common_types.cc new file mode 100644 index 0000000000..101d26adc5 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_common_types.cc @@ -0,0 +1,388 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_common_types.h" + +#include "y_absl/container/inlined_vector.h" +#include "y_absl/status/statusor.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_join.h" +#include "envoy/extensions/transport_sockets/tls/v3/common.upb.h" +#include "envoy/extensions/transport_sockets/tls/v3/tls.upb.h" +#include "envoy/type/matcher/v3/regex.upb.h" +#include "envoy/type/matcher/v3/string.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "xds/type/v3/typed_struct.upb.h" + +namespace grpc_core { + +// +// CommonTlsContext::CertificateValidationContext +// + +TString CommonTlsContext::CertificateValidationContext::ToString() const { + std::vector<TString> contents; + for (const auto& match : match_subject_alt_names) { + contents.push_back(match.ToString()); + } + return y_absl::StrFormat("{match_subject_alt_names=[%s]}", + y_absl::StrJoin(contents, ", ")); +} + +bool CommonTlsContext::CertificateValidationContext::Empty() const { + return match_subject_alt_names.empty(); +} + +// +// CommonTlsContext::CertificateProviderPluginInstance +// + +TString CommonTlsContext::CertificateProviderPluginInstance::ToString() + const { + y_absl::InlinedVector<TString, 2> contents; + if (!instance_name.empty()) { + contents.push_back(y_absl::StrFormat("instance_name=%s", instance_name)); + } + if (!certificate_name.empty()) { + contents.push_back( + y_absl::StrFormat("certificate_name=%s", certificate_name)); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +bool CommonTlsContext::CertificateProviderPluginInstance::Empty() const { + return instance_name.empty() && certificate_name.empty(); +} + +// +// CommonTlsContext +// + +TString CommonTlsContext::ToString() const { + y_absl::InlinedVector<TString, 2> contents; + if (!tls_certificate_provider_instance.Empty()) { + contents.push_back( + y_absl::StrFormat("tls_certificate_provider_instance=%s", + tls_certificate_provider_instance.ToString())); + } + if (!certificate_validation_context.Empty()) { + contents.push_back( + y_absl::StrFormat("certificate_validation_context=%s", + certificate_validation_context.ToString())); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +bool CommonTlsContext::Empty() const { + return tls_certificate_provider_instance.Empty() && + certificate_validation_context.Empty(); +} + +namespace { + +// CertificateProviderInstance is deprecated but we are still supporting it for +// backward compatibility reasons. Note that we still parse the data into the +// same CertificateProviderPluginInstance struct since the fields are the same. +// TODO(yashykt): Remove this once we stop supporting the old way of fetching +// certificate provider instances. +grpc_error_handle CertificateProviderInstanceParse( + const XdsEncodingContext& context, + const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance* + certificate_provider_instance_proto, + CommonTlsContext::CertificateProviderPluginInstance* + certificate_provider_plugin_instance) { + *certificate_provider_plugin_instance = { + UpbStringToStdString( + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance_instance_name( + certificate_provider_instance_proto)), + UpbStringToStdString( + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CertificateProviderInstance_certificate_name( + certificate_provider_instance_proto))}; + if (context.certificate_provider_definition_map->find( + certificate_provider_plugin_instance->instance_name) == + context.certificate_provider_definition_map->end()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Unrecognized certificate provider instance name: ", + certificate_provider_plugin_instance->instance_name)); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle CertificateProviderPluginInstanceParse( + const XdsEncodingContext& context, + const envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance* + certificate_provider_plugin_instance_proto, + CommonTlsContext::CertificateProviderPluginInstance* + certificate_provider_plugin_instance) { + *certificate_provider_plugin_instance = { + UpbStringToStdString( + envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance_instance_name( + certificate_provider_plugin_instance_proto)), + UpbStringToStdString( + envoy_extensions_transport_sockets_tls_v3_CertificateProviderPluginInstance_certificate_name( + certificate_provider_plugin_instance_proto))}; + if (context.certificate_provider_definition_map->find( + certificate_provider_plugin_instance->instance_name) == + context.certificate_provider_definition_map->end()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Unrecognized certificate provider instance name: ", + certificate_provider_plugin_instance->instance_name)); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle CertificateValidationContextParse( + const XdsEncodingContext& context, + const envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext* + certificate_validation_context_proto, + CommonTlsContext::CertificateValidationContext* + certificate_validation_context) { + std::vector<grpc_error_handle> errors; + size_t len = 0; + auto* subject_alt_names_matchers = + envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_match_subject_alt_names( + certificate_validation_context_proto, &len); + for (size_t i = 0; i < len; ++i) { + StringMatcher::Type type; + TString matcher; + if (envoy_type_matcher_v3_StringMatcher_has_exact( + subject_alt_names_matchers[i])) { + 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::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::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::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::kSafeRegex; + auto* regex_matcher = envoy_type_matcher_v3_StringMatcher_safe_regex( + subject_alt_names_matchers[i]); + matcher = UpbStringToStdString( + envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); + } else { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid StringMatcher specified")); + continue; + } + bool ignore_case = envoy_type_matcher_v3_StringMatcher_ignore_case( + subject_alt_names_matchers[i]); + y_absl::StatusOr<StringMatcher> string_matcher = + StringMatcher::Create(type, matcher, + /*case_sensitive=*/!ignore_case); + if (!string_matcher.ok()) { + errors.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("string matcher: ", string_matcher.status().message()))); + continue; + } + if (type == StringMatcher::Type::kSafeRegex && ignore_case) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "StringMatcher: ignore_case has no effect for SAFE_REGEX.")); + continue; + } + certificate_validation_context->match_subject_alt_names.push_back( + std::move(string_matcher.value())); + } + auto* ca_certificate_provider_instance = + envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_ca_certificate_provider_instance( + certificate_validation_context_proto); + if (ca_certificate_provider_instance != nullptr) { + grpc_error_handle error = CertificateProviderPluginInstanceParse( + context, ca_certificate_provider_instance, + &certificate_validation_context->ca_certificate_provider_instance); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_spki( + certificate_validation_context_proto, nullptr) != nullptr) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: verify_certificate_spki " + "unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_verify_certificate_hash( + certificate_validation_context_proto, nullptr) != nullptr) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: verify_certificate_hash " + "unsupported")); + } + auto* require_signed_certificate_timestamp = + envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_require_signed_certificate_timestamp( + certificate_validation_context_proto); + if (require_signed_certificate_timestamp != nullptr && + google_protobuf_BoolValue_value(require_signed_certificate_timestamp)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: " + "require_signed_certificate_timestamp unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_crl( + certificate_validation_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: crl unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CertificateValidationContext_has_custom_validator_config( + certificate_validation_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "CertificateValidationContext: custom_validator_config " + "unsupported")); + } + return GRPC_ERROR_CREATE_FROM_VECTOR( + "Error parsing CertificateValidationContext", &errors); +} + +} // namespace + +grpc_error_handle CommonTlsContext::Parse( + const XdsEncodingContext& context, + const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext* + common_tls_context_proto, + CommonTlsContext* common_tls_context) { + std::vector<grpc_error_handle> errors; + // The validation context is derived from the oneof in + // 'validation_context_type'. 'validation_context_sds_secret_config' is not + // supported. + auto* combined_validation_context = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_combined_validation_context( + common_tls_context_proto); + if (combined_validation_context != nullptr) { + auto* default_validation_context = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CombinedCertificateValidationContext_default_validation_context( + combined_validation_context); + if (default_validation_context != nullptr) { + grpc_error_handle error = CertificateValidationContextParse( + context, default_validation_context, + &common_tls_context->certificate_validation_context); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + // If after parsing default_validation_context, + // common_tls_context->certificate_validation_context.ca_certificate_provider_instance + // is empty, fall back onto + // 'validation_context_certificate_provider_instance' inside + // 'combined_validation_context'. Note that this way of fetching root + // certificates is deprecated and will be removed in the future. + // TODO(yashykt): Remove this once it's no longer needed. + auto* validation_context_certificate_provider_instance = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_CombinedCertificateValidationContext_validation_context_certificate_provider_instance( + combined_validation_context); + if (common_tls_context->certificate_validation_context + .ca_certificate_provider_instance.Empty() && + validation_context_certificate_provider_instance != nullptr) { + grpc_error_handle error = CertificateProviderInstanceParse( + context, validation_context_certificate_provider_instance, + &common_tls_context->certificate_validation_context + .ca_certificate_provider_instance); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + } else { + auto* validation_context = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_validation_context( + common_tls_context_proto); + if (validation_context != nullptr) { + grpc_error_handle error = CertificateValidationContextParse( + context, validation_context, + &common_tls_context->certificate_validation_context); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } else if ( + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_validation_context_sds_secret_config( + common_tls_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "validation_context_sds_secret_config unsupported")); + } + } + auto* tls_certificate_provider_instance = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_tls_certificate_provider_instance( + common_tls_context_proto); + if (tls_certificate_provider_instance != nullptr) { + grpc_error_handle error = CertificateProviderPluginInstanceParse( + context, tls_certificate_provider_instance, + &common_tls_context->tls_certificate_provider_instance); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } else { + // Fall back onto 'tls_certificate_certificate_provider_instance'. Note that + // this way of fetching identity certificates is deprecated and will be + // removed in the future. + // TODO(yashykt): Remove this once it's no longer needed. + auto* tls_certificate_certificate_provider_instance = + envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_tls_certificate_certificate_provider_instance( + common_tls_context_proto); + if (tls_certificate_certificate_provider_instance != nullptr) { + grpc_error_handle error = CertificateProviderInstanceParse( + context, tls_certificate_certificate_provider_instance, + &common_tls_context->tls_certificate_provider_instance); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } else { + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_certificates( + common_tls_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "tls_certificates unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_certificate_sds_secret_configs( + common_tls_context_proto)) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "tls_certificate_sds_secret_configs unsupported")); + } + } + } + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_tls_params( + common_tls_context_proto)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("tls_params unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_CommonTlsContext_has_custom_handshaker( + common_tls_context_proto)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("custom_handshaker unsupported")); + } + return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing CommonTlsContext", + &errors); +} + +grpc_error_handle ExtractHttpFilterTypeName(const XdsEncodingContext& context, + const google_protobuf_Any* any, + y_absl::string_view* filter_type) { + *filter_type = UpbStringToAbsl(google_protobuf_Any_type_url(any)); + if (*filter_type == "type.googleapis.com/xds.type.v3.TypedStruct" || + *filter_type == "type.googleapis.com/udpa.type.v1.TypedStruct") { + upb_strview any_value = google_protobuf_Any_value(any); + const auto* typed_struct = xds_type_v3_TypedStruct_parse( + any_value.data, any_value.size, context.arena); + if (typed_struct == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "could not parse TypedStruct from filter config"); + } + *filter_type = + UpbStringToAbsl(xds_type_v3_TypedStruct_type_url(typed_struct)); + } + *filter_type = y_absl::StripPrefix(*filter_type, "type.googleapis.com/"); + return GRPC_ERROR_NONE; +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_common_types.h b/contrib/libs/grpc/src/core/ext/xds/xds_common_types.h new file mode 100644 index 0000000000..4c26539238 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_common_types.h @@ -0,0 +1,110 @@ +// +// 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_XDS_XDS_COMMON_TYPES_H +#define GRPC_CORE_EXT_XDS_XDS_COMMON_TYPES_H + +#include <grpc/support/port_platform.h> + +#include <util/generic/string.h> +#include <vector> + +#include "y_absl/strings/str_format.h" +#include "envoy/extensions/transport_sockets/tls/v3/tls.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/duration.upb.h" + +#include "src/core/ext/xds/upb_utils.h" +#include "src/core/lib/matchers/matchers.h" + +namespace grpc_core { + +struct Duration { + int64_t seconds = 0; + int32_t nanos = 0; + + Duration() = default; + + bool operator==(const Duration& other) const { + return seconds == other.seconds && nanos == other.nanos; + } + TString ToString() const { + return y_absl::StrFormat("Duration seconds: %ld, nanos %d", seconds, nanos); + } + + static Duration Parse(const google_protobuf_Duration* proto_duration) { + Duration duration; + duration.seconds = google_protobuf_Duration_seconds(proto_duration); + duration.nanos = google_protobuf_Duration_nanos(proto_duration); + return duration; + } +}; + +struct CommonTlsContext { + struct CertificateProviderPluginInstance { + TString instance_name; + TString certificate_name; + + bool operator==(const CertificateProviderPluginInstance& other) const { + return instance_name == other.instance_name && + certificate_name == other.certificate_name; + } + + TString ToString() const; + bool Empty() const; + }; + + struct CertificateValidationContext { + CertificateProviderPluginInstance ca_certificate_provider_instance; + std::vector<StringMatcher> match_subject_alt_names; + + bool operator==(const CertificateValidationContext& other) const { + return ca_certificate_provider_instance == + other.ca_certificate_provider_instance && + match_subject_alt_names == other.match_subject_alt_names; + } + + TString ToString() const; + bool Empty() const; + }; + + CertificateValidationContext certificate_validation_context; + CertificateProviderPluginInstance tls_certificate_provider_instance; + + bool operator==(const CommonTlsContext& other) const { + return certificate_validation_context == + other.certificate_validation_context && + tls_certificate_provider_instance == + other.tls_certificate_provider_instance; + } + + TString ToString() const; + bool Empty() const; + + static grpc_error_handle Parse( + const XdsEncodingContext& context, + const envoy_extensions_transport_sockets_tls_v3_CommonTlsContext* + common_tls_context_proto, + CommonTlsContext* common_tls_context); +}; + +grpc_error_handle ExtractHttpFilterTypeName(const XdsEncodingContext& context, + const google_protobuf_Any* any, + y_absl::string_view* filter_type); + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_COMMON_TYPES_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc new file mode 100644 index 0000000000..f83dac09fc --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc @@ -0,0 +1,364 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_endpoint.h" + +#include "y_absl/memory/memory.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_join.h" +#include "envoy/config/core/v3/address.upb.h" +#include "envoy/config/core/v3/base.upb.h" +#include "envoy/config/core/v3/health_check.upb.h" +#include "envoy/config/endpoint/v3/endpoint.upb.h" +#include "envoy/config/endpoint/v3/endpoint.upbdefs.h" +#include "envoy/config/endpoint/v3/endpoint_components.upb.h" +#include "envoy/type/v3/percent.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "upb/text_encode.h" +#include "upb/upb.h" +#include "upb/upb.hpp" + +#include "src/core/ext/xds/upb_utils.h" +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" + +namespace grpc_core { + +// +// XdsEndpointResource +// + +TString XdsEndpointResource::Priority::Locality::ToString() const { + std::vector<TString> endpoint_strings; + for (const ServerAddress& endpoint : endpoints) { + endpoint_strings.emplace_back(endpoint.ToString()); + } + return y_absl::StrCat("{name=", name->AsHumanReadableString(), + ", lb_weight=", lb_weight, ", endpoints=[", + y_absl::StrJoin(endpoint_strings, ", "), "]}"); +} + +bool XdsEndpointResource::Priority::operator==(const Priority& other) const { + if (localities.size() != other.localities.size()) return false; + auto it1 = localities.begin(); + auto it2 = other.localities.begin(); + while (it1 != localities.end()) { + if (*it1->first != *it2->first) return false; + if (it1->second != it2->second) return false; + ++it1; + ++it2; + } + return true; +} + +TString XdsEndpointResource::Priority::ToString() const { + std::vector<TString> locality_strings; + for (const auto& p : localities) { + locality_strings.emplace_back(p.second.ToString()); + } + return y_absl::StrCat("[", y_absl::StrJoin(locality_strings, ", "), "]"); +} + +bool XdsEndpointResource::DropConfig::ShouldDrop( + const TString** category_name) const { + for (size_t i = 0; i < drop_category_list_.size(); ++i) { + const auto& drop_category = drop_category_list_[i]; + // Generate a random number in [0, 1000000). + const uint32_t random = static_cast<uint32_t>(rand()) % 1000000; + if (random < drop_category.parts_per_million) { + *category_name = &drop_category.name; + return true; + } + } + return false; +} + +TString XdsEndpointResource::DropConfig::ToString() const { + std::vector<TString> category_strings; + for (const DropCategory& category : drop_category_list_) { + category_strings.emplace_back( + y_absl::StrCat(category.name, "=", category.parts_per_million)); + } + return y_absl::StrCat("{[", y_absl::StrJoin(category_strings, ", "), + "], drop_all=", drop_all_, "}"); +} + +TString XdsEndpointResource::ToString() const { + std::vector<TString> priority_strings; + for (size_t i = 0; i < priorities.size(); ++i) { + const Priority& priority = priorities[i]; + priority_strings.emplace_back( + y_absl::StrCat("priority ", i, ": ", priority.ToString())); + } + return y_absl::StrCat("priorities=[", y_absl::StrJoin(priority_strings, ", "), + "], drop_config=", drop_config->ToString()); +} + +// +// XdsEndpointResourceType +// + +namespace { + +void MaybeLogClusterLoadAssignment( + const XdsEncodingContext& context, + const envoy_config_endpoint_v3_ClusterLoadAssignment* cla) { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && + gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + const upb_msgdef* msg_type = + envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef( + context.symtab); + char buf[10240]; + upb_text_encode(cla, msg_type, nullptr, 0, buf, sizeof(buf)); + gpr_log(GPR_DEBUG, "[xds_client %p] ClusterLoadAssignment: %s", + context.client, buf); + } +} + +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. + const int32_t health_status = + envoy_config_endpoint_v3_LbEndpoint_health_status(lb_endpoint); + if (health_status != envoy_config_core_v3_UNKNOWN && + health_status != envoy_config_core_v3_HEALTHY) { + return GRPC_ERROR_NONE; + } + // Find the ip:port. + const envoy_config_endpoint_v3_Endpoint* endpoint = + envoy_config_endpoint_v3_LbEndpoint_endpoint(lb_endpoint); + const envoy_config_core_v3_Address* address = + envoy_config_endpoint_v3_Endpoint_address(endpoint); + const envoy_config_core_v3_SocketAddress* socket_address = + envoy_config_core_v3_Address_socket_address(address); + TString address_str = UpbStringToStdString( + envoy_config_core_v3_SocketAddress_address(socket_address)); + uint32_t port = envoy_config_core_v3_SocketAddress_port_value(socket_address); + if (GPR_UNLIKELY(port >> 16) != 0) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Invalid port."); + } + // Find load_balancing_weight for the endpoint. + const google_protobuf_UInt32Value* load_balancing_weight = + envoy_config_endpoint_v3_LbEndpoint_load_balancing_weight(lb_endpoint); + const int32_t weight = + load_balancing_weight != nullptr + ? google_protobuf_UInt32Value_value(load_balancing_weight) + : 500; + if (weight == 0) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid endpoint weight of 0."); + } + // Populate grpc_resolved_address. + grpc_resolved_address addr; + 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. + std::map<const char*, std::unique_ptr<ServerAddress::AttributeInterface>> + attributes; + attributes[ServerAddressWeightAttribute::kServerAddressWeightAttributeKey] = + y_absl::make_unique<ServerAddressWeightAttribute>(weight); + list->emplace_back(addr, nullptr, std::move(attributes)); + return GRPC_ERROR_NONE; +} + +grpc_error_handle LocalityParse( + const envoy_config_endpoint_v3_LocalityLbEndpoints* locality_lb_endpoints, + XdsEndpointResource::Priority::Locality* output_locality, + size_t* priority) { + // Parse LB weight. + const google_protobuf_UInt32Value* lb_weight = + envoy_config_endpoint_v3_LocalityLbEndpoints_load_balancing_weight( + locality_lb_endpoints); + // If LB weight is not specified, it means this locality is assigned no load. + // TODO(juanlishen): When we support CDS to configure the inter-locality + // policy, we should change the LB weight handling. + output_locality->lb_weight = + lb_weight != nullptr ? google_protobuf_UInt32Value_value(lb_weight) : 0; + if (output_locality->lb_weight == 0) return GRPC_ERROR_NONE; + // Parse locality name. + 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."); + } + TString region = + UpbStringToStdString(envoy_config_core_v3_Locality_region(locality)); + TString zone = + UpbStringToStdString(envoy_config_core_v3_Locality_region(locality)); + TString sub_zone = + UpbStringToStdString(envoy_config_core_v3_Locality_sub_zone(locality)); + output_locality->name = MakeRefCounted<XdsLocalityName>( + std::move(region), std::move(zone), std::move(sub_zone)); + // Parse the addresses. + size_t size; + const envoy_config_endpoint_v3_LbEndpoint* const* lb_endpoints = + envoy_config_endpoint_v3_LocalityLbEndpoints_lb_endpoints( + locality_lb_endpoints, &size); + for (size_t i = 0; i < size; ++i) { + grpc_error_handle error = ServerAddressParseAndAppend( + lb_endpoints[i], &output_locality->endpoints); + if (error != GRPC_ERROR_NONE) return error; + } + // Parse the priority. + *priority = envoy_config_endpoint_v3_LocalityLbEndpoints_priority( + locality_lb_endpoints); + return GRPC_ERROR_NONE; +} + +grpc_error_handle DropParseAndAppend( + const envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload* + drop_overload, + XdsEndpointResource::DropConfig* drop_config) { + // Get the category. + TString category = UpbStringToStdString( + envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload_category( + drop_overload)); + if (category.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty drop category name"); + } + // Get the drop rate (per million). + const envoy_type_v3_FractionalPercent* drop_percentage = + envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload_drop_percentage( + drop_overload); + uint32_t numerator = + envoy_type_v3_FractionalPercent_numerator(drop_percentage); + const auto denominator = + static_cast<envoy_type_v3_FractionalPercent_DenominatorType>( + envoy_type_v3_FractionalPercent_denominator(drop_percentage)); + // Normalize to million. + switch (denominator) { + case envoy_type_v3_FractionalPercent_HUNDRED: + numerator *= 10000; + break; + case envoy_type_v3_FractionalPercent_TEN_THOUSAND: + numerator *= 100; + break; + case envoy_type_v3_FractionalPercent_MILLION: + break; + default: + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Unknown denominator type"); + } + // Cap numerator to 1000000. + numerator = std::min(numerator, 1000000u); + drop_config->AddCategory(std::move(category), numerator); + return GRPC_ERROR_NONE; +} + +grpc_error_handle EdsResourceParse( + const XdsEncodingContext& /*context*/, + const envoy_config_endpoint_v3_ClusterLoadAssignment* + cluster_load_assignment, + bool /*is_v2*/, XdsEndpointResource* eds_update) { + std::vector<grpc_error_handle> errors; + // 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); + for (size_t j = 0; j < locality_size; ++j) { + size_t priority; + XdsEndpointResource::Priority::Locality locality; + grpc_error_handle error = LocalityParse(endpoints[j], &locality, &priority); + if (error != GRPC_ERROR_NONE) { + errors.push_back(error); + continue; + } + // Filter out locality with weight 0. + if (locality.lb_weight == 0) continue; + // Make sure prorities is big enough. Note that they might not + // arrive in priority order. + while (eds_update->priorities.size() < priority + 1) { + eds_update->priorities.emplace_back(); + } + eds_update->priorities[priority].localities.emplace(locality.name.get(), + std::move(locality)); + } + for (const auto& priority : eds_update->priorities) { + if (priority.localities.empty()) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("sparse priority list")); + } + } + // Get the drop config. + eds_update->drop_config = MakeRefCounted<XdsEndpointResource::DropConfig>(); + const envoy_config_endpoint_v3_ClusterLoadAssignment_Policy* policy = + envoy_config_endpoint_v3_ClusterLoadAssignment_policy( + cluster_load_assignment); + if (policy != nullptr) { + size_t drop_size; + const envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_DropOverload* const* + drop_overload = + envoy_config_endpoint_v3_ClusterLoadAssignment_Policy_drop_overloads( + policy, &drop_size); + for (size_t j = 0; j < drop_size; ++j) { + grpc_error_handle error = + DropParseAndAppend(drop_overload[j], eds_update->drop_config.get()); + if (error != GRPC_ERROR_NONE) { + errors.push_back( + grpc_error_add_child(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "drop config validation error"), + error)); + } + } + } + return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing EDS resource", &errors); +} + +} // namespace + +y_absl::StatusOr<XdsResourceType::DecodeResult> XdsEndpointResourceType::Decode( + const XdsEncodingContext& context, y_absl::string_view serialized_resource, + bool is_v2) const { + // Parse serialized proto. + auto* resource = envoy_config_endpoint_v3_ClusterLoadAssignment_parse( + serialized_resource.data(), serialized_resource.size(), context.arena); + if (resource == nullptr) { + return y_absl::InvalidArgumentError( + "Can't parse ClusterLoadAssignment resource."); + } + MaybeLogClusterLoadAssignment(context, resource); + // Validate resource. + DecodeResult result; + result.name = UpbStringToStdString( + envoy_config_endpoint_v3_ClusterLoadAssignment_cluster_name(resource)); + auto endpoint_data = y_absl::make_unique<ResourceDataSubclass>(); + grpc_error_handle error = + EdsResourceParse(context, resource, is_v2, &endpoint_data->resource); + if (error != GRPC_ERROR_NONE) { + TString error_str = grpc_error_std_string(error); + GRPC_ERROR_UNREF(error); + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_ERROR, "[xds_client %p] invalid ClusterLoadAssignment %s: %s", + context.client, result.name.c_str(), error_str.c_str()); + } + result.resource = y_absl::InvalidArgumentError(error_str); + } else { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_INFO, "[xds_client %p] parsed ClusterLoadAssignment %s: %s", + context.client, result.name.c_str(), + endpoint_data->resource.ToString().c_str()); + } + result.resource = std::move(endpoint_data); + } + return std::move(result); +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h new file mode 100644 index 0000000000..492609ac86 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h @@ -0,0 +1,135 @@ +// +// 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_XDS_XDS_ENDPOINT_H +#define GRPC_CORE_EXT_XDS_XDS_ENDPOINT_H + +#include <grpc/support/port_platform.h> + +#include <map> +#include <set> +#include <util/generic/string.h> + +#include "y_absl/container/inlined_vector.h" +#include "envoy/config/endpoint/v3/endpoint.upbdefs.h" + +#include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_client_stats.h" +#include "src/core/ext/xds/xds_resource_type_impl.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/resolver/server_address.h" + +namespace grpc_core { + +struct XdsEndpointResource { + struct Priority { + struct Locality { + RefCountedPtr<XdsLocalityName> name; + uint32_t lb_weight; + ServerAddressList endpoints; + + bool operator==(const Locality& other) const { + return *name == *other.name && lb_weight == other.lb_weight && + endpoints == other.endpoints; + } + bool operator!=(const Locality& other) const { return !(*this == other); } + TString ToString() const; + }; + + std::map<XdsLocalityName*, Locality, XdsLocalityName::Less> localities; + + bool operator==(const Priority& other) const; + TString ToString() const; + }; + using PriorityList = y_absl::InlinedVector<Priority, 2>; + + // There are two phases of accessing this class's content: + // 1. to initialize in the control plane combiner; + // 2. to use in the data plane combiner. + // So no additional synchronization is needed. + class DropConfig : public RefCounted<DropConfig> { + public: + struct DropCategory { + bool operator==(const DropCategory& other) const { + return name == other.name && + parts_per_million == other.parts_per_million; + } + + TString name; + const uint32_t parts_per_million; + }; + + using DropCategoryList = y_absl::InlinedVector<DropCategory, 2>; + + void AddCategory(TString name, uint32_t parts_per_million) { + drop_category_list_.emplace_back( + DropCategory{std::move(name), parts_per_million}); + if (parts_per_million == 1000000) drop_all_ = true; + } + + // The only method invoked from outside the WorkSerializer (used in + // the data plane). + bool ShouldDrop(const TString** category_name) const; + + const DropCategoryList& drop_category_list() const { + return drop_category_list_; + } + + bool drop_all() const { return drop_all_; } + + bool operator==(const DropConfig& other) const { + return drop_category_list_ == other.drop_category_list_; + } + bool operator!=(const DropConfig& other) const { return !(*this == other); } + + TString ToString() const; + + private: + DropCategoryList drop_category_list_; + bool drop_all_ = false; + }; + + PriorityList priorities; + RefCountedPtr<DropConfig> drop_config; + + bool operator==(const XdsEndpointResource& other) const { + return priorities == other.priorities && *drop_config == *other.drop_config; + } + TString ToString() const; +}; + +class XdsEndpointResourceType + : public XdsResourceTypeImpl<XdsEndpointResourceType, XdsEndpointResource> { + public: + y_absl::string_view type_url() const override { + return "envoy.config.endpoint.v3.ClusterLoadAssignment"; + } + y_absl::string_view v2_type_url() const override { + return "envoy.api.v2.ClusterLoadAssignment"; + } + + y_absl::StatusOr<DecodeResult> Decode(const XdsEncodingContext& context, + y_absl::string_view serialized_resource, + bool is_v2) const override; + + void InitUpbSymtab(upb_symtab* symtab) const override { + envoy_config_endpoint_v3_ClusterLoadAssignment_getmsgdef(symtab); + } +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_ENDPOINT_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_http_filters.cc b/contrib/libs/grpc/src/core/ext/xds/xds_http_filters.cc index c063a5d4f0..9564254be6 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_http_filters.cc +++ b/contrib/libs/grpc/src/core/ext/xds/xds_http_filters.cc @@ -22,6 +22,7 @@ #include "envoy/extensions/filters/http/router/v3/router.upbdefs.h" #include "src/core/ext/xds/xds_http_fault_filter.h" +#include "src/core/ext/xds/xds_http_rbac_filter.h" namespace grpc_core { @@ -106,6 +107,10 @@ void XdsHttpFilterRegistry::Init() { {kXdsHttpRouterFilterConfigName}); RegisterFilter(y_absl::make_unique<XdsHttpFaultFilter>(), {kXdsHttpFaultFilterConfigName}); + RegisterFilter(y_absl::make_unique<XdsHttpRbacFilter>(), + {kXdsHttpRbacFilterConfigName}); + RegisterFilter(y_absl::make_unique<XdsHttpRbacFilter>(), + {kXdsHttpRbacFilterConfigOverrideName}); } void XdsHttpFilterRegistry::Shutdown() { diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc b/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc new file mode 100644 index 0000000000..86bc5f6981 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc @@ -0,0 +1,563 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_http_rbac_filter.h" + +#include "y_absl/strings/str_format.h" +#include "envoy/config/core/v3/address.upb.h" +#include "envoy/config/rbac/v3/rbac.upb.h" +#include "envoy/config/route/v3/route_components.upb.h" +#include "envoy/extensions/filters/http/rbac/v3/rbac.upb.h" +#include "envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.h" +#include "envoy/type/matcher/v3/metadata.upb.h" +#include "envoy/type/matcher/v3/path.upb.h" +#include "envoy/type/matcher/v3/regex.upb.h" +#include "envoy/type/matcher/v3/string.upb.h" +#include "envoy/type/v3/range.upb.h" +#include "google/protobuf/wrappers.upb.h" + +#include "src/core/ext/filters/rbac/rbac_filter.h" +#include "src/core/ext/filters/rbac/rbac_service_config_parser.h" +#include "src/core/ext/xds/upb_utils.h" +#include "src/core/lib/channel/channel_args.h" + +namespace grpc_core { + +const char* kXdsHttpRbacFilterConfigName = + "envoy.extensions.filters.http.rbac.v3.RBAC"; + +const char* kXdsHttpRbacFilterConfigOverrideName = + "envoy.extensions.filters.http.rbac.v3.RBACPerRoute"; + +namespace { + +Json ParseRegexMatcherToJson( + const envoy_type_matcher_v3_RegexMatcher* regex_matcher) { + return Json::Object( + {{"regex", UpbStringToStdString(envoy_type_matcher_v3_RegexMatcher_regex( + regex_matcher))}}); +} + +Json ParseInt64RangeToJson(const envoy_type_v3_Int64Range* range) { + return Json::Object{{"start", envoy_type_v3_Int64Range_start(range)}, + {"end", envoy_type_v3_Int64Range_end(range)}}; +} + +y_absl::StatusOr<Json> ParseHeaderMatcherToJson( + const envoy_config_route_v3_HeaderMatcher* header) { + Json::Object header_json; + std::vector<y_absl::Status> error_list; + TString name = + UpbStringToStdString(envoy_config_route_v3_HeaderMatcher_name(header)); + if (name == ":scheme") { + error_list.push_back( + y_absl::InvalidArgumentError("':scheme' not allowed in header")); + } else if (y_absl::StartsWith(name, "grpc-")) { + error_list.push_back( + y_absl::InvalidArgumentError("'grpc-' prefixes not allowed in header")); + } + header_json.emplace("name", std::move(name)); + if (envoy_config_route_v3_HeaderMatcher_has_exact_match(header)) { + header_json.emplace( + "exactMatch", + UpbStringToStdString( + envoy_config_route_v3_HeaderMatcher_exact_match(header))); + } else if (envoy_config_route_v3_HeaderMatcher_has_safe_regex_match(header)) { + header_json.emplace( + "safeRegexMatch", + ParseRegexMatcherToJson( + envoy_config_route_v3_HeaderMatcher_safe_regex_match(header))); + } else if (envoy_config_route_v3_HeaderMatcher_has_range_match(header)) { + header_json.emplace( + "rangeMatch", + ParseInt64RangeToJson( + envoy_config_route_v3_HeaderMatcher_range_match(header))); + } else if (envoy_config_route_v3_HeaderMatcher_has_present_match(header)) { + header_json.emplace( + "presentMatch", + envoy_config_route_v3_HeaderMatcher_present_match(header)); + } else if (envoy_config_route_v3_HeaderMatcher_has_prefix_match(header)) { + header_json.emplace( + "prefixMatch", + UpbStringToStdString( + envoy_config_route_v3_HeaderMatcher_prefix_match(header))); + } else if (envoy_config_route_v3_HeaderMatcher_has_suffix_match(header)) { + header_json.emplace( + "suffixMatch", + UpbStringToStdString( + envoy_config_route_v3_HeaderMatcher_suffix_match(header))); + } else if (envoy_config_route_v3_HeaderMatcher_has_contains_match(header)) { + header_json.emplace( + "containsMatch", + UpbStringToStdString( + envoy_config_route_v3_HeaderMatcher_contains_match(header))); + } else { + error_list.push_back( + y_absl::InvalidArgumentError("Invalid route header matcher specified.")); + } + if (!error_list.empty()) { + return StatusCreate(y_absl::StatusCode::kInvalidArgument, + "Error parsing HeaderMatcher", DEBUG_LOCATION, + std::move(error_list)); + } + header_json.emplace("invertMatch", + envoy_config_route_v3_HeaderMatcher_invert_match(header)); + return header_json; +} + +y_absl::StatusOr<Json> ParseStringMatcherToJson( + const envoy_type_matcher_v3_StringMatcher* matcher) { + Json::Object json; + if (envoy_type_matcher_v3_StringMatcher_has_exact(matcher)) { + json.emplace("exact", + UpbStringToStdString( + envoy_type_matcher_v3_StringMatcher_exact(matcher))); + } else if (envoy_type_matcher_v3_StringMatcher_has_prefix(matcher)) { + json.emplace("prefix", + UpbStringToStdString( + envoy_type_matcher_v3_StringMatcher_prefix(matcher))); + } else if (envoy_type_matcher_v3_StringMatcher_has_suffix(matcher)) { + json.emplace("suffix", + UpbStringToStdString( + envoy_type_matcher_v3_StringMatcher_suffix(matcher))); + } else if (envoy_type_matcher_v3_StringMatcher_has_safe_regex(matcher)) { + json.emplace("safeRegex", + ParseRegexMatcherToJson( + envoy_type_matcher_v3_StringMatcher_safe_regex(matcher))); + } else if (envoy_type_matcher_v3_StringMatcher_has_contains(matcher)) { + json.emplace("contains", + UpbStringToStdString( + envoy_type_matcher_v3_StringMatcher_contains(matcher))); + } else { + return y_absl::InvalidArgumentError("StringMatcher: Invalid match pattern"); + } + json.emplace("ignoreCase", + envoy_type_matcher_v3_StringMatcher_ignore_case(matcher)); + return json; +} + +y_absl::StatusOr<Json> ParsePathMatcherToJson( + const envoy_type_matcher_v3_PathMatcher* matcher) { + const auto* path = envoy_type_matcher_v3_PathMatcher_path(matcher); + if (path == nullptr) { + return y_absl::InvalidArgumentError("PathMatcher has empty path"); + } + Json::Object json; + auto path_json = ParseStringMatcherToJson(path); + if (!path_json.ok()) { + return path_json; + } + json.emplace("path", std::move(*path_json)); + return json; +} + +Json ParseUInt32ValueToJson(const google_protobuf_UInt32Value* value) { + return Json::Object{{"value", google_protobuf_UInt32Value_value(value)}}; +} + +Json ParseCidrRangeToJson(const envoy_config_core_v3_CidrRange* range) { + Json::Object json; + json.emplace("addressPrefix", + UpbStringToStdString( + envoy_config_core_v3_CidrRange_address_prefix(range))); + const auto* prefix_len = envoy_config_core_v3_CidrRange_prefix_len(range); + if (prefix_len != nullptr) { + json.emplace("prefixLen", ParseUInt32ValueToJson(prefix_len)); + } + return json; +} + +Json ParseMetadataMatcherToJson( + const envoy_type_matcher_v3_MetadataMatcher* metadata_matcher) { + Json::Object json; + // The fields "filter", "path" and "value" are irrelevant to gRPC as per + // https://github.com/grpc/proposal/blob/master/A41-xds-rbac.md and are not + // being parsed. + json.emplace("invert", + envoy_type_matcher_v3_MetadataMatcher_invert(metadata_matcher)); + return json; +} + +y_absl::StatusOr<Json> ParsePermissionToJson( + const envoy_config_rbac_v3_Permission* permission) { + Json::Object permission_json; + // Helper function to parse Permission::Set to JSON. Used by `and_rules` and + // `or_rules`. + auto parse_permission_set_to_json = + [](const envoy_config_rbac_v3_Permission_Set* set) + -> y_absl::StatusOr<Json> { + std::vector<y_absl::Status> error_list; + Json::Array rules_json; + size_t size; + const envoy_config_rbac_v3_Permission* const* rules = + envoy_config_rbac_v3_Permission_Set_rules(set, &size); + for (size_t i = 0; i < size; ++i) { + auto permission_json = ParsePermissionToJson(rules[i]); + if (!permission_json.ok()) { + error_list.push_back(permission_json.status()); + } else { + rules_json.emplace_back(std::move(*permission_json)); + } + } + if (!error_list.empty()) { + return StatusCreate(y_absl::StatusCode::kInvalidArgument, + "Error parsing Set", DEBUG_LOCATION, + std::move(error_list)); + } + return Json::Object({{"rules", std::move(rules_json)}}); + }; + if (envoy_config_rbac_v3_Permission_has_and_rules(permission)) { + const auto* and_rules = + envoy_config_rbac_v3_Permission_and_rules(permission); + auto permission_set_json = parse_permission_set_to_json(and_rules); + if (!permission_set_json.ok()) { + return permission_set_json; + } + permission_json.emplace("andRules", std::move(*permission_set_json)); + } else if (envoy_config_rbac_v3_Permission_has_or_rules(permission)) { + const auto* or_rules = envoy_config_rbac_v3_Permission_or_rules(permission); + auto permission_set_json = parse_permission_set_to_json(or_rules); + if (!permission_set_json.ok()) { + return permission_set_json; + } + permission_json.emplace("orRules", std::move(*permission_set_json)); + } else if (envoy_config_rbac_v3_Permission_has_any(permission)) { + permission_json.emplace("any", + envoy_config_rbac_v3_Permission_any(permission)); + } else if (envoy_config_rbac_v3_Permission_has_header(permission)) { + auto header_json = ParseHeaderMatcherToJson( + envoy_config_rbac_v3_Permission_header(permission)); + if (!header_json.ok()) { + return header_json; + } + permission_json.emplace("header", std::move(*header_json)); + } else if (envoy_config_rbac_v3_Permission_has_url_path(permission)) { + auto url_path_json = ParsePathMatcherToJson( + envoy_config_rbac_v3_Permission_url_path(permission)); + if (!url_path_json.ok()) { + return url_path_json; + } + permission_json.emplace("urlPath", std::move(*url_path_json)); + } else if (envoy_config_rbac_v3_Permission_has_destination_ip(permission)) { + permission_json.emplace( + "destinationIp", + ParseCidrRangeToJson( + envoy_config_rbac_v3_Permission_destination_ip(permission))); + } else if (envoy_config_rbac_v3_Permission_has_destination_port(permission)) { + permission_json.emplace( + "destinationPort", + envoy_config_rbac_v3_Permission_destination_port(permission)); + } else if (envoy_config_rbac_v3_Permission_has_metadata(permission)) { + permission_json.emplace( + "metadata", ParseMetadataMatcherToJson( + envoy_config_rbac_v3_Permission_metadata(permission))); + } else if (envoy_config_rbac_v3_Permission_has_not_rule(permission)) { + auto not_rule_json = ParsePermissionToJson( + envoy_config_rbac_v3_Permission_not_rule(permission)); + if (!not_rule_json.ok()) { + return not_rule_json; + } + permission_json.emplace("notRule", std::move(*not_rule_json)); + } else if (envoy_config_rbac_v3_Permission_has_requested_server_name( + permission)) { + auto requested_server_name_json = ParseStringMatcherToJson( + envoy_config_rbac_v3_Permission_requested_server_name(permission)); + if (!requested_server_name_json.ok()) { + return requested_server_name_json; + } + permission_json.emplace("requestedServerName", + std::move(*requested_server_name_json)); + } else { + return y_absl::InvalidArgumentError("Permission: Invalid rule"); + } + return permission_json; +} + +y_absl::StatusOr<Json> ParsePrincipalToJson( + const envoy_config_rbac_v3_Principal* principal) { + Json::Object principal_json; + // Helper function to parse Principal::Set to JSON. Used by `and_ids` and + // `or_ids`. + auto parse_principal_set_to_json = + [](const envoy_config_rbac_v3_Principal_Set* set) + -> y_absl::StatusOr<Json> { + Json::Object json; + std::vector<y_absl::Status> error_list; + Json::Array ids_json; + size_t size; + const envoy_config_rbac_v3_Principal* const* ids = + envoy_config_rbac_v3_Principal_Set_ids(set, &size); + for (size_t i = 0; i < size; ++i) { + auto principal_json = ParsePrincipalToJson(ids[i]); + if (!principal_json.ok()) { + error_list.push_back(principal_json.status()); + } else { + ids_json.emplace_back(std::move(*principal_json)); + } + } + if (!error_list.empty()) { + return StatusCreate(y_absl::StatusCode::kInvalidArgument, + "Error parsing Set", DEBUG_LOCATION, + std::move(error_list)); + } + return Json::Object({{"ids", std::move(ids_json)}}); + }; + if (envoy_config_rbac_v3_Principal_has_and_ids(principal)) { + const auto* and_rules = envoy_config_rbac_v3_Principal_and_ids(principal); + auto principal_set_json = parse_principal_set_to_json(and_rules); + if (!principal_set_json.ok()) { + return principal_set_json; + } + principal_json.emplace("andIds", std::move(*principal_set_json)); + } else if (envoy_config_rbac_v3_Principal_has_or_ids(principal)) { + const auto* or_rules = envoy_config_rbac_v3_Principal_or_ids(principal); + auto principal_set_json = parse_principal_set_to_json(or_rules); + if (!principal_set_json.ok()) { + return principal_set_json; + } + principal_json.emplace("orIds", std::move(*principal_set_json)); + } else if (envoy_config_rbac_v3_Principal_has_any(principal)) { + principal_json.emplace("any", + envoy_config_rbac_v3_Principal_any(principal)); + } else if (envoy_config_rbac_v3_Principal_has_authenticated(principal)) { + auto* authenticated_json = + principal_json.emplace("authenticated", Json::Object()) + .first->second.mutable_object(); + const auto* principal_name = + envoy_config_rbac_v3_Principal_Authenticated_principal_name( + envoy_config_rbac_v3_Principal_authenticated(principal)); + if (principal_name != nullptr) { + auto principal_name_json = ParseStringMatcherToJson(principal_name); + if (!principal_name_json.ok()) { + return principal_name_json; + } + authenticated_json->emplace("principalName", + std::move(*principal_name_json)); + } + } else if (envoy_config_rbac_v3_Principal_has_source_ip(principal)) { + principal_json.emplace( + "sourceIp", ParseCidrRangeToJson( + envoy_config_rbac_v3_Principal_source_ip(principal))); + } else if (envoy_config_rbac_v3_Principal_has_direct_remote_ip(principal)) { + principal_json.emplace( + "directRemoteIp", + ParseCidrRangeToJson( + envoy_config_rbac_v3_Principal_direct_remote_ip(principal))); + } else if (envoy_config_rbac_v3_Principal_has_remote_ip(principal)) { + principal_json.emplace( + "remoteIp", ParseCidrRangeToJson( + envoy_config_rbac_v3_Principal_remote_ip(principal))); + } else if (envoy_config_rbac_v3_Principal_has_header(principal)) { + auto header_json = ParseHeaderMatcherToJson( + envoy_config_rbac_v3_Principal_header(principal)); + if (!header_json.ok()) { + return header_json; + } + principal_json.emplace("header", std::move(*header_json)); + } else if (envoy_config_rbac_v3_Principal_has_url_path(principal)) { + auto url_path_json = ParsePathMatcherToJson( + envoy_config_rbac_v3_Principal_url_path(principal)); + if (!url_path_json.ok()) { + return url_path_json; + } + principal_json.emplace("urlPath", std::move(*url_path_json)); + } else if (envoy_config_rbac_v3_Principal_has_metadata(principal)) { + principal_json.emplace( + "metadata", ParseMetadataMatcherToJson( + envoy_config_rbac_v3_Principal_metadata(principal))); + } else if (envoy_config_rbac_v3_Principal_has_not_id(principal)) { + auto not_id_json = + ParsePrincipalToJson(envoy_config_rbac_v3_Principal_not_id(principal)); + if (!not_id_json.ok()) { + return not_id_json; + } + principal_json.emplace("notId", std::move(*not_id_json)); + } else { + return y_absl::InvalidArgumentError("Principal: Invalid rule"); + } + return principal_json; +} + +y_absl::StatusOr<Json> ParsePolicyToJson( + const envoy_config_rbac_v3_Policy* policy) { + Json::Object policy_json; + std::vector<y_absl::Status> error_list; + size_t size; + Json::Array permissions_json; + const envoy_config_rbac_v3_Permission* const* permissions = + envoy_config_rbac_v3_Policy_permissions(policy, &size); + for (size_t i = 0; i < size; ++i) { + auto permission_json = ParsePermissionToJson(permissions[i]); + if (!permission_json.ok()) { + error_list.push_back(permission_json.status()); + } else { + permissions_json.emplace_back(std::move(*permission_json)); + } + } + policy_json.emplace("permissions", std::move(permissions_json)); + Json::Array principals_json; + const envoy_config_rbac_v3_Principal* const* principals = + envoy_config_rbac_v3_Policy_principals(policy, &size); + for (size_t i = 0; i < size; ++i) { + auto principal_json = ParsePrincipalToJson(principals[i]); + if (!principal_json.ok()) { + error_list.push_back(principal_json.status()); + } else { + principals_json.emplace_back(std::move(*principal_json)); + } + } + policy_json.emplace("principals", std::move(principals_json)); + if (envoy_config_rbac_v3_Policy_has_condition(policy)) { + error_list.push_back( + y_absl::InvalidArgumentError("Policy: condition not supported")); + } + if (envoy_config_rbac_v3_Policy_has_checked_condition(policy)) { + error_list.push_back( + y_absl::InvalidArgumentError("Policy: checked condition not supported")); + } + if (!error_list.empty()) { + return StatusCreate(y_absl::StatusCode::kInvalidArgument, + "Error parsing Policy", DEBUG_LOCATION, + std::move(error_list)); + } + return policy_json; +} + +y_absl::StatusOr<Json> ParseHttpRbacToJson( + const envoy_extensions_filters_http_rbac_v3_RBAC* rbac) { + Json::Object rbac_json; + std::vector<y_absl::Status> error_list; + const auto* rules = envoy_extensions_filters_http_rbac_v3_RBAC_rules(rbac); + if (rules != nullptr) { + int action = envoy_config_rbac_v3_RBAC_action(rules); + // Treat Log action as RBAC being absent + if (action == envoy_config_rbac_v3_RBAC_LOG) { + return rbac_json; + } + Json::Object inner_rbac_json; + inner_rbac_json.emplace("action", envoy_config_rbac_v3_RBAC_action(rules)); + if (envoy_config_rbac_v3_RBAC_has_policies(rules)) { + Json::Object policies_object; + size_t iter = UPB_MAP_BEGIN; + while (true) { + auto* entry = envoy_config_rbac_v3_RBAC_policies_next(rules, &iter); + if (entry == nullptr) { + break; + } + auto policy = ParsePolicyToJson( + envoy_config_rbac_v3_RBAC_PoliciesEntry_value(entry)); + if (!policy.ok()) { + error_list.push_back(StatusCreate( + y_absl::StatusCode::kInvalidArgument, + y_absl::StrFormat( + "RBAC PoliciesEntry key:%s", + UpbStringToStdString( + envoy_config_rbac_v3_RBAC_PoliciesEntry_key(entry))), + DEBUG_LOCATION, {policy.status()})); + } else { + policies_object.emplace( + UpbStringToStdString( + envoy_config_rbac_v3_RBAC_PoliciesEntry_key(entry)), + std::move(*policy)); + } + } + inner_rbac_json.emplace("policies", std::move(policies_object)); + } + rbac_json.emplace("rules", std::move(inner_rbac_json)); + } + if (!error_list.empty()) { + return StatusCreate(y_absl::StatusCode::kInvalidArgument, + "Error parsing RBAC", DEBUG_LOCATION, + std::move(error_list)); + } + return rbac_json; +} + +} // namespace + +void XdsHttpRbacFilter::PopulateSymtab(upb_symtab* symtab) const { + envoy_extensions_filters_http_rbac_v3_RBAC_getmsgdef(symtab); +} + +y_absl::StatusOr<XdsHttpFilterImpl::FilterConfig> +XdsHttpRbacFilter::GenerateFilterConfig(upb_strview serialized_filter_config, + upb_arena* arena) const { + y_absl::StatusOr<Json> rbac_json; + auto* rbac = envoy_extensions_filters_http_rbac_v3_RBAC_parse( + serialized_filter_config.data, serialized_filter_config.size, arena); + if (rbac == nullptr) { + return y_absl::InvalidArgumentError( + "could not parse HTTP RBAC filter config"); + } + rbac_json = ParseHttpRbacToJson(rbac); + if (!rbac_json.ok()) { + return rbac_json.status(); + } + return FilterConfig{kXdsHttpRbacFilterConfigName, std::move(*rbac_json)}; +} + +y_absl::StatusOr<XdsHttpFilterImpl::FilterConfig> +XdsHttpRbacFilter::GenerateFilterConfigOverride( + upb_strview serialized_filter_config, upb_arena* arena) const { + auto* rbac_per_route = + envoy_extensions_filters_http_rbac_v3_RBACPerRoute_parse( + serialized_filter_config.data, serialized_filter_config.size, arena); + if (rbac_per_route == nullptr) { + return y_absl::InvalidArgumentError("could not parse RBACPerRoute"); + } + y_absl::StatusOr<Json> rbac_json; + const auto* rbac = + envoy_extensions_filters_http_rbac_v3_RBACPerRoute_rbac(rbac_per_route); + if (rbac == nullptr) { + rbac_json = Json::Object(); + } else { + rbac_json = ParseHttpRbacToJson(rbac); + if (!rbac_json.ok()) { + return rbac_json.status(); + } + } + return FilterConfig{kXdsHttpRbacFilterConfigOverrideName, + std::move(*rbac_json)}; +} + +const grpc_channel_filter* XdsHttpRbacFilter::channel_filter() const { + return &RbacFilter::kFilterVtable; +} + +grpc_channel_args* XdsHttpRbacFilter::ModifyChannelArgs( + grpc_channel_args* args) const { + grpc_arg arg_to_add = grpc_channel_arg_integer_create( + const_cast<char*>(GRPC_ARG_PARSE_RBAC_METHOD_CONFIG), 1); + grpc_channel_args* new_args = + grpc_channel_args_copy_and_add(args, &arg_to_add, 1); + grpc_channel_args_destroy(args); + return new_args; +} + +y_absl::StatusOr<XdsHttpFilterImpl::ServiceConfigJsonEntry> +XdsHttpRbacFilter::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{"rbacPolicy", policy_json.Dump()}; +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.h b/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.h new file mode 100644 index 0000000000..e01d4cc1e8 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.h @@ -0,0 +1,54 @@ +// +// 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_RBAC_FILTER_H +#define GRPC_CORE_EXT_XDS_XDS_HTTP_RBAC_FILTER_H + +#include <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_http_filters.h" + +namespace grpc_core { + +extern const char* kXdsHttpRbacFilterConfigName; +extern const char* kXdsHttpRbacFilterConfigOverrideName; + +class XdsHttpRbacFilter : public XdsHttpFilterImpl { + public: + void PopulateSymtab(upb_symtab* symtab) const override; + + y_absl::StatusOr<FilterConfig> GenerateFilterConfig( + upb_strview serialized_filter_config, upb_arena* arena) const override; + + y_absl::StatusOr<FilterConfig> GenerateFilterConfigOverride( + upb_strview serialized_filter_config, upb_arena* arena) const override; + + const grpc_channel_filter* channel_filter() const override; + + grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) const override; + + y_absl::StatusOr<ServiceConfigJsonEntry> GenerateServiceConfig( + const FilterConfig& hcm_filter_config, + const FilterConfig* filter_config_override) const override; + + bool IsSupportedOnClients() const override { return false; } + + bool IsSupportedOnServers() const override { return true; } +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_HTTP_RBAC_FILTER_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_listener.cc b/contrib/libs/grpc/src/core/ext/xds/xds_listener.cc new file mode 100644 index 0000000000..ee7a08f88c --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_listener.cc @@ -0,0 +1,1036 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_listener.h" + +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_join.h" +#include "y_absl/strings/str_split.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/protocol.upb.h" +#include "envoy/config/listener/v3/api_listener.upb.h" +#include "envoy/config/listener/v3/listener.upb.h" +#include "envoy/config/listener/v3/listener.upbdefs.h" +#include "envoy/config/listener/v3/listener_components.upb.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 "google/protobuf/wrappers.upb.h" +#include "upb/text_encode.h" +#include "upb/upb.h" +#include "upb/upb.hpp" + +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" +#include "src/core/lib/gprpp/host_port.h" +#include "src/core/lib/iomgr/sockaddr.h" + +namespace grpc_core { + +// +// XdsListenerResource::DownstreamTlsContext +// + +TString XdsListenerResource::DownstreamTlsContext::ToString() const { + return y_absl::StrFormat("common_tls_context=%s, require_client_certificate=%s", + common_tls_context.ToString(), + require_client_certificate ? "true" : "false"); +} + +bool XdsListenerResource::DownstreamTlsContext::Empty() const { + return common_tls_context.Empty(); +} + +// +// XdsListenerResource::HttpConnectionManager +// + +TString XdsListenerResource::HttpConnectionManager::ToString() const { + y_absl::InlinedVector<TString, 4> contents; + contents.push_back(y_absl::StrFormat( + "route_config_name=%s", + !route_config_name.empty() ? route_config_name.c_str() : "<inlined>")); + contents.push_back(y_absl::StrFormat("http_max_stream_duration=%s", + http_max_stream_duration.ToString())); + if (rds_update.has_value()) { + contents.push_back( + y_absl::StrFormat("rds_update=%s", rds_update->ToString())); + } + if (!http_filters.empty()) { + std::vector<TString> filter_strings; + for (const auto& http_filter : http_filters) { + filter_strings.push_back(http_filter.ToString()); + } + contents.push_back(y_absl::StrCat("http_filters=[", + y_absl::StrJoin(filter_strings, ", "), "]")); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsListenerResource::HttpFilter +// + +TString XdsListenerResource::HttpConnectionManager::HttpFilter::ToString() + const { + return y_absl::StrCat("{name=", name, ", config=", config.ToString(), "}"); +} + +// +// XdsListenerResource::FilterChainData +// + +TString XdsListenerResource::FilterChainData::ToString() const { + return y_absl::StrCat( + "{downstream_tls_context=", downstream_tls_context.ToString(), + " http_connection_manager=", http_connection_manager.ToString(), "}"); +} + +// +// XdsListenerResource::FilterChainMap::CidrRange +// + +TString XdsListenerResource::FilterChainMap::CidrRange::ToString() const { + return y_absl::StrCat( + "{address_prefix=", grpc_sockaddr_to_string(&address, false), + ", prefix_len=", prefix_len, "}"); +} + +// +// FilterChain +// + +struct FilterChain { + struct FilterChainMatch { + uint32_t destination_port = 0; + std::vector<XdsListenerResource::FilterChainMap::CidrRange> prefix_ranges; + XdsListenerResource::FilterChainMap::ConnectionSourceType source_type = + XdsListenerResource::FilterChainMap::ConnectionSourceType::kAny; + std::vector<XdsListenerResource::FilterChainMap::CidrRange> + source_prefix_ranges; + std::vector<uint32_t> source_ports; + std::vector<TString> server_names; + TString transport_protocol; + std::vector<TString> application_protocols; + + TString ToString() const; + } filter_chain_match; + + std::shared_ptr<XdsListenerResource::FilterChainData> filter_chain_data; +}; + +TString FilterChain::FilterChainMatch::ToString() const { + y_absl::InlinedVector<TString, 8> contents; + if (destination_port != 0) { + contents.push_back(y_absl::StrCat("destination_port=", destination_port)); + } + if (!prefix_ranges.empty()) { + std::vector<TString> prefix_ranges_content; + for (const auto& range : prefix_ranges) { + prefix_ranges_content.push_back(range.ToString()); + } + contents.push_back(y_absl::StrCat( + "prefix_ranges={", y_absl::StrJoin(prefix_ranges_content, ", "), "}")); + } + if (source_type == XdsListenerResource::FilterChainMap::ConnectionSourceType:: + kSameIpOrLoopback) { + contents.push_back("source_type=SAME_IP_OR_LOOPBACK"); + } else if (source_type == XdsListenerResource::FilterChainMap:: + ConnectionSourceType::kExternal) { + contents.push_back("source_type=EXTERNAL"); + } + if (!source_prefix_ranges.empty()) { + std::vector<TString> source_prefix_ranges_content; + for (const auto& range : source_prefix_ranges) { + source_prefix_ranges_content.push_back(range.ToString()); + } + contents.push_back( + y_absl::StrCat("source_prefix_ranges={", + y_absl::StrJoin(source_prefix_ranges_content, ", "), "}")); + } + if (!source_ports.empty()) { + contents.push_back( + y_absl::StrCat("source_ports={", y_absl::StrJoin(source_ports, ", "), "}")); + } + if (!server_names.empty()) { + contents.push_back( + y_absl::StrCat("server_names={", y_absl::StrJoin(server_names, ", "), "}")); + } + if (!transport_protocol.empty()) { + contents.push_back(y_absl::StrCat("transport_protocol=", transport_protocol)); + } + if (!application_protocols.empty()) { + contents.push_back(y_absl::StrCat("application_protocols={", + y_absl::StrJoin(application_protocols, ", "), + "}")); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsListenerResource::FilterChainMap +// + +TString XdsListenerResource::FilterChainMap::ToString() const { + std::vector<TString> 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< + XdsListenerResource::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(y_absl::StrCat( + "{filter_chain_match=", filter_chain_match.ToString(), + ", filter_chain=", source_port_pair.second.data->ToString(), + "}")); + } + } + } + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsListenerResource +// + +TString XdsListenerResource::ToString() const { + y_absl::InlinedVector<TString, 4> contents; + if (type == ListenerType::kTcpListener) { + contents.push_back(y_absl::StrCat("address=", address)); + contents.push_back( + y_absl::StrCat("filter_chain_map=", filter_chain_map.ToString())); + if (default_filter_chain.has_value()) { + contents.push_back(y_absl::StrCat("default_filter_chain=", + default_filter_chain->ToString())); + } + } else if (type == ListenerType::kHttpApiListener) { + contents.push_back(y_absl::StrFormat("http_connection_manager=%s", + http_connection_manager.ToString())); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsListenerResourceType +// + +namespace { + +void MaybeLogHttpConnectionManager( + const XdsEncodingContext& context, + const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* + http_connection_manager_config) { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && + gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + const upb_msgdef* msg_type = + envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef( + context.symtab); + char buf[10240]; + upb_text_encode(http_connection_manager_config, msg_type, nullptr, 0, buf, + sizeof(buf)); + gpr_log(GPR_DEBUG, "[xds_client %p] HttpConnectionManager: %s", + context.client, buf); + } +} + +grpc_error_handle HttpConnectionManagerParse( + bool is_client, const XdsEncodingContext& context, + const envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager* + http_connection_manager_proto, + bool is_v2, + XdsListenerResource::HttpConnectionManager* http_connection_manager) { + MaybeLogHttpConnectionManager(context, http_connection_manager_proto); + // NACK a non-zero `xff_num_trusted_hops` and a `non-empty + // original_ip_detection_extensions` as mentioned in + // https://github.com/grpc/proposal/blob/master/A41-xds-rbac.md + if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_xff_num_trusted_hops( + http_connection_manager_proto) != 0) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "'xff_num_trusted_hops' must be zero"); + } + if (envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_has_original_ip_detection_extensions( + http_connection_manager_proto)) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "'original_ip_detection_extensions' must be empty"); + } + // 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 = + Duration::Parse(duration); + } + } + // Parse filters. + 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_proto, &num_filters); + std::set<y_absl::string_view> names_seen; + for (size_t i = 0; i < num_filters; ++i) { + const auto* http_filter = http_filters[i]; + y_absl::string_view name = UpbStringToAbsl( + envoy_extensions_filters_network_http_connection_manager_v3_HttpFilter_name( + http_filter)); + if (name.empty()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("empty filter name at index ", i)); + } + if (names_seen.find(name) != names_seen.end()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("duplicate HTTP filter name: ", name)); + } + 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_CPP_STRING( + y_absl::StrCat("no filter config specified for filter name ", name)); + } + y_absl::string_view 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 (is_optional) continue; + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("no filter registered for config type ", filter_type)); + } + if ((is_client && !filter_impl->IsSupportedOnClients()) || + (!is_client && !filter_impl->IsSupportedOnServers())) { + if (is_optional) continue; + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrFormat("Filter %s is not supported on %s", filter_type, + is_client ? "clients" : "servers")); + } + y_absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config = + filter_impl->GenerateFilterConfig(google_protobuf_Any_value(any), + context.arena); + if (!filter_config.ok()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( + "filter config for type ", filter_type, + " failed to parse: ", StatusToString(filter_config.status()))); + } + http_connection_manager->http_filters.emplace_back( + XdsListenerResource::HttpConnectionManager::HttpFilter{ + TString(name), std::move(*filter_config)}); + } + if (http_connection_manager->http_filters.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Expected at least one HTTP filter"); + } + // Make sure that the last filter is terminal and non-last filters are + // non-terminal. Note that this check is being performed in a separate loop + // to take care of the case where there are two terminal filters in the list + // out of which only one gets added in the final list. + for (const auto& http_filter : http_connection_manager->http_filters) { + const XdsHttpFilterImpl* filter_impl = + XdsHttpFilterRegistry::GetFilterForType( + http_filter.config.config_proto_type_name); + if (&http_filter != &http_connection_manager->http_filters.back()) { + // Filters before the last filter must not be terminal. + if (filter_impl->IsTerminalFilter()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("terminal filter for config type ", + http_filter.config.config_proto_type_name, + " must be the last filter in the chain")); + } + } else { + // The last filter must be terminal. + if (!filter_impl->IsTerminalFilter()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("non-terminal filter for config type ", + http_filter.config.config_proto_type_name, + " is the last filter in the chain")); + } + } + } + } 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( + XdsListenerResource::HttpConnectionManager::HttpFilter{ + "router", {kXdsHttpRouterFilterConfigName, Json()}}); + } + // Guarding parsing of RouteConfig on the server side with the environmental + // variable since that's the first feature on the server side that will be + // using this. + if (is_client || XdsRbacEnabled()) { + // 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); + XdsRouteConfigResource rds_update; + grpc_error_handle error = + XdsRouteConfigResource::Parse(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)); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle LdsResourceParseClient( + const XdsEncodingContext& context, + const envoy_config_listener_v3_ApiListener* api_listener, bool is_v2, + XdsListenerResource* lds_update) { + lds_update->type = XdsListenerResource::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 HttpConnectionManagerParse(true /* is_client */, context, + http_connection_manager, is_v2, + &lds_update->http_connection_manager); +} + +grpc_error_handle DownstreamTlsContextParse( + const XdsEncodingContext& context, + const envoy_config_core_v3_TransportSocket* transport_socket, + XdsListenerResource::DownstreamTlsContext* downstream_tls_context) { + y_absl::string_view name = UpbStringToAbsl( + envoy_config_core_v3_TransportSocket_name(transport_socket)); + if (name != "envoy.transport_sockets.tls") { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Unrecognized transport socket: ", name)); + } + auto* typed_config = + envoy_config_core_v3_TransportSocket_typed_config(transport_socket); + std::vector<grpc_error_handle> errors; + if (typed_config != nullptr) { + const upb_strview encoded_downstream_tls_context = + google_protobuf_Any_value(typed_config); + auto* downstream_tls_context_proto = + envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_parse( + encoded_downstream_tls_context.data, + encoded_downstream_tls_context.size, context.arena); + if (downstream_tls_context_proto == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Can't decode downstream tls context."); + } + auto* common_tls_context = + envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_common_tls_context( + downstream_tls_context_proto); + if (common_tls_context != nullptr) { + grpc_error_handle error = + CommonTlsContext::Parse(context, common_tls_context, + &downstream_tls_context->common_tls_context); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + auto* require_client_certificate = + envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_require_client_certificate( + downstream_tls_context_proto); + if (require_client_certificate != nullptr) { + downstream_tls_context->require_client_certificate = + google_protobuf_BoolValue_value(require_client_certificate); + } + auto* require_sni = + envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_require_sni( + downstream_tls_context_proto); + if (require_sni != nullptr && + google_protobuf_BoolValue_value(require_sni)) { + errors.push_back( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("require_sni: unsupported")); + } + if (envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_ocsp_staple_policy( + downstream_tls_context_proto) != + envoy_extensions_transport_sockets_tls_v3_DownstreamTlsContext_LENIENT_STAPLING) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "ocsp_staple_policy: Only LENIENT_STAPLING supported")); + } + } + if (downstream_tls_context->common_tls_context + .tls_certificate_provider_instance.instance_name.empty()) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "TLS configuration provided but no " + "tls_certificate_provider_instance found.")); + } + if (downstream_tls_context->require_client_certificate && + downstream_tls_context->common_tls_context.certificate_validation_context + .ca_certificate_provider_instance.instance_name.empty()) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "TLS configuration requires client certificates but no certificate " + "provider instance specified for validation.")); + } + if (!downstream_tls_context->common_tls_context.certificate_validation_context + .match_subject_alt_names.empty()) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "match_subject_alt_names not supported on servers")); + } + return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing DownstreamTlsContext", + &errors); +} + +grpc_error_handle CidrRangeParse( + const envoy_config_core_v3_CidrRange* cidr_range_proto, + XdsListenerResource::FilterChainMap::CidrRange* cidr_range) { + TString 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<const grpc_sockaddr*>(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++) { + XdsListenerResource::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<XdsListenerResource::FilterChainMap::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++) { + XdsListenerResource::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 XdsEncodingContext& context, + const envoy_config_listener_v3_FilterChain* filter_chain_proto, bool is_v2, + FilterChain* filter_chain) { + std::vector<grpc_error_handle> errors; + auto* filter_chain_match = + envoy_config_listener_v3_FilterChain_filter_chain_match( + filter_chain_proto); + if (filter_chain_match != nullptr) { + grpc_error_handle error = FilterChainMatchParse( + filter_chain_match, &filter_chain->filter_chain_match); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + filter_chain->filter_chain_data = + std::make_shared<XdsListenerResource::FilterChainData>(); + // 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) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "FilterChain should have exactly one filter: HttpConnectionManager; no " + "other filter is supported at the moment")); + } else { + auto* typed_config = + envoy_config_listener_v3_Filter_typed_config(filters[0]); + if (typed_config == nullptr) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No typed_config found in filter.")); + } else { + y_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") { + errors.push_back(GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Unsupported filter type ", type_url))); + } else { + 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) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Could not parse HttpConnectionManager config from filter " + "typed_config")); + } else { + grpc_error_handle error = HttpConnectionManagerParse( + false /* is_client */, context, http_connection_manager, is_v2, + &filter_chain->filter_chain_data->http_connection_manager); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + } + } + } + auto* transport_socket = + envoy_config_listener_v3_FilterChain_transport_socket(filter_chain_proto); + if (transport_socket != nullptr) { + grpc_error_handle error = DownstreamTlsContextParse( + context, transport_socket, + &filter_chain->filter_chain_data->downstream_tls_context); + if (error != GRPC_ERROR_NONE) errors.push_back(error); + } + return GRPC_ERROR_CREATE_FROM_VECTOR("Error parsing FilterChain", &errors); +} + +grpc_error_handle AddressParse( + const envoy_config_core_v3_Address* address_proto, TString* address) { + const auto* socket_address = + envoy_config_core_v3_Address_socket_address(address_proto); + if (socket_address == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_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; +} + +// 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 +// XdsListenerResource::FilterChainMap +struct InternalFilterChainMap { + using SourceIpMap = + std::map<TString, XdsListenerResource::FilterChainMap::SourceIp>; + using ConnectionSourceTypesArray = std::array<SourceIpMap, 3>; + struct DestinationIp { + y_absl::optional<XdsListenerResource::FilterChainMap::CidrRange> prefix_range; + bool transport_protocol_raw_buffer_provided = false; + ConnectionSourceTypesArray source_types_array; + }; + using DestinationIpMap = std::map<TString, DestinationIp>; + DestinationIpMap destination_ip_map; +}; + +grpc_error_handle AddFilterChainDataForSourcePort( + const FilterChain& filter_chain, + XdsListenerResource::FilterChainMap::SourcePortsMap* ports_map, + uint32_t port) { + auto insert_result = ports_map->emplace( + port, XdsListenerResource::FilterChainMap::FilterChainDataSharedPtr{ + filter_chain.filter_chain_data}); + if (!insert_result.second) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( + "Duplicate matching rules detected when adding filter chain: ", + filter_chain.filter_chain_match.ToString())); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle AddFilterChainDataForSourcePorts( + const FilterChain& filter_chain, + XdsListenerResource::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( + "", XdsListenerResource::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( + y_absl::StrCat(grpc_sockaddr_to_string(&prefix_range.address, false), + "/", prefix_range.prefix_len), + XdsListenerResource::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<unsigned int>( + filter_chain.filter_chain_match.source_type) < 3); + return AddFilterChainDataForSourceIpRange( + filter_chain, &destination_ip->source_types_array[static_cast<int>( + 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 TString& 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( + y_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; +} + +XdsListenerResource::FilterChainMap BuildFromInternalFilterChainMap( + InternalFilterChainMap* internal_filter_chain_map) { + XdsListenerResource::FilterChainMap filter_chain_map; + for (auto& destination_ip_pair : + internal_filter_chain_map->destination_ip_map) { + XdsListenerResource::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<FilterChain>& filter_chains, + XdsListenerResource::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 LdsResourceParseServer( + const XdsEncodingContext& context, + const envoy_config_listener_v3_Listener* listener, bool is_v2, + XdsListenerResource* lds_update) { + lds_update->type = XdsListenerResource::ListenerType::kTcpListener; + 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); + std::vector<FilterChain> parsed_filter_chains; + parsed_filter_chains.reserve(size); + for (size_t i = 0; i < size; i++) { + 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) { + 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) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No filter chain provided."); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle LdsResourceParse( + const XdsEncodingContext& context, + const envoy_config_listener_v3_Listener* listener, bool is_v2, + XdsListenerResource* lds_update) { + // 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); + const envoy_config_core_v3_Address* address = + envoy_config_listener_v3_Listener_address(listener); + if (api_listener != nullptr && address != nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Listener has both address and ApiListener"); + } + if (api_listener == nullptr && address == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Listener has neither address nor ApiListener"); + } + // Validate Listener fields. + grpc_error_handle error = GRPC_ERROR_NONE; + if (api_listener != nullptr) { + error = LdsResourceParseClient(context, api_listener, is_v2, lds_update); + } else { + error = LdsResourceParseServer(context, listener, is_v2, lds_update); + } + return error; +} + +void MaybeLogListener(const XdsEncodingContext& context, + const envoy_config_listener_v3_Listener* listener) { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && + gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + const upb_msgdef* msg_type = + envoy_config_listener_v3_Listener_getmsgdef(context.symtab); + char buf[10240]; + upb_text_encode(listener, msg_type, nullptr, 0, buf, sizeof(buf)); + gpr_log(GPR_DEBUG, "[xds_client %p] Listener: %s", context.client, buf); + } +} + +} // namespace + +y_absl::StatusOr<XdsResourceType::DecodeResult> XdsListenerResourceType::Decode( + const XdsEncodingContext& context, y_absl::string_view serialized_resource, + bool is_v2) const { + // Parse serialized proto. + auto* resource = envoy_config_listener_v3_Listener_parse( + serialized_resource.data(), serialized_resource.size(), context.arena); + if (resource == nullptr) { + return y_absl::InvalidArgumentError("Can't parse Listener resource."); + } + MaybeLogListener(context, resource); + // Validate resource. + DecodeResult result; + result.name = + UpbStringToStdString(envoy_config_listener_v3_Listener_name(resource)); + auto listener_data = y_absl::make_unique<ResourceDataSubclass>(); + grpc_error_handle error = + LdsResourceParse(context, resource, is_v2, &listener_data->resource); + if (error != GRPC_ERROR_NONE) { + TString error_str = grpc_error_std_string(error); + GRPC_ERROR_UNREF(error); + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_ERROR, "[xds_client %p] invalid Listener %s: %s", + context.client, result.name.c_str(), error_str.c_str()); + } + result.resource = y_absl::InvalidArgumentError(error_str); + } else { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_INFO, "[xds_client %p] parsed Listener %s: %s", + context.client, result.name.c_str(), + listener_data->resource.ToString().c_str()); + } + result.resource = std::move(listener_data); + } + return std::move(result); +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_listener.h b/contrib/libs/grpc/src/core/ext/xds/xds_listener.h new file mode 100644 index 0000000000..52e49390cf --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_listener.h @@ -0,0 +1,220 @@ +// +// 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_XDS_XDS_LISTENER_H +#define GRPC_CORE_EXT_XDS_XDS_LISTENER_H + +#include <grpc/support/port_platform.h> + +#include <array> +#include <map> +#include <util/generic/string.h> +#include <vector> + +#include "y_absl/status/statusor.h" +#include "y_absl/strings/string_view.h" +#include "y_absl/types/optional.h" +#include "envoy/config/listener/v3/listener.upbdefs.h" +#include "envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.h" + +#include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_common_types.h" +#include "src/core/ext/xds/xds_http_filters.h" +#include "src/core/ext/xds/xds_resource_type_impl.h" +#include "src/core/ext/xds/xds_route_config.h" + +namespace grpc_core { + +// TODO(roth): When we can use y_absl::variant<>, consider using that +// here, to enforce the fact that only one of the two fields can be set. +struct XdsListenerResource { + struct DownstreamTlsContext { + CommonTlsContext common_tls_context; + bool require_client_certificate = false; + + bool operator==(const DownstreamTlsContext& other) const { + return common_tls_context == other.common_tls_context && + require_client_certificate == other.require_client_certificate; + } + + TString ToString() const; + bool Empty() const; + }; + + enum class ListenerType { + kTcpListener = 0, + kHttpApiListener, + } type; + + struct HttpConnectionManager { + // The name to use in the RDS request. + TString 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. + y_absl::optional<XdsRouteConfigResource> rds_update; + + struct HttpFilter { + TString name; + XdsHttpFilterImpl::FilterConfig config; + + bool operator==(const HttpFilter& other) const { + return name == other.name && config == other.config; + } + + TString ToString() const; + }; + std::vector<HttpFilter> 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; + } + + TString ToString() const; + }; + + // Populated for type=kHttpApiListener. + HttpConnectionManager http_connection_manager; + + // Populated for type=kTcpListener. + // host:port listening_address set when type is kTcpListener + TString 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 FilterChainData& other) const { + return downstream_tls_context == other.downstream_tls_context && + http_connection_manager == other.http_connection_manager; + } + + TString ToString() const; + }; + + // 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<FilterChainData> 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; + } + + TString ToString() const; + }; + using SourcePortsMap = std::map<uint16_t, FilterChainDataSharedPtr>; + struct SourceIp { + y_absl::optional<CidrRange> 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<SourceIp>; + enum class ConnectionSourceType { kAny = 0, kSameIpOrLoopback, kExternal }; + using ConnectionSourceTypesArray = std::array<SourceIpVector, 3>; + struct DestinationIp { + y_absl::optional<CidrRange> 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<DestinationIp>; + DestinationIpVector destination_ip_vector; + + bool operator==(const FilterChainMap& other) const { + return destination_ip_vector == other.destination_ip_vector; + } + + TString ToString() const; + } filter_chain_map; + + y_absl::optional<FilterChainData> default_filter_chain; + + bool operator==(const XdsListenerResource& other) const { + 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; + } + + TString ToString() const; +}; + +class XdsListenerResourceType + : public XdsResourceTypeImpl<XdsListenerResourceType, XdsListenerResource> { + public: + y_absl::string_view type_url() const override { + return "envoy.config.listener.v3.Listener"; + } + y_absl::string_view v2_type_url() const override { + return "envoy.api.v2.Listener"; + } + + y_absl::StatusOr<DecodeResult> Decode(const XdsEncodingContext& context, + y_absl::string_view serialized_resource, + bool is_v2) const override; + + bool AllResourcesRequiredInSotW() const override { return true; } + + void InitUpbSymtab(upb_symtab* symtab) const override { + envoy_config_listener_v3_Listener_getmsgdef(symtab); + envoy_extensions_filters_network_http_connection_manager_v3_HttpConnectionManager_getmsgdef( + symtab); + XdsHttpFilterRegistry::PopulateSymtab(symtab); + } +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_LISTENER_H diff --git a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.h b/contrib/libs/grpc/src/core/ext/xds/xds_resource_type.cc index a1c9baa476..a9264ccb77 100644 --- a/contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.h +++ b/contrib/libs/grpc/src/core/ext/xds/xds_resource_type.cc @@ -1,3 +1,4 @@ +// // Copyright 2021 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -11,20 +12,22 @@ // 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_TRANSPORT_CHTTP2_TRANSPORT_HPACK_UTILS_H -#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_UTILS_H +// #include <grpc/support/port_platform.h> -#include "src/core/lib/transport/metadata.h" +#include "src/core/ext/xds/xds_resource_type.h" namespace grpc_core { -// Return the size occupied by some metadata in the HPACK table. -size_t MetadataSizeInHPackTable(grpc_mdelem elem, - bool use_true_binary_metadata); +bool XdsResourceType::IsType(y_absl::string_view resource_type, + bool* is_v2) const { + if (resource_type == type_url()) return true; + if (resource_type == v2_type_url()) { + if (is_v2 != nullptr) *is_v2 = true; + return true; + } + return false; +} } // namespace grpc_core - -#endif // GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_UTILS_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_resource_type.h b/contrib/libs/grpc/src/core/ext/xds/xds_resource_type.h new file mode 100644 index 0000000000..551354f108 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_resource_type.h @@ -0,0 +1,98 @@ +// +// 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 <grpc/support/port_platform.h> + +#include <memory> +#include <util/generic/string.h> + +#include "y_absl/status/statusor.h" +#include "y_absl/strings/string_view.h" + +#include "src/core/ext/xds/upb_utils.h" + +#ifndef GRPC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_H +#define GRPC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_H + +namespace grpc_core { + +// Interface for an xDS resource type. +// Used to inject type-specific logic into XdsClient. +class XdsResourceType { + public: + // A base type for resource data. + // Subclasses will extend this, and their DecodeResults will be + // downcastable to their extended type. + struct ResourceData { + virtual ~ResourceData() = default; + }; + + // Result returned by Decode(). + struct DecodeResult { + TString name; + y_absl::StatusOr<std::unique_ptr<ResourceData>> resource; + }; + + virtual ~XdsResourceType() = default; + + // Returns v3 resource type. + virtual y_absl::string_view type_url() const = 0; + + // Returns v2 resource type. + virtual y_absl::string_view v2_type_url() const = 0; + + // Decodes and validates a serialized resource proto. + // If the resource fails protobuf deserialization, returns non-OK status. + // If the deserialized resource fails validation, returns a DecodeResult + // whose resource field is set to a non-OK status. + // Otherwise, returns a DecodeResult with a valid resource. + virtual y_absl::StatusOr<DecodeResult> Decode( + const XdsEncodingContext& context, y_absl::string_view serialized_resource, + bool is_v2) const = 0; + + // Returns true if r1 and r2 are equal. + // Must be invoked only on resources returned by this object's Decode() + // method. + virtual bool ResourcesEqual(const ResourceData* r1, + const ResourceData* r2) const = 0; + + // Returns a copy of resource. + // Must be invoked only on resources returned by this object's Decode() + // method. + virtual std::unique_ptr<ResourceData> CopyResource( + const ResourceData* resource) const = 0; + + // Indicates whether the resource type requires that all resources must + // be present in every SotW response from the server. If true, a + // response that does not include a previously seen resource will be + // interpreted as a deletion of that resource. + virtual bool AllResourcesRequiredInSotW() const { return false; } + + // Populate upb symtab with xDS proto messages that we want to print + // properly in logs. + // Note: This won't actually work properly until upb adds support for + // Any fields in textproto printing (internal b/178821188). + virtual void InitUpbSymtab(upb_symtab* symtab) const = 0; + + // Convenience method for checking if resource_type matches this type. + // Checks against both type_url() and v2_type_url(). + // If is_v2 is non-null, it will be set to true if matching v2_type_url(). + bool IsType(y_absl::string_view resource_type, bool* is_v2) const; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_resource_type_impl.h b/contrib/libs/grpc/src/core/ext/xds/xds_resource_type_impl.h new file mode 100644 index 0000000000..b259449a26 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_resource_type_impl.h @@ -0,0 +1,87 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_resource_type.h" + +#ifndef GRPC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_IMPL_H +#define GRPC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_IMPL_H + +namespace grpc_core { + +// Base class for XdsResourceType implementations. +// Handles all down-casting logic for a particular resource type struct. +template <typename Subclass, typename ResourceTypeStruct> +class XdsResourceTypeImpl : public XdsResourceType { + public: + struct ResourceDataSubclass : public ResourceData { + ResourceTypeStruct resource; + }; + + // XdsClient watcher that handles down-casting. + class WatcherInterface : public XdsClient::ResourceWatcherInterface { + public: + virtual void OnResourceChanged(ResourceTypeStruct listener) = 0; + + private: + // Get result from XdsClient generic watcher interface, perform + // down-casting, and invoke the caller's OnListenerChanged() method. + void OnGenericResourceChanged( + const XdsResourceType::ResourceData* resource) override { + OnResourceChanged( + static_cast<const ResourceDataSubclass*>(resource)->resource); + } + }; + + static const Subclass* Get() { + static const Subclass* g_instance = new Subclass(); + return g_instance; + } + + // Convenient wrappers around XdsClient generic watcher API that provide + // type-safety. + static void StartWatch(XdsClient* xds_client, y_absl::string_view resource_name, + RefCountedPtr<WatcherInterface> watcher) { + xds_client->WatchResource(Get(), resource_name, std::move(watcher)); + } + static void CancelWatch(XdsClient* xds_client, + y_absl::string_view resource_name, + WatcherInterface* watcher, + bool delay_unsubscription = false) { + xds_client->CancelResourceWatch(Get(), resource_name, watcher, + delay_unsubscription); + } + + bool ResourcesEqual(const ResourceData* r1, + const ResourceData* r2) const override { + return static_cast<const ResourceDataSubclass*>(r1)->resource == + static_cast<const ResourceDataSubclass*>(r2)->resource; + } + + std::unique_ptr<ResourceData> CopyResource( + const ResourceData* resource) const override { + auto* resource_copy = new ResourceDataSubclass(); + resource_copy->resource = + static_cast<const ResourceDataSubclass*>(resource)->resource; + return std::unique_ptr<ResourceData>(resource_copy); + } +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_RESOURCE_TYPE_IMPL_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_route_config.cc b/contrib/libs/grpc/src/core/ext/xds/xds_route_config.cc new file mode 100644 index 0000000000..19614d39e9 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_route_config.cc @@ -0,0 +1,993 @@ +// +// 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 <grpc/support/port_platform.h> + +#include "y_absl/memory/memory.h" +#include "y_absl/strings/str_cat.h" +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_join.h" +#include "y_absl/strings/str_split.h" +#include "y_absl/strings/string_view.h" +#include "envoy/config/core/v3/base.upb.h" +#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/type/matcher/v3/regex.upb.h" +#include "envoy/type/matcher/v3/string.upb.h" +#include "envoy/type/v3/percent.upb.h" +#include "envoy/type/v3/range.upb.h" +#include "google/protobuf/any.upb.h" +#include "google/protobuf/wrappers.upb.h" +#include "upb/text_encode.h" +#include "upb/upb.h" +#include "upb/upb.hpp" + +#include "src/core/ext/xds/upb_utils.h" +#include "src/core/ext/xds/xds_api.h" +#include "src/core/ext/xds/xds_common_types.h" +#include "src/core/ext/xds/xds_resource_type.h" +#include "src/core/ext/xds/xds_routing.h" +#include "src/core/lib/gpr/env.h" +#include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/error.h" + +namespace grpc_core { + +// TODO(yashykt): Remove once RBAC is no longer experimental +bool XdsRbacEnabled() { + char* value = gpr_getenv("GRPC_XDS_EXPERIMENTAL_RBAC"); + bool parsed_value; + bool parse_succeeded = gpr_parse_bool_value(value, &parsed_value); + gpr_free(value); + return parse_succeeded && parsed_value; +} + +// +// XdsRouteConfigResource::RetryPolicy +// + +TString XdsRouteConfigResource::RetryPolicy::RetryBackOff::ToString() + const { + std::vector<TString> contents; + contents.push_back( + y_absl::StrCat("RetryBackOff Base: ", base_interval.ToString())); + contents.push_back( + y_absl::StrCat("RetryBackOff max: ", max_interval.ToString())); + return y_absl::StrJoin(contents, ","); +} + +TString XdsRouteConfigResource::RetryPolicy::ToString() const { + std::vector<TString> contents; + contents.push_back(y_absl::StrFormat("num_retries=%d", num_retries)); + contents.push_back(retry_back_off.ToString()); + return y_absl::StrCat("{", y_absl::StrJoin(contents, ","), "}"); +} + +// +// XdsRouteConfigResource::Route::Matchers +// + +TString XdsRouteConfigResource::Route::Matchers::ToString() const { + std::vector<TString> contents; + contents.push_back( + y_absl::StrFormat("PathMatcher{%s}", path_matcher.ToString())); + for (const HeaderMatcher& header_matcher : header_matchers) { + contents.push_back(header_matcher.ToString()); + } + if (fraction_per_million.has_value()) { + contents.push_back(y_absl::StrFormat("Fraction Per Million %d", + fraction_per_million.value())); + } + return y_absl::StrJoin(contents, "\n"); +} + +// +// XdsRouteConfigResource::Route::RouteAction::HashPolicy +// + +XdsRouteConfigResource::Route::RouteAction::HashPolicy::HashPolicy( + const HashPolicy& other) + : type(other.type), + header_name(other.header_name), + regex_substitution(other.regex_substitution) { + if (other.regex != nullptr) { + regex = + y_absl::make_unique<RE2>(other.regex->pattern(), other.regex->options()); + } +} + +XdsRouteConfigResource::Route::RouteAction::HashPolicy& +XdsRouteConfigResource::Route::RouteAction::HashPolicy::operator=( + const HashPolicy& other) { + type = other.type; + header_name = other.header_name; + if (other.regex != nullptr) { + regex = + y_absl::make_unique<RE2>(other.regex->pattern(), other.regex->options()); + } + regex_substitution = other.regex_substitution; + return *this; +} + +XdsRouteConfigResource::Route::RouteAction::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)) {} + +XdsRouteConfigResource::Route::RouteAction::HashPolicy& +XdsRouteConfigResource::Route::RouteAction::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 XdsRouteConfigResource::Route::RouteAction::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; +} + +TString XdsRouteConfigResource::Route::RouteAction::HashPolicy::ToString() + const { + std::vector<TString> 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( + y_absl::StrFormat("terminal=%s", terminal ? "true" : "false")); + if (type == Type::HEADER) { + contents.push_back(y_absl::StrFormat( + "Header %s:/%s/%s", header_name, + (regex == nullptr) ? "" : regex->pattern(), regex_substitution)); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsRouteConfigResource::Route::RouteAction::ClusterWeight +// + +TString +XdsRouteConfigResource::Route::RouteAction::ClusterWeight::ToString() const { + std::vector<TString> contents; + contents.push_back(y_absl::StrCat("cluster=", name)); + contents.push_back(y_absl::StrCat("weight=", weight)); + if (!typed_per_filter_config.empty()) { + std::vector<TString> parts; + for (const auto& p : typed_per_filter_config) { + const TString& key = p.first; + const auto& config = p.second; + parts.push_back(y_absl::StrCat(key, "=", config.ToString())); + } + contents.push_back(y_absl::StrCat("typed_per_filter_config={", + y_absl::StrJoin(parts, ", "), "}")); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsRouteConfigResource::Route::RouteAction +// + +TString XdsRouteConfigResource::Route::RouteAction::ToString() const { + std::vector<TString> contents; + for (const HashPolicy& hash_policy : hash_policies) { + contents.push_back(y_absl::StrCat("hash_policy=", hash_policy.ToString())); + } + if (retry_policy.has_value()) { + contents.push_back(y_absl::StrCat("retry_policy=", retry_policy->ToString())); + } + if (!cluster_name.empty()) { + contents.push_back(y_absl::StrFormat("Cluster name: %s", cluster_name)); + } + for (const ClusterWeight& cluster_weight : weighted_clusters) { + contents.push_back(cluster_weight.ToString()); + } + if (max_stream_duration.has_value()) { + contents.push_back(max_stream_duration->ToString()); + } + return y_absl::StrCat("{", y_absl::StrJoin(contents, ", "), "}"); +} + +// +// XdsRouteConfigResource::Route +// + +TString XdsRouteConfigResource::Route::ToString() const { + std::vector<TString> contents; + contents.push_back(matchers.ToString()); + auto* route_action = + y_absl::get_if<XdsRouteConfigResource::Route::RouteAction>(&action); + if (route_action != nullptr) { + contents.push_back(y_absl::StrCat("route=", route_action->ToString())); + } else if (y_absl::holds_alternative< + XdsRouteConfigResource::Route::NonForwardingAction>(action)) { + contents.push_back("non_forwarding_action={}"); + } else { + contents.push_back("unknown_action={}"); + } + if (!typed_per_filter_config.empty()) { + contents.push_back("typed_per_filter_config={"); + for (const auto& p : typed_per_filter_config) { + const TString& name = p.first; + const auto& config = p.second; + contents.push_back(y_absl::StrCat(" ", name, "=", config.ToString())); + } + contents.push_back("}"); + } + return y_absl::StrJoin(contents, "\n"); +} + +// +// XdsRouteConfigResource +// + +TString XdsRouteConfigResource::ToString() const { + std::vector<TString> vhosts; + for (const VirtualHost& vhost : virtual_hosts) { + vhosts.push_back( + y_absl::StrCat("vhost={\n" + " domains=[", + y_absl::StrJoin(vhost.domains, ", "), + "]\n" + " routes=[\n")); + for (const XdsRouteConfigResource::Route& route : vhost.routes) { + vhosts.push_back(" {\n"); + vhosts.push_back(route.ToString()); + vhosts.push_back("\n }\n"); + } + vhosts.push_back(" ]\n"); + vhosts.push_back(" typed_per_filter_config={\n"); + for (const auto& p : vhost.typed_per_filter_config) { + const TString& name = p.first; + const auto& config = p.second; + vhosts.push_back( + y_absl::StrCat(" ", name, "=", config.ToString(), "\n")); + } + vhosts.push_back(" }\n"); + vhosts.push_back("]\n"); + } + return y_absl::StrJoin(vhosts, ""); +} + +namespace { + +grpc_error_handle RoutePathMatchParse( + const envoy_config_route_v3_RouteMatch* match, + XdsRouteConfigResource::Route* route, bool* ignore_route) { + auto* case_sensitive_ptr = + envoy_config_route_v3_RouteMatch_case_sensitive(match); + bool case_sensitive = true; + if (case_sensitive_ptr != nullptr) { + case_sensitive = google_protobuf_BoolValue_value(case_sensitive_ptr); + } + StringMatcher::Type type; + TString match_string; + if (envoy_config_route_v3_RouteMatch_has_prefix(match)) { + y_absl::string_view prefix = + UpbStringToAbsl(envoy_config_route_v3_RouteMatch_prefix(match)); + // Empty prefix "" is accepted. + if (!prefix.empty()) { + // Prefix "/" is accepted. + if (prefix[0] != '/') { + // Prefix which does not start with a / will never match anything, so + // ignore this route. + *ignore_route = true; + return GRPC_ERROR_NONE; + } + std::vector<y_absl::string_view> prefix_elements = + y_absl::StrSplit(prefix.substr(1), y_absl::MaxSplits('/', 2)); + if (prefix_elements.size() > 2) { + // Prefix cannot have more than 2 slashes. + *ignore_route = true; + return GRPC_ERROR_NONE; + } else if (prefix_elements.size() == 2 && prefix_elements[0].empty()) { + // Prefix contains empty string between the 2 slashes + *ignore_route = true; + return GRPC_ERROR_NONE; + } + } + type = StringMatcher::Type::kPrefix; + match_string = TString(prefix); + } else if (envoy_config_route_v3_RouteMatch_has_path(match)) { + y_absl::string_view path = + UpbStringToAbsl(envoy_config_route_v3_RouteMatch_path(match)); + if (path.empty()) { + // Path that is empty will never match anything, so ignore this route. + *ignore_route = true; + return GRPC_ERROR_NONE; + } + if (path[0] != '/') { + // Path which does not start with a / will never match anything, so + // ignore this route. + *ignore_route = true; + return GRPC_ERROR_NONE; + } + std::vector<y_absl::string_view> path_elements = + y_absl::StrSplit(path.substr(1), y_absl::MaxSplits('/', 2)); + if (path_elements.size() != 2) { + // Path not in the required format of /service/method will never match + // anything, so ignore this route. + *ignore_route = true; + return GRPC_ERROR_NONE; + } else if (path_elements[0].empty()) { + // Path contains empty service name will never match anything, so ignore + // this route. + *ignore_route = true; + return GRPC_ERROR_NONE; + } else if (path_elements[1].empty()) { + // Path contains empty method name will never match anything, so ignore + // this route. + *ignore_route = true; + return GRPC_ERROR_NONE; + } + type = StringMatcher::Type::kExact; + match_string = TString(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::kSafeRegex; + match_string = UpbStringToStdString( + envoy_type_matcher_v3_RegexMatcher_regex(regex_matcher)); + } else { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid route path specifier specified."); + } + y_absl::StatusOr<StringMatcher> string_matcher = + StringMatcher::Create(type, match_string, case_sensitive); + if (!string_matcher.ok()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("path matcher: ", string_matcher.status().message())); + } + route->matchers.path_matcher = std::move(string_matcher.value()); + return GRPC_ERROR_NONE; +} + +grpc_error_handle RouteHeaderMatchersParse( + const envoy_config_route_v3_RouteMatch* match, + XdsRouteConfigResource::Route* route) { + size_t size; + const envoy_config_route_v3_HeaderMatcher* const* headers = + envoy_config_route_v3_RouteMatch_headers(match, &size); + for (size_t i = 0; i < size; ++i) { + const envoy_config_route_v3_HeaderMatcher* header = headers[i]; + const TString name = + UpbStringToStdString(envoy_config_route_v3_HeaderMatcher_name(header)); + HeaderMatcher::Type type; + TString match_string; + int64_t range_start = 0; + int64_t range_end = 0; + bool present_match = false; + if (envoy_config_route_v3_HeaderMatcher_has_exact_match(header)) { + 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( + header)) { + 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::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::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::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::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::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::kContains; + match_string = UpbStringToStdString( + envoy_config_route_v3_HeaderMatcher_contains_match(header)); + } else { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Invalid route header matcher specified."); + } + bool invert_match = + envoy_config_route_v3_HeaderMatcher_invert_match(header); + y_absl::StatusOr<HeaderMatcher> header_matcher = + HeaderMatcher::Create(name, type, match_string, range_start, range_end, + present_match, invert_match); + if (!header_matcher.ok()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("header matcher: ", header_matcher.status().message())); + } + route->matchers.header_matchers.emplace_back( + std::move(header_matcher.value())); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle RouteRuntimeFractionParse( + const envoy_config_route_v3_RouteMatch* match, + XdsRouteConfigResource::Route* route) { + const envoy_config_core_v3_RuntimeFractionalPercent* runtime_fraction = + envoy_config_route_v3_RouteMatch_runtime_fraction(match); + if (runtime_fraction != nullptr) { + const envoy_type_v3_FractionalPercent* fraction = + envoy_config_core_v3_RuntimeFractionalPercent_default_value( + runtime_fraction); + if (fraction != nullptr) { + uint32_t numerator = envoy_type_v3_FractionalPercent_numerator(fraction); + const auto denominator = + static_cast<envoy_type_v3_FractionalPercent_DenominatorType>( + envoy_type_v3_FractionalPercent_denominator(fraction)); + // Normalize to million. + switch (denominator) { + case envoy_type_v3_FractionalPercent_HUNDRED: + numerator *= 10000; + break; + case envoy_type_v3_FractionalPercent_TEN_THOUSAND: + numerator *= 100; + break; + case envoy_type_v3_FractionalPercent_MILLION: + break; + default: + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "Unknown denominator type"); + } + route->matchers.fraction_per_million = numerator; + } + } + return GRPC_ERROR_NONE; +} + +template <typename ParentType, typename EntryType> +grpc_error_handle ParseTypedPerFilterConfig( + const XdsEncodingContext& context, const ParentType* parent, + const EntryType* (*entry_func)(const ParentType*, size_t*), + upb_strview (*key_func)(const EntryType*), + const google_protobuf_Any* (*value_func)(const EntryType*), + XdsRouteConfigResource::TypedPerFilterConfig* typed_per_filter_config) { + size_t filter_it = UPB_MAP_BEGIN; + while (true) { + const auto* filter_entry = entry_func(parent, &filter_it); + if (filter_entry == nullptr) break; + y_absl::string_view key = UpbStringToAbsl(key_func(filter_entry)); + if (key.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("empty filter name in map"); + } + const google_protobuf_Any* any = value_func(filter_entry); + GPR_ASSERT(any != nullptr); + y_absl::string_view filter_type = + UpbStringToAbsl(google_protobuf_Any_type_url(any)); + if (filter_type.empty()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("no filter config specified for filter name ", key)); + } + bool is_optional = false; + if (filter_type == + "type.googleapis.com/envoy.config.route.v3.FilterConfig") { + upb_strview any_value = google_protobuf_Any_value(any); + const auto* filter_config = envoy_config_route_v3_FilterConfig_parse( + any_value.data, any_value.size, context.arena); + if (filter_config == nullptr) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("could not parse FilterConfig wrapper for ", key)); + } + 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_CPP_STRING( + y_absl::StrCat("no filter config specified for filter name ", key)); + } + } + 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 (is_optional) continue; + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("no filter registered for config type ", filter_type)); + } + y_absl::StatusOr<XdsHttpFilterImpl::FilterConfig> filter_config = + filter_impl->GenerateFilterConfigOverride( + google_protobuf_Any_value(any), context.arena); + if (!filter_config.ok()) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( + "filter config for type ", filter_type, + " failed to parse: ", StatusToString(filter_config.status()))); + } + (*typed_per_filter_config)[TString(key)] = std::move(*filter_config); + } + return GRPC_ERROR_NONE; +} + +grpc_error_handle RetryPolicyParse( + const XdsEncodingContext& context, + const envoy_config_route_v3_RetryPolicy* retry_policy, + y_absl::optional<XdsRouteConfigResource::RetryPolicy>* retry) { + std::vector<grpc_error_handle> errors; + XdsRouteConfigResource::RetryPolicy retry_to_return; + auto retry_on = UpbStringToStdString( + envoy_config_route_v3_RetryPolicy_retry_on(retry_policy)); + std::vector<y_absl::string_view> codes = y_absl::StrSplit(retry_on, ','); + for (const auto& code : codes) { + if (code == "cancelled") { + retry_to_return.retry_on.Add(GRPC_STATUS_CANCELLED); + } else if (code == "deadline-exceeded") { + retry_to_return.retry_on.Add(GRPC_STATUS_DEADLINE_EXCEEDED); + } else if (code == "internal") { + retry_to_return.retry_on.Add(GRPC_STATUS_INTERNAL); + } else if (code == "resource-exhausted") { + retry_to_return.retry_on.Add(GRPC_STATUS_RESOURCE_EXHAUSTED); + } else if (code == "unavailable") { + retry_to_return.retry_on.Add(GRPC_STATUS_UNAVAILABLE); + } else { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_INFO, "Unsupported retry_on policy %s.", + TString(code).c_str()); + } + } + } + const google_protobuf_UInt32Value* num_retries = + envoy_config_route_v3_RetryPolicy_num_retries(retry_policy); + if (num_retries != nullptr) { + uint32_t num_retries_value = google_protobuf_UInt32Value_value(num_retries); + if (num_retries_value == 0) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction RetryPolicy num_retries set to invalid value 0.")); + } else { + retry_to_return.num_retries = num_retries_value; + } + } else { + retry_to_return.num_retries = 1; + } + const envoy_config_route_v3_RetryPolicy_RetryBackOff* backoff = + envoy_config_route_v3_RetryPolicy_retry_back_off(retry_policy); + if (backoff != nullptr) { + const google_protobuf_Duration* base_interval = + envoy_config_route_v3_RetryPolicy_RetryBackOff_base_interval(backoff); + if (base_interval == nullptr) { + errors.push_back(GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction RetryPolicy RetryBackoff missing base interval.")); + } else { + retry_to_return.retry_back_off.base_interval = + Duration::Parse(base_interval); + } + const google_protobuf_Duration* max_interval = + envoy_config_route_v3_RetryPolicy_RetryBackOff_max_interval(backoff); + Duration max; + if (max_interval != nullptr) { + max = Duration::Parse(max_interval); + } else { + // if max interval is not set, it is 10x the base, if the value in nanos + // can yield another second, adjust the value in seconds accordingly. + max.seconds = retry_to_return.retry_back_off.base_interval.seconds * 10; + max.nanos = retry_to_return.retry_back_off.base_interval.nanos * 10; + if (max.nanos > 1000000000) { + max.seconds += max.nanos / 1000000000; + max.nanos = max.nanos % 1000000000; + } + } + retry_to_return.retry_back_off.max_interval = max; + } else { + retry_to_return.retry_back_off.base_interval.seconds = 0; + retry_to_return.retry_back_off.base_interval.nanos = 25000000; + retry_to_return.retry_back_off.max_interval.seconds = 0; + retry_to_return.retry_back_off.max_interval.nanos = 250000000; + } + if (errors.empty()) { + *retry = retry_to_return; + return GRPC_ERROR_NONE; + } else { + return GRPC_ERROR_CREATE_FROM_VECTOR("errors parsing retry policy", + &errors); + } +} + +grpc_error_handle RouteActionParse( + const XdsEncodingContext& context, + const envoy_config_route_v3_Route* route_msg, + XdsRouteConfigResource::Route::RouteAction* route, bool* ignore_route) { + const envoy_config_route_v3_RouteAction* route_action = + envoy_config_route_v3_Route_route(route_msg); + // Get the cluster or weighted_clusters in the RouteAction. + if (envoy_config_route_v3_RouteAction_has_cluster(route_action)) { + route->cluster_name = UpbStringToStdString( + envoy_config_route_v3_RouteAction_cluster(route_action)); + if (route->cluster_name.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction cluster contains empty cluster name."); + } + } else if (envoy_config_route_v3_RouteAction_has_weighted_clusters( + route_action)) { + const envoy_config_route_v3_WeightedCluster* weighted_cluster = + envoy_config_route_v3_RouteAction_weighted_clusters(route_action); + uint32_t total_weight = 100; + const google_protobuf_UInt32Value* weight = + envoy_config_route_v3_WeightedCluster_total_weight(weighted_cluster); + if (weight != nullptr) { + total_weight = google_protobuf_UInt32Value_value(weight); + } + size_t clusters_size; + const envoy_config_route_v3_WeightedCluster_ClusterWeight* const* clusters = + envoy_config_route_v3_WeightedCluster_clusters(weighted_cluster, + &clusters_size); + uint32_t sum_of_weights = 0; + for (size_t j = 0; j < clusters_size; ++j) { + const envoy_config_route_v3_WeightedCluster_ClusterWeight* + cluster_weight = clusters[j]; + XdsRouteConfigResource::Route::RouteAction::ClusterWeight cluster; + cluster.name = UpbStringToStdString( + envoy_config_route_v3_WeightedCluster_ClusterWeight_name( + cluster_weight)); + if (cluster.name.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction weighted_cluster cluster contains empty cluster " + "name."); + } + const google_protobuf_UInt32Value* weight = + envoy_config_route_v3_WeightedCluster_ClusterWeight_weight( + cluster_weight); + if (weight == nullptr) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction weighted_cluster cluster missing weight"); + } + cluster.weight = google_protobuf_UInt32Value_value(weight); + if (cluster.weight == 0) continue; + sum_of_weights += cluster.weight; + 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, + envoy_config_route_v3_WeightedCluster_ClusterWeight_typed_per_filter_config_next, + envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_key, + envoy_config_route_v3_WeightedCluster_ClusterWeight_TypedPerFilterConfigEntry_value, + &cluster.typed_per_filter_config); + if (error != GRPC_ERROR_NONE) return error; + } + route->weighted_clusters.emplace_back(std::move(cluster)); + } + if (total_weight != sum_of_weights) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction weighted_cluster has incorrect total weight"); + } + if (route->weighted_clusters.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "RouteAction weighted_cluster has no valid clusters specified."); + } + } else { + // No cluster or weighted_clusters found in RouteAction, ignore this route. + *ignore_route = true; + } + if (!*ignore_route) { + const envoy_config_route_v3_RouteAction_MaxStreamDuration* + max_stream_duration = + envoy_config_route_v3_RouteAction_max_stream_duration(route_action); + if (max_stream_duration != nullptr) { + const google_protobuf_Duration* duration = + envoy_config_route_v3_RouteAction_MaxStreamDuration_grpc_timeout_header_max( + max_stream_duration); + if (duration == nullptr) { + duration = + envoy_config_route_v3_RouteAction_MaxStreamDuration_max_stream_duration( + max_stream_duration); + } + if (duration != nullptr) { + route->max_stream_duration = Duration::Parse(duration); + } + } + } + // Get HashPolicy from RouteAction + 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]; + XdsRouteConfigResource::Route::RouteAction::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 = + XdsRouteConfigResource::Route::RouteAction::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) { + 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 = y_absl::make_unique<RE2>( + 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) { + TString key = UpbStringToStdString( + envoy_config_route_v3_RouteAction_HashPolicy_FilterState_key( + filter_state)); + if (key == "io.grpc.channel_id") { + policy.type = XdsRouteConfigResource::Route::RouteAction::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)); + } + // Get retry policy + const envoy_config_route_v3_RetryPolicy* retry_policy = + envoy_config_route_v3_RouteAction_retry_policy(route_action); + if (retry_policy != nullptr) { + y_absl::optional<XdsRouteConfigResource::RetryPolicy> retry; + grpc_error_handle error = RetryPolicyParse(context, retry_policy, &retry); + if (error != GRPC_ERROR_NONE) return error; + route->retry_policy = retry; + } + return GRPC_ERROR_NONE; +} + +} // namespace + +grpc_error_handle XdsRouteConfigResource::Parse( + const XdsEncodingContext& context, + const envoy_config_route_v3_RouteConfiguration* route_config, + XdsRouteConfigResource* rds_update) { + // Get the virtual hosts. + size_t num_virtual_hosts; + const envoy_config_route_v3_VirtualHost* const* virtual_hosts = + envoy_config_route_v3_RouteConfiguration_virtual_hosts( + route_config, &num_virtual_hosts); + for (size_t i = 0; i < num_virtual_hosts; ++i) { + rds_update->virtual_hosts.emplace_back(); + XdsRouteConfigResource::VirtualHost& vhost = + rds_update->virtual_hosts.back(); + // Parse domains. + size_t domain_size; + upb_strview const* domains = envoy_config_route_v3_VirtualHost_domains( + virtual_hosts[i], &domain_size); + for (size_t j = 0; j < domain_size; ++j) { + TString domain_pattern = UpbStringToStdString(domains[j]); + if (!XdsRouting::IsValidDomainPattern(domain_pattern)) { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Invalid domain pattern \"", domain_pattern, "\".")); + } + vhost.domains.emplace_back(std::move(domain_pattern)); + } + if (vhost.domains.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("VirtualHost has no domains"); + } + // Parse typed_per_filter_config. + if (context.use_v3) { + grpc_error_handle error = ParseTypedPerFilterConfig< + envoy_config_route_v3_VirtualHost, + envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry>( + context, virtual_hosts[i], + envoy_config_route_v3_VirtualHost_typed_per_filter_config_next, + envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_key, + envoy_config_route_v3_VirtualHost_TypedPerFilterConfigEntry_value, + &vhost.typed_per_filter_config); + if (error != GRPC_ERROR_NONE) return error; + } + // Parse retry policy. + y_absl::optional<XdsRouteConfigResource::RetryPolicy> + virtual_host_retry_policy; + const envoy_config_route_v3_RetryPolicy* retry_policy = + envoy_config_route_v3_VirtualHost_retry_policy(virtual_hosts[i]); + if (retry_policy != nullptr) { + grpc_error_handle error = + RetryPolicyParse(context, retry_policy, &virtual_host_retry_policy); + if (error != GRPC_ERROR_NONE) return error; + } + // Parse routes. + size_t num_routes; + const envoy_config_route_v3_Route* const* routes = + envoy_config_route_v3_VirtualHost_routes(virtual_hosts[i], &num_routes); + if (num_routes < 1) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING( + "No route found in the virtual host."); + } + // Loop over the whole list of routes + 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<void>(envoy_config_route_v3_RouteMatch_query_parameters( + match, &query_parameters_size)); + if (query_parameters_size > 0) { + continue; + } + XdsRouteConfigResource::Route route; + bool ignore_route = false; + grpc_error_handle error = + RoutePathMatchParse(match, &route, &ignore_route); + if (error != GRPC_ERROR_NONE) return error; + if (ignore_route) continue; + error = RouteHeaderMatchersParse(match, &route); + if (error != GRPC_ERROR_NONE) return error; + error = RouteRuntimeFractionParse(match, &route); + if (error != GRPC_ERROR_NONE) return error; + if (envoy_config_route_v3_Route_has_route(routes[j])) { + route.action.emplace<XdsRouteConfigResource::Route::RouteAction>(); + auto& route_action = + y_absl::get<XdsRouteConfigResource::Route::RouteAction>(route.action); + error = + RouteActionParse(context, routes[j], &route_action, &ignore_route); + if (error != GRPC_ERROR_NONE) return error; + if (ignore_route) continue; + if (route_action.retry_policy == y_absl::nullopt && + retry_policy != nullptr) { + route_action.retry_policy = virtual_host_retry_policy; + } + } else if (envoy_config_route_v3_Route_has_non_forwarding_action( + routes[j])) { + route.action + .emplace<XdsRouteConfigResource::Route::NonForwardingAction>(); + } + if (context.use_v3) { + grpc_error_handle error = ParseTypedPerFilterConfig< + envoy_config_route_v3_Route, + envoy_config_route_v3_Route_TypedPerFilterConfigEntry>( + context, routes[j], + envoy_config_route_v3_Route_typed_per_filter_config_next, + envoy_config_route_v3_Route_TypedPerFilterConfigEntry_key, + envoy_config_route_v3_Route_TypedPerFilterConfigEntry_value, + &route.typed_per_filter_config); + if (error != GRPC_ERROR_NONE) return error; + } + vhost.routes.emplace_back(std::move(route)); + } + if (vhost.routes.empty()) { + return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No valid routes specified."); + } + } + return GRPC_ERROR_NONE; +} + +// +// XdsRouteConfigResourceType +// + +namespace { + +void MaybeLogRouteConfiguration( + const XdsEncodingContext& context, + const envoy_config_route_v3_RouteConfiguration* route_config) { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer) && + gpr_should_log(GPR_LOG_SEVERITY_DEBUG)) { + const upb_msgdef* msg_type = + envoy_config_route_v3_RouteConfiguration_getmsgdef(context.symtab); + char buf[10240]; + upb_text_encode(route_config, msg_type, nullptr, 0, buf, sizeof(buf)); + gpr_log(GPR_DEBUG, "[xds_client %p] RouteConfiguration: %s", context.client, + buf); + } +} + +} // namespace + +y_absl::StatusOr<XdsResourceType::DecodeResult> +XdsRouteConfigResourceType::Decode(const XdsEncodingContext& context, + y_absl::string_view serialized_resource, + bool /*is_v2*/) const { + // Parse serialized proto. + auto* resource = envoy_config_route_v3_RouteConfiguration_parse( + serialized_resource.data(), serialized_resource.size(), context.arena); + if (resource == nullptr) { + return y_absl::InvalidArgumentError( + "Can't parse RouteConfiguration resource."); + } + MaybeLogRouteConfiguration(context, resource); + // Validate resource. + DecodeResult result; + result.name = UpbStringToStdString( + envoy_config_route_v3_RouteConfiguration_name(resource)); + auto route_config_data = y_absl::make_unique<ResourceDataSubclass>(); + grpc_error_handle error = XdsRouteConfigResource::Parse( + context, resource, &route_config_data->resource); + if (error != GRPC_ERROR_NONE) { + TString error_str = grpc_error_std_string(error); + GRPC_ERROR_UNREF(error); + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_ERROR, "[xds_client %p] invalid RouteConfiguration %s: %s", + context.client, result.name.c_str(), error_str.c_str()); + } + result.resource = y_absl::InvalidArgumentError(error_str); + } else { + if (GRPC_TRACE_FLAG_ENABLED(*context.tracer)) { + gpr_log(GPR_INFO, "[xds_client %p] parsed RouteConfiguration %s: %s", + context.client, result.name.c_str(), + route_config_data->resource.ToString().c_str()); + } + result.resource = std::move(route_config_data); + } + return std::move(result); +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_route_config.h b/contrib/libs/grpc/src/core/ext/xds/xds_route_config.h new file mode 100644 index 0000000000..0721a9b112 --- /dev/null +++ b/contrib/libs/grpc/src/core/ext/xds/xds_route_config.h @@ -0,0 +1,215 @@ +// +// 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_XDS_XDS_ROUTE_CONFIG_H +#define GRPC_CORE_EXT_XDS_XDS_ROUTE_CONFIG_H + +#include <grpc/support/port_platform.h> + +#include <map> +#include <util/generic/string.h> +#include <vector> + +#include "y_absl/types/optional.h" +#include "y_absl/types/variant.h" +#include "envoy/config/route/v3/route.upb.h" +#include "envoy/config/route/v3/route.upbdefs.h" +#include "re2/re2.h" + +#include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_common_types.h" +#include "src/core/ext/xds/xds_http_filters.h" +#include "src/core/ext/xds/xds_resource_type_impl.h" +#include "src/core/lib/channel/status_util.h" +#include "src/core/lib/matchers/matchers.h" + +namespace grpc_core { + +bool XdsRbacEnabled(); + +struct XdsRouteConfigResource { + using TypedPerFilterConfig = + std::map<TString, XdsHttpFilterImpl::FilterConfig>; + + struct RetryPolicy { + internal::StatusCodeSet retry_on; + uint32_t num_retries; + + struct RetryBackOff { + Duration base_interval; + Duration max_interval; + + bool operator==(const RetryBackOff& other) const { + return base_interval == other.base_interval && + max_interval == other.max_interval; + } + TString ToString() const; + }; + RetryBackOff retry_back_off; + + bool operator==(const RetryPolicy& other) const { + return (retry_on == other.retry_on && num_retries == other.num_retries && + retry_back_off == other.retry_back_off); + } + TString ToString() const; + }; + + // TODO(donnadionne): When we can use y_absl::variant<>, consider using that + // for: PathMatcher, HeaderMatcher, cluster_name and weighted_clusters + struct Route { + // Matchers for this route. + struct Matchers { + StringMatcher path_matcher; + std::vector<HeaderMatcher> header_matchers; + y_absl::optional<uint32_t> fraction_per_million; + + bool operator==(const Matchers& other) const { + return path_matcher == other.path_matcher && + header_matchers == other.header_matchers && + fraction_per_million == other.fraction_per_million; + } + TString ToString() const; + }; + + Matchers matchers; + + struct UnknownAction { + bool operator==(const UnknownAction& /* other */) const { return true; } + }; + + struct RouteAction { + struct HashPolicy { + enum Type { HEADER, CHANNEL_ID }; + Type type; + bool terminal = false; + // Fields used for type HEADER. + TString header_name; + std::unique_ptr<RE2> regex = nullptr; + TString 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; + TString ToString() const; + }; + + struct ClusterWeight { + TString name; + uint32_t weight; + TypedPerFilterConfig typed_per_filter_config; + + bool operator==(const ClusterWeight& other) const { + return name == other.name && weight == other.weight && + typed_per_filter_config == other.typed_per_filter_config; + } + TString ToString() const; + }; + + std::vector<HashPolicy> hash_policies; + y_absl::optional<RetryPolicy> retry_policy; + + // Action for this route. + // TODO(roth): When we can use y_absl::variant<>, consider using that + // here, to enforce the fact that only one of the two fields can be set. + TString cluster_name; + std::vector<ClusterWeight> weighted_clusters; + // Storing the timeout duration from route action: + // RouteAction.max_stream_duration.grpc_timeout_header_max or + // RouteAction.max_stream_duration.max_stream_duration if the former is + // not set. + y_absl::optional<Duration> max_stream_duration; + + bool operator==(const RouteAction& other) const { + return hash_policies == other.hash_policies && + retry_policy == other.retry_policy && + cluster_name == other.cluster_name && + weighted_clusters == other.weighted_clusters && + max_stream_duration == other.max_stream_duration; + } + TString ToString() const; + }; + + struct NonForwardingAction { + bool operator==(const NonForwardingAction& /* other */) const { + return true; + } + }; + + y_absl::variant<UnknownAction, RouteAction, NonForwardingAction> action; + TypedPerFilterConfig typed_per_filter_config; + + bool operator==(const Route& other) const { + return matchers == other.matchers && action == other.action && + typed_per_filter_config == other.typed_per_filter_config; + } + TString ToString() const; + }; + + struct VirtualHost { + std::vector<TString> domains; + std::vector<Route> routes; + TypedPerFilterConfig typed_per_filter_config; + + bool operator==(const VirtualHost& other) const { + return domains == other.domains && routes == other.routes && + typed_per_filter_config == other.typed_per_filter_config; + } + }; + + std::vector<VirtualHost> virtual_hosts; + + bool operator==(const XdsRouteConfigResource& other) const { + return virtual_hosts == other.virtual_hosts; + } + TString ToString() const; + + static grpc_error_handle Parse( + const XdsEncodingContext& context, + const envoy_config_route_v3_RouteConfiguration* route_config, + XdsRouteConfigResource* rds_update); +}; + +class XdsRouteConfigResourceType + : public XdsResourceTypeImpl<XdsRouteConfigResourceType, + XdsRouteConfigResource> { + public: + y_absl::string_view type_url() const override { + return "envoy.config.route.v3.RouteConfiguration"; + } + y_absl::string_view v2_type_url() const override { + return "envoy.api.v2.RouteConfiguration"; + } + + y_absl::StatusOr<DecodeResult> Decode(const XdsEncodingContext& context, + y_absl::string_view serialized_resource, + bool /*is_v2*/) const override; + + void InitUpbSymtab(upb_symtab* symtab) const override { + envoy_config_route_v3_RouteConfiguration_getmsgdef(symtab); + } +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_EXT_XDS_XDS_ROUTE_CONFIG_H diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_routing.cc b/contrib/libs/grpc/src/core/ext/xds/xds_routing.cc index b0f5cee4e2..0dd0610297 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_routing.cc +++ b/contrib/libs/grpc/src/core/ext/xds/xds_routing.cc @@ -147,7 +147,7 @@ y_absl::optional<size_t> XdsRouting::GetRouteForRequest( const RouteListIterator& route_list_iterator, y_absl::string_view path, grpc_metadata_batch* initial_metadata) { for (size_t i = 0; i < route_list_iterator.Size(); ++i) { - const XdsApi::Route::Matchers& matchers = + const XdsRouteConfigResource::Route::Matchers& matchers = route_list_iterator.GetMatchersForRoute(i); if (matchers.path_matcher.Match(path) && HeadersMatch(matchers.header_matchers, initial_metadata) && @@ -174,16 +174,17 @@ y_absl::optional<y_absl::string_view> XdsRouting::GetHeaderValue( } else if (header_name == "content-type") { return "application/grpc"; } - return grpc_metadata_batch_get_value(initial_metadata, header_name, - concatenated_value); + return initial_metadata->GetStringValue(header_name, concatenated_value); } namespace { const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride( const TString& instance_name, - const XdsApi::RdsUpdate::VirtualHost& vhost, const XdsApi::Route& route, - const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight) { + const XdsRouteConfigResource::VirtualHost& vhost, + const XdsRouteConfigResource::Route& route, + const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* + cluster_weight) { // Check ClusterWeight, if any. if (cluster_weight != nullptr) { auto it = cluster_weight->typed_per_filter_config.find(instance_name); @@ -203,10 +204,12 @@ const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride( XdsRouting::GeneratePerHttpFilterConfigsResult XdsRouting::GeneratePerHTTPFilterConfigs( - const std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter>& + const std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>& http_filters, - const XdsApi::RdsUpdate::VirtualHost& vhost, const XdsApi::Route& route, - const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight, + const XdsRouteConfigResource::VirtualHost& vhost, + const XdsRouteConfigResource::Route& route, + const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* + cluster_weight, grpc_channel_args* args) { GeneratePerHttpFilterConfigsResult result; result.args = args; diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_routing.h b/contrib/libs/grpc/src/core/ext/xds/xds_routing.h index cd294e5806..21262eb1e0 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_routing.h +++ b/contrib/libs/grpc/src/core/ext/xds/xds_routing.h @@ -27,7 +27,8 @@ #include <grpc/support/log.h> -#include "src/core/ext/xds/xds_api.h" +#include "src/core/ext/xds/xds_listener.h" +#include "src/core/ext/xds/xds_route_config.h" #include "src/core/lib/matchers/matchers.h" #include "src/core/lib/transport/metadata_batch.h" @@ -51,7 +52,7 @@ class XdsRouting { // Number of routes. virtual size_t Size() const = 0; // Returns the matchers for the route at the specified index. - virtual const XdsApi::Route::Matchers& GetMatchersForRoute( + virtual const XdsRouteConfigResource::Route::Matchers& GetMatchersForRoute( size_t index) const = 0; }; @@ -86,10 +87,12 @@ class XdsRouting { // Generates a map of per_filter_configs. \a args is consumed. static GeneratePerHttpFilterConfigsResult GeneratePerHTTPFilterConfigs( - const std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter>& + const std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>& http_filters, - const XdsApi::RdsUpdate::VirtualHost& vhost, const XdsApi::Route& route, - const XdsApi::Route::RouteAction::ClusterWeight* cluster_weight, + const XdsRouteConfigResource::VirtualHost& vhost, + const XdsRouteConfigResource::Route& route, + const XdsRouteConfigResource::Route::RouteAction::ClusterWeight* + cluster_weight, grpc_channel_args* args); }; diff --git a/contrib/libs/grpc/src/core/ext/xds/xds_server_config_fetcher.cc b/contrib/libs/grpc/src/core/ext/xds/xds_server_config_fetcher.cc index 918d312799..33aa58843f 100644 --- a/contrib/libs/grpc/src/core/ext/xds/xds_server_config_fetcher.cc +++ b/contrib/libs/grpc/src/core/ext/xds/xds_server_config_fetcher.cc @@ -26,7 +26,10 @@ #include "src/core/ext/xds/xds_certificate_provider.h" #include "src/core/ext/xds/xds_channel_stack_modifier.h" #include "src/core/ext/xds/xds_client.h" +#include "src/core/ext/xds/xds_listener.h" +#include "src/core/ext/xds/xds_route_config.h" #include "src/core/ext/xds/xds_routing.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/config/core_configuration.h" @@ -68,8 +71,8 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher { private: class ListenerWatcher; - RefCountedPtr<XdsClient> xds_client_; - grpc_server_xds_status_notifier serving_status_notifier_; + const RefCountedPtr<XdsClient> xds_client_; + const grpc_server_xds_status_notifier serving_status_notifier_; Mutex mu_; std::map<grpc_server_config_fetcher::WatcherInterface*, ListenerWatcher*> listener_watchers_ Y_ABSL_GUARDED_BY(mu_); @@ -86,7 +89,7 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher { // update received was a fatal error (resource does not exist), the server // listener is made to stop listening. class XdsServerConfigFetcher::ListenerWatcher - : public XdsClient::ListenerWatcherInterface { + : public XdsListenerResourceType::WatcherInterface { public: ListenerWatcher(RefCountedPtr<XdsClient> xds_client, std::unique_ptr<grpc_server_config_fetcher::WatcherInterface> @@ -94,7 +97,7 @@ class XdsServerConfigFetcher::ListenerWatcher grpc_server_xds_status_notifier serving_status_notifier, TString listening_address); - void OnListenerChanged(XdsApi::LdsUpdate listener) override; + void OnResourceChanged(XdsListenerResource listener) override; void OnError(grpc_error_handle error) override; @@ -140,10 +143,10 @@ class XdsServerConfigFetcher::ListenerWatcher class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager : public grpc_server_config_fetcher::ConnectionManager { public: - FilterChainMatchManager( - RefCountedPtr<XdsClient> xds_client, - XdsApi::LdsUpdate::FilterChainMap filter_chain_map, - y_absl::optional<XdsApi::LdsUpdate::FilterChainData> default_filter_chain); + FilterChainMatchManager(RefCountedPtr<XdsClient> xds_client, + XdsListenerResource::FilterChainMap filter_chain_map, + y_absl::optional<XdsListenerResource::FilterChainData> + default_filter_chain); y_absl::StatusOr<grpc_channel_args*> UpdateChannelArgsForConnection( grpc_channel_args* args, grpc_endpoint* tcp) override; @@ -154,11 +157,11 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager void StartRdsWatch(RefCountedPtr<ListenerWatcher> listener_watcher) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(&ListenerWatcher::mu_); - const XdsApi::LdsUpdate::FilterChainMap& filter_chain_map() const { + const XdsListenerResource::FilterChainMap& filter_chain_map() const { return filter_chain_map_; } - const y_absl::optional<XdsApi::LdsUpdate::FilterChainData>& + const y_absl::optional<XdsListenerResource::FilterChainData>& default_filter_chain() const { return default_filter_chain_; } @@ -176,7 +179,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager class RouteConfigWatcher; struct RdsUpdateState { RouteConfigWatcher* watcher; - y_absl::optional<y_absl::StatusOr<XdsApi::RdsUpdate>> rds_update; + y_absl::optional<y_absl::StatusOr<XdsRouteConfigResource>> rds_update; }; class XdsServerConfigSelector; @@ -185,12 +188,12 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager y_absl::StatusOr<RefCountedPtr<XdsCertificateProvider>> CreateOrGetXdsCertificateProviderFromFilterChainData( - const XdsApi::LdsUpdate::FilterChainData* filter_chain); + const XdsListenerResource::FilterChainData* filter_chain); // Helper functions invoked by RouteConfigWatcher when there are updates to // RDS resources. void OnRouteConfigChanged(const TString& resource_name, - XdsApi::RdsUpdate route_config); + XdsRouteConfigResource route_config); void OnError(const TString& resource_name, grpc_error_handle error); void OnResourceDoesNotExist(const TString& resource_name); @@ -198,14 +201,13 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager // This ref is only kept around till the FilterChainMatchManager becomes // ready. RefCountedPtr<ListenerWatcher> listener_watcher_; - const XdsApi::LdsUpdate::FilterChainMap filter_chain_map_; - const y_absl::optional<XdsApi::LdsUpdate::FilterChainData> - default_filter_chain_; + XdsListenerResource::FilterChainMap filter_chain_map_; + y_absl::optional<XdsListenerResource::FilterChainData> default_filter_chain_; Mutex mu_; size_t rds_resources_yet_to_fetch_ Y_ABSL_GUARDED_BY(mu_) = 0; std::map<TString /* resource_name */, RdsUpdateState> rds_map_ Y_ABSL_GUARDED_BY(mu_); - std::map<const XdsApi::LdsUpdate::FilterChainData*, CertificateProviders> + std::map<const XdsListenerResource::FilterChainData*, CertificateProviders> certificate_providers_map_ Y_ABSL_GUARDED_BY(mu_); }; @@ -217,7 +219,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager // with the latest updates and new connections do not need to wait for the RDS // resources to be fetched. class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: - RouteConfigWatcher : public XdsClient::RouteConfigWatcherInterface { + RouteConfigWatcher : public XdsRouteConfigResourceType::WatcherInterface { public: RouteConfigWatcher( TString resource_name, @@ -225,7 +227,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: : resource_name_(std::move(resource_name)), filter_chain_match_manager_(std::move(filter_chain_match_manager)) {} - void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override { + void OnResourceChanged(XdsRouteConfigResource route_config) override { filter_chain_match_manager_->OnRouteConfigChanged(resource_name_, std::move(route_config)); } @@ -251,8 +253,8 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: XdsServerConfigSelector : public ServerConfigSelector { public: static y_absl::StatusOr<RefCountedPtr<XdsServerConfigSelector>> Create( - XdsApi::RdsUpdate rds_update, - const std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter>& + XdsRouteConfigResource rds_update, + const std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter>& http_filters); ~XdsServerConfigSelector() override = default; @@ -263,7 +265,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: struct Route { // true if an action other than kNonForwardingAction is configured. bool unsupported_action; - XdsApi::Route::Matchers matchers; + XdsRouteConfigResource::Route::Matchers matchers; RefCountedPtr<ServiceConfig> method_config; }; @@ -274,7 +276,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: size_t Size() const override { return routes_->size(); } - const XdsApi::Route::Matchers& GetMatchersForRoute( + const XdsRouteConfigResource::Route::Matchers& GetMatchersForRoute( size_t index) const override { return (*routes_)[index].matchers; } @@ -314,8 +316,8 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: : public ServerConfigSelectorProvider { public: StaticXdsServerConfigSelectorProvider( - y_absl::StatusOr<XdsApi::RdsUpdate> static_resource, - std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter> + y_absl::StatusOr<XdsRouteConfigResource> static_resource, + std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter> http_filters) : static_resource_(std::move(static_resource)), http_filters_(std::move(http_filters)) {} @@ -332,11 +334,13 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: http_filters_); } + void Orphan() override {} + void CancelWatch() override { watcher_.reset(); } private: - y_absl::StatusOr<XdsApi::RdsUpdate> static_resource_; - std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter> + y_absl::StatusOr<XdsRouteConfigResource> static_resource_; + std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter> http_filters_; std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher> watcher_; @@ -350,10 +354,12 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: public: DynamicXdsServerConfigSelectorProvider( RefCountedPtr<XdsClient> xds_client, TString resource_name, - y_absl::StatusOr<XdsApi::RdsUpdate> initial_resource, - std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter> + y_absl::StatusOr<XdsRouteConfigResource> initial_resource, + std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter> http_filters); + void Orphan() override; + y_absl::StatusOr<RefCountedPtr<ServerConfigSelector>> Watch( std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher> watcher) override; @@ -362,32 +368,32 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: private: class RouteConfigWatcher; - void OnRouteConfigChanged(XdsApi::RdsUpdate rds_update); + void OnRouteConfigChanged(XdsRouteConfigResource rds_update); void OnError(grpc_error_handle error); void OnResourceDoesNotExist(); RefCountedPtr<XdsClient> xds_client_; TString resource_name_; - std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter> + std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter> http_filters_; RouteConfigWatcher* route_config_watcher_ = nullptr; Mutex mu_; std::unique_ptr<ServerConfigSelectorProvider::ServerConfigSelectorWatcher> watcher_ Y_ABSL_GUARDED_BY(mu_); - y_absl::StatusOr<XdsApi::RdsUpdate> resource_ Y_ABSL_GUARDED_BY(mu_); + y_absl::StatusOr<XdsRouteConfigResource> resource_ Y_ABSL_GUARDED_BY(mu_); }; // A watcher implementation for updating the RDS resource used by // DynamicXdsServerConfigSelectorProvider class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: DynamicXdsServerConfigSelectorProvider::RouteConfigWatcher - : public XdsClient::RouteConfigWatcherInterface { + : public XdsRouteConfigResourceType::WatcherInterface { public: explicit RouteConfigWatcher( - RefCountedPtr<DynamicXdsServerConfigSelectorProvider> parent) + WeakRefCountedPtr<DynamicXdsServerConfigSelectorProvider> parent) : parent_(std::move(parent)) {} - void OnRouteConfigChanged(XdsApi::RdsUpdate route_config) override { + void OnResourceChanged(XdsRouteConfigResource route_config) override { parent_->OnRouteConfigChanged(std::move(route_config)); } @@ -396,7 +402,7 @@ class XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: void OnResourceDoesNotExist() override { parent_->OnResourceDoesNotExist(); } private: - RefCountedPtr<DynamicXdsServerConfigSelectorProvider> parent_; + WeakRefCountedPtr<DynamicXdsServerConfigSelectorProvider> parent_; }; // @@ -410,6 +416,17 @@ XdsServerConfigFetcher::XdsServerConfigFetcher( GPR_ASSERT(xds_client_ != nullptr); } +TString ListenerResourceName(y_absl::string_view resource_name_template, + y_absl::string_view listening_address) { + TString tmp; + if (y_absl::StartsWith(resource_name_template, "xdstp:")) { + tmp = URI::PercentEncodePath(listening_address); + listening_address = tmp; + } + return y_absl::StrReplaceAll(resource_name_template, + {{"%s", listening_address}}); +} + void XdsServerConfigFetcher::StartWatch( TString listening_address, std::unique_ptr<grpc_server_config_fetcher::WatcherInterface> watcher) { @@ -418,10 +435,11 @@ void XdsServerConfigFetcher::StartWatch( xds_client_, std::move(watcher), serving_status_notifier_, listening_address); auto* listener_watcher_ptr = listener_watcher.get(); - xds_client_->WatchListenerData( - y_absl::StrReplaceAll( + XdsListenerResourceType::StartWatch( + xds_client_.get(), + ListenerResourceName( xds_client_->bootstrap().server_listener_resource_name_template(), - {{"%s", listening_address}}), + listening_address), std::move(listener_watcher)); MutexLock lock(&mu_); listener_watchers_.emplace(watcher_ptr, listener_watcher_ptr); @@ -433,10 +451,11 @@ void XdsServerConfigFetcher::CancelWatch( auto it = listener_watchers_.find(watcher); if (it != listener_watchers_.end()) { // Cancel the watch on the listener before erasing - xds_client_->CancelListenerDataWatch( - y_absl::StrReplaceAll( + XdsListenerResourceType::CancelWatch( + xds_client_.get(), + ListenerResourceName( xds_client_->bootstrap().server_listener_resource_name_template(), - {{"%s", it->second->listening_address()}}), + it->second->listening_address()), it->second, false /* delay_unsubscription */); listener_watchers_.erase(it); } @@ -457,8 +476,8 @@ XdsServerConfigFetcher::ListenerWatcher::ListenerWatcher( serving_status_notifier_(serving_status_notifier), listening_address_(std::move(listening_address)) {} -void XdsServerConfigFetcher::ListenerWatcher::OnListenerChanged( - XdsApi::LdsUpdate listener) { +void XdsServerConfigFetcher::ListenerWatcher::OnResourceChanged( + XdsListenerResource listener) { if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_server_config_fetcher_trace)) { gpr_log(GPR_INFO, "[ListenerWatcher %p] Received LDS update from xds client %p: %s", @@ -578,16 +597,20 @@ void XdsServerConfigFetcher::ListenerWatcher:: XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: FilterChainMatchManager( RefCountedPtr<XdsClient> xds_client, - XdsApi::LdsUpdate::FilterChainMap filter_chain_map, - y_absl::optional<XdsApi::LdsUpdate::FilterChainData> default_filter_chain) + XdsListenerResource::FilterChainMap filter_chain_map, + y_absl::optional<XdsListenerResource::FilterChainData> + default_filter_chain) : xds_client_(std::move(xds_client)), filter_chain_map_(std::move(filter_chain_map)), default_filter_chain_(std::move(default_filter_chain)) {} void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: StartRdsWatch(RefCountedPtr<ListenerWatcher> listener_watcher) { - // Get the set of RDS resources to watch on + // Get the set of RDS resources to watch on. Also get the set of + // FilterChainData so that we can reverse the list of HTTP filters since + // received data moves *up* the stack in Core. std::set<TString> resource_names; + std::set<XdsListenerResource::FilterChainData*> filter_chain_data_set; for (const auto& destination_ip : filter_chain_map_.destination_ip_vector) { for (const auto& source_type : destination_ip.source_types_array) { for (const auto& source_ip : source_type) { @@ -598,17 +621,34 @@ void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: source_port_pair.second.data->http_connection_manager .route_config_name); } + filter_chain_data_set.insert(source_port_pair.second.data.get()); } } } } - if (default_filter_chain_.has_value() && - !default_filter_chain_->http_connection_manager.route_config_name - .empty()) { - resource_names.insert( - default_filter_chain_->http_connection_manager.route_config_name); + if (default_filter_chain_.has_value()) { + if (!default_filter_chain_->http_connection_manager.route_config_name + .empty()) { + resource_names.insert( + default_filter_chain_->http_connection_manager.route_config_name); + } + std::reverse( + default_filter_chain_->http_connection_manager.http_filters.begin(), + default_filter_chain_->http_connection_manager.http_filters.end()); + } + // Reverse the lists of HTTP filters in all the filter chains + for (auto* filter_chain_data : filter_chain_data_set) { + std::reverse( + filter_chain_data->http_connection_manager.http_filters.begin(), + filter_chain_data->http_connection_manager.http_filters.end()); } // Start watching on referenced RDS resources + struct WatcherToStart { + TString resource_name; + RefCountedPtr<RouteConfigWatcher> watcher; + }; + std::vector<WatcherToStart> watchers_to_start; + watchers_to_start.reserve(resource_names.size()); { MutexLock lock(&mu_); for (const auto& resource_name : resource_names) { @@ -617,14 +657,19 @@ void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: MakeRefCounted<RouteConfigWatcher>(resource_name, WeakRef()); rds_map_.emplace(resource_name, RdsUpdateState{route_config_watcher.get(), y_absl::nullopt}); - xds_client_->WatchRouteConfigData(resource_name, - std::move(route_config_watcher)); + watchers_to_start.push_back( + WatcherToStart{resource_name, std::move(route_config_watcher)}); } if (rds_resources_yet_to_fetch_ != 0) { listener_watcher_ = std::move(listener_watcher); listener_watcher = nullptr; } } + for (auto& watcher_to_start : watchers_to_start) { + XdsRouteConfigResourceType::StartWatch(xds_client_.get(), + watcher_to_start.resource_name, + std::move(watcher_to_start.watcher)); + } // Promote this filter chain match manager if all referenced resources are // fetched. if (listener_watcher != nullptr) { @@ -637,7 +682,8 @@ void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: MutexLock lock(&mu_); // Cancel the RDS watches to clear up the weak refs for (const auto& entry : rds_map_) { - xds_client_->CancelRouteConfigDataWatch(entry.first, entry.second.watcher, + XdsRouteConfigResourceType::CancelWatch(xds_client_.get(), entry.first, + entry.second.watcher, false /* delay_unsubscription */); } // Also give up the ref on ListenerWatcher since it won't be needed anymore @@ -647,7 +693,7 @@ void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: y_absl::StatusOr<RefCountedPtr<XdsCertificateProvider>> XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: CreateOrGetXdsCertificateProviderFromFilterChainData( - const XdsApi::LdsUpdate::FilterChainData* filter_chain) { + const XdsListenerResource::FilterChainData* filter_chain) { MutexLock lock(&mu_); auto it = certificate_providers_map_.find(filter_chain); if (it != certificate_providers_map_.end()) { @@ -711,7 +757,7 @@ XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: OnRouteConfigChanged(const TString& resource_name, - XdsApi::RdsUpdate route_config) { + XdsRouteConfigResource route_config) { RefCountedPtr<ListenerWatcher> listener_watcher; { MutexLock lock(&mu_); @@ -777,8 +823,8 @@ void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: } } -const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourcePort( - const XdsApi::LdsUpdate::FilterChainMap::SourcePortsMap& source_ports_map, +const XdsListenerResource::FilterChainData* FindFilterChainDataForSourcePort( + const XdsListenerResource::FilterChainMap::SourcePortsMap& source_ports_map, y_absl::string_view port_str) { int port = 0; if (!y_absl::SimpleAtoi(port_str, &port)) return nullptr; @@ -794,10 +840,10 @@ const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourcePort( return nullptr; } -const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourceIp( - const XdsApi::LdsUpdate::FilterChainMap::SourceIpVector& source_ip_vector, +const XdsListenerResource::FilterChainData* FindFilterChainDataForSourceIp( + const XdsListenerResource::FilterChainMap::SourceIpVector& source_ip_vector, const grpc_resolved_address* source_ip, y_absl::string_view port) { - const XdsApi::LdsUpdate::FilterChainMap::SourceIp* best_match = nullptr; + const XdsListenerResource::FilterChainMap::SourceIp* best_match = nullptr; for (const auto& entry : source_ip_vector) { // Special case for catch-all if (!entry.prefix_range.has_value()) { @@ -840,8 +886,8 @@ bool IsLoopbackIp(const grpc_resolved_address* address) { return false; } -const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourceType( - const XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceTypesArray& +const XdsListenerResource::FilterChainData* FindFilterChainDataForSourceType( + const XdsListenerResource::FilterChainMap::ConnectionSourceTypesArray& source_types_array, grpc_endpoint* tcp, y_absl::string_view destination_ip) { auto source_uri = URI::Parse(grpc_endpoint_get_peer(tcp)); @@ -865,34 +911,34 @@ const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourceType( } // Use kAny only if kSameIporLoopback and kExternal are empty if (source_types_array[static_cast<int>( - XdsApi::LdsUpdate::FilterChainMap:: + XdsListenerResource::FilterChainMap:: ConnectionSourceType::kSameIpOrLoopback)] .empty() && - source_types_array[static_cast<int>(XdsApi::LdsUpdate::FilterChainMap:: + source_types_array[static_cast<int>(XdsListenerResource::FilterChainMap:: ConnectionSourceType::kExternal)] .empty()) { return FindFilterChainDataForSourceIp( source_types_array[static_cast<int>( - XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::kAny)], + XdsListenerResource::FilterChainMap::ConnectionSourceType::kAny)], &source_addr, port); } if (IsLoopbackIp(&source_addr) || host == destination_ip) { return FindFilterChainDataForSourceIp( source_types_array[static_cast<int>( - XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType:: + XdsListenerResource::FilterChainMap::ConnectionSourceType:: kSameIpOrLoopback)], &source_addr, port); } else { return FindFilterChainDataForSourceIp( source_types_array[static_cast<int>( - XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType:: + XdsListenerResource::FilterChainMap::ConnectionSourceType:: kExternal)], &source_addr, port); } } -const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForDestinationIp( - const XdsApi::LdsUpdate::FilterChainMap::DestinationIpVector +const XdsListenerResource::FilterChainData* FindFilterChainDataForDestinationIp( + const XdsListenerResource::FilterChainMap::DestinationIpVector destination_ip_vector, grpc_endpoint* tcp) { auto destination_uri = URI::Parse(grpc_endpoint_get_local_address(tcp)); @@ -914,7 +960,8 @@ const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForDestinationIp( GRPC_ERROR_UNREF(error); return nullptr; } - const XdsApi::LdsUpdate::FilterChainMap::DestinationIp* best_match = nullptr; + const XdsListenerResource::FilterChainMap::DestinationIp* best_match = + nullptr; for (const auto& entry : destination_ip_vector) { // Special case for catch-all if (!entry.prefix_range.has_value()) { @@ -960,16 +1007,13 @@ y_absl::StatusOr<grpc_channel_args*> XdsServerConfigFetcher::ListenerWatcher:: std::vector<const grpc_channel_filter*> filters; // Iterate the list of HTTP filters in reverse since in Core, received data // flows *up* the stack. - for (auto reverse_iterator = - filter_chain->http_connection_manager.http_filters.rbegin(); - reverse_iterator != - filter_chain->http_connection_manager.http_filters.rend(); - ++reverse_iterator) { + for (const auto& http_filter : + filter_chain->http_connection_manager.http_filters) { // 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( - reverse_iterator->config.config_proto_type_name); + http_filter.config.config_proto_type_name); GPR_ASSERT(filter_impl != nullptr); // Some filters like the router filter are no-op filters and do not have // an implementation. @@ -986,7 +1030,7 @@ y_absl::StatusOr<grpc_channel_args*> XdsServerConfigFetcher::ListenerWatcher:: filter_chain->http_connection_manager.rds_update.value(), filter_chain->http_connection_manager.http_filters); } else { - y_absl::StatusOr<XdsApi::RdsUpdate> initial_resource; + y_absl::StatusOr<XdsRouteConfigResource> initial_resource; { MutexLock lock(&mu_); initial_resource = @@ -1035,8 +1079,9 @@ y_absl::StatusOr< FilterChainMatchManager::XdsServerConfigSelector>> XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: XdsServerConfigSelector::Create( - XdsApi::RdsUpdate rds_update, - const std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter>& + XdsRouteConfigResource rds_update, + const std::vector< + XdsListenerResource::HttpConnectionManager::HttpFilter>& http_filters) { auto config_selector = MakeRefCounted<XdsServerConfigSelector>(); for (auto& vhost : rds_update.virtual_hosts) { @@ -1048,8 +1093,8 @@ XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: auto& config_selector_route = virtual_host.routes.back(); config_selector_route.matchers = std::move(route.matchers); config_selector_route.unsupported_action = - y_absl::get_if<XdsApi::Route::NonForwardingAction>(&route.action) == - nullptr; + y_absl::get_if<XdsRouteConfigResource::Route::NonForwardingAction>( + &route.action) == nullptr; XdsRouting::GeneratePerHttpFilterConfigsResult result = XdsRouting::GeneratePerHTTPFilterConfigs(http_filters, vhost, route, nullptr, nullptr); @@ -1089,19 +1134,19 @@ ServerConfigSelector::CallConfig XdsServerConfigFetcher::ListenerWatcher:: FilterChainMatchManager::XdsServerConfigSelector::GetCallConfig( grpc_metadata_batch* metadata) { CallConfig call_config; - if (metadata->legacy_index()->named.path == nullptr) { + if (metadata->get_pointer(HttpPathMetadata()) == nullptr) { call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No path found"); return call_config; } - y_absl::string_view path = StringViewFromSlice( - GRPC_MDVALUE(metadata->legacy_index()->named.path->md)); - if (metadata->legacy_index()->named.authority == nullptr) { + y_absl::string_view path = + metadata->get_pointer(HttpPathMetadata())->as_string_view(); + if (metadata->get_pointer(HttpAuthorityMetadata()) == nullptr) { call_config.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("No authority found"); return call_config; } - y_absl::string_view authority = StringViewFromSlice( - GRPC_MDVALUE(metadata->legacy_index()->named.authority->md)); + y_absl::string_view authority = + metadata->get_pointer(HttpAuthorityMetadata())->as_string_view(); auto vhost_index = XdsRouting::FindVirtualHostForDomain( VirtualHostListIterator(&virtual_hosts_), authority); if (!vhost_index.has_value()) { @@ -1146,18 +1191,28 @@ XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: DynamicXdsServerConfigSelectorProvider:: DynamicXdsServerConfigSelectorProvider( RefCountedPtr<XdsClient> xds_client, TString resource_name, - y_absl::StatusOr<XdsApi::RdsUpdate> initial_resource, - std::vector<XdsApi::LdsUpdate::HttpConnectionManager::HttpFilter> + y_absl::StatusOr<XdsRouteConfigResource> initial_resource, + std::vector<XdsListenerResource::HttpConnectionManager::HttpFilter> http_filters) : xds_client_(std::move(xds_client)), resource_name_(std::move(resource_name)), http_filters_(std::move(http_filters)), resource_(std::move(initial_resource)) { GPR_ASSERT(!resource_name_.empty()); - auto route_config_watcher = MakeRefCounted<RouteConfigWatcher>(Ref()); + // RouteConfigWatcher is being created here instead of in Watch() to avoid + // deadlocks from invoking XdsRouteConfigResourceType::StartWatch whilst in a + // critical region. + auto route_config_watcher = MakeRefCounted<RouteConfigWatcher>(WeakRef()); route_config_watcher_ = route_config_watcher.get(); - xds_client_->WatchRouteConfigData(resource_name_, - std::move(route_config_watcher)); + XdsRouteConfigResourceType::StartWatch(xds_client_.get(), resource_name_, + std::move(route_config_watcher)); +} + +void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: + DynamicXdsServerConfigSelectorProvider::Orphan() { + XdsRouteConfigResourceType::CancelWatch(xds_client_.get(), resource_name_, + route_config_watcher_, + false /* delay_unsubscription */); } y_absl::StatusOr<RefCountedPtr<ServerConfigSelector>> @@ -1166,7 +1221,7 @@ XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: std::unique_ptr< ServerConfigSelectorProvider::ServerConfigSelectorWatcher> watcher) { - y_absl::StatusOr<XdsApi::RdsUpdate> resource; + y_absl::StatusOr<XdsRouteConfigResource> resource; { MutexLock lock(&mu_); GPR_ASSERT(watcher_ == nullptr); @@ -1181,20 +1236,22 @@ XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: DynamicXdsServerConfigSelectorProvider::CancelWatch() { - xds_client_->CancelRouteConfigDataWatch(resource_name_, route_config_watcher_, - false /* delay_unsubscription */); MutexLock lock(&mu_); watcher_.reset(); } void XdsServerConfigFetcher::ListenerWatcher::FilterChainMatchManager:: DynamicXdsServerConfigSelectorProvider::OnRouteConfigChanged( - XdsApi::RdsUpdate rds_update) { + XdsRouteConfigResource rds_update) { MutexLock lock(&mu_); resource_ = std::move(rds_update); if (watcher_ == nullptr) { return; } + // Currently server_config_selector_filter does not call into + // DynamicXdsServerConfigSelectorProvider while holding a lock, but if that + // ever changes, we would want to invoke the update outside the critical + // region with the use of a WorkSerializer. watcher_->OnServerConfigSelectorUpdate( XdsServerConfigSelector::Create(*resource_, http_filters_)); } @@ -1235,7 +1292,10 @@ grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create( args = grpc_core::CoreConfiguration::Get() .channel_args_preconditioning() .PreconditionChannelArgs(args); - GRPC_API_TRACE("grpc_server_config_fetcher_xds_create()", 0, ()); + GRPC_API_TRACE( + "grpc_server_config_fetcher_xds_create(notifier={on_serving_status_" + "update=%p, user_data=%p}, args=%p)", + 3, (notifier.on_serving_status_update, notifier.user_data, args)); grpc_error_handle error = GRPC_ERROR_NONE; grpc_core::RefCountedPtr<grpc_core::XdsClient> xds_client = grpc_core::XdsClient::GetOrCreate(args, &error); diff --git a/contrib/libs/grpc/src/core/lib/address_utils/parse_address.cc b/contrib/libs/grpc/src/core/lib/address_utils/parse_address.cc index eaaa168fa7..df63f40e2e 100644 --- a/contrib/libs/grpc/src/core/lib/address_utils/parse_address.cc +++ b/contrib/libs/grpc/src/core/lib/address_utils/parse_address.cc @@ -37,6 +37,7 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.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/grpc_if_nametoindex.h" @@ -318,3 +319,22 @@ uint16_t grpc_strhtons(const char* port) { } return htons(static_cast<unsigned short>(atoi(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<grpc_sockaddr_in6*>(out->addr); + grpc_sockaddr_in* addr4 = reinterpret_cast<grpc_sockaddr_in*>(out->addr); + if (grpc_inet_pton(GRPC_AF_INET6, addr, &addr6->sin6_addr) == 1) { + addr6->sin6_family = GRPC_AF_INET6; + out->len = sizeof(grpc_sockaddr_in6); + } else if (grpc_inet_pton(GRPC_AF_INET, addr, &addr4->sin_addr) == 1) { + addr4->sin_family = GRPC_AF_INET; + out->len = sizeof(grpc_sockaddr_in); + } else { + return GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Failed to parse address:", addr)); + } + grpc_sockaddr_set_port(out, port); + return GRPC_ERROR_NONE; +} diff --git a/contrib/libs/grpc/src/core/lib/address_utils/parse_address.h b/contrib/libs/grpc/src/core/lib/address_utils/parse_address.h index e6e9ffcbfa..78c3656cca 100644 --- a/contrib/libs/grpc/src/core/lib/address_utils/parse_address.h +++ b/contrib/libs/grpc/src/core/lib/address_utils/parse_address.h @@ -61,6 +61,11 @@ bool grpc_parse_ipv6_hostport(y_absl::string_view hostport, /* Converts named or numeric port to a uint16 suitable for use in a sockaddr. */ uint16_t grpc_strhtons(const char* 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); + namespace grpc_core { /** Populate \a resolved_addr to be a unix socket at |path| */ diff --git a/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc b/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc index 5e7229cd26..a6b7c4af3d 100644 --- a/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc +++ b/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc @@ -29,16 +29,42 @@ #include "y_absl/strings/str_cat.h" #include "y_absl/strings/str_format.h" -#include <grpc/event_engine/event_engine.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/host_port.h" -#include "src/core/lib/iomgr/event_engine/resolved_address_internal.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/socket_utils.h" -#include "src/core/lib/iomgr/unix_sockets_posix.h" + +#ifdef GRPC_HAVE_UNIX_SOCKET +#include <sys/un.h> +#endif + +#ifdef GRPC_HAVE_UNIX_SOCKET +static TString grpc_sockaddr_to_uri_unix_if_possible( + const grpc_resolved_address* resolved_addr) { + const grpc_sockaddr* addr = + reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); + if (addr->sa_family != AF_UNIX) { + return ""; + } + const auto* unix_addr = reinterpret_cast<const struct sockaddr_un*>(addr); + if (unix_addr->sun_path[0] == '\0' && unix_addr->sun_path[1] != '\0') { + return y_absl::StrCat( + "unix-abstract:", + y_absl::string_view( + unix_addr->sun_path + 1, + resolved_addr->len - sizeof(unix_addr->sun_family) - 1)); + } + return y_absl::StrCat("unix:", unix_addr->sun_path); +} +#else +static TString grpc_sockaddr_to_uri_unix_if_possible( + const grpc_resolved_address* /* addr */) { + return ""; +} +#endif static const uint8_t kV4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff}; @@ -200,25 +226,6 @@ TString grpc_sockaddr_to_string(const grpc_resolved_address* resolved_addr, return out; } -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<grpc_sockaddr_in6*>(out->addr); - grpc_sockaddr_in* addr4 = reinterpret_cast<grpc_sockaddr_in*>(out->addr); - if (grpc_inet_pton(GRPC_AF_INET6, addr, &addr6->sin6_addr) == 1) { - addr6->sin6_family = GRPC_AF_INET6; - out->len = sizeof(grpc_sockaddr_in6); - } else if (grpc_inet_pton(GRPC_AF_INET, addr, &addr4->sin_addr) == 1) { - addr4->sin_family = GRPC_AF_INET; - out->len = sizeof(grpc_sockaddr_in); - } else { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrCat("Failed to parse address:", addr)); - } - grpc_sockaddr_set_port(out, port); - return GRPC_ERROR_NONE; -} - TString grpc_sockaddr_to_uri(const grpc_resolved_address* resolved_addr) { if (resolved_addr->len == 0) return ""; grpc_resolved_address addr_normalized; @@ -269,10 +276,11 @@ int grpc_sockaddr_get_port(const grpc_resolved_address* resolved_addr) { case GRPC_AF_INET6: return grpc_ntohs( (reinterpret_cast<const grpc_sockaddr_in6*>(addr))->sin6_port); +#ifdef GRPC_HAVE_UNIX_SOCKET + case AF_UNIX: + return 1; +#endif default: - if (grpc_is_unix_socket(resolved_addr)) { - return 1; - } gpr_log(GPR_ERROR, "Unknown socket family %d in grpc_sockaddr_get_port", addr->sa_family); return 0; @@ -399,14 +407,3 @@ bool grpc_sockaddr_match_subnet(const grpc_resolved_address* address, } return false; } - -namespace grpc_event_engine { -namespace experimental { - -TString ResolvedAddressToURI(const EventEngine::ResolvedAddress& addr) { - auto gra = CreateGRPCResolvedAddress(addr); - return grpc_sockaddr_to_uri(&gra); -} - -} // namespace experimental -} // namespace grpc_event_engine diff --git a/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.h b/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.h index ddfebfa8c1..9164175b7e 100644 --- a/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.h +++ b/contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.h @@ -23,9 +23,7 @@ #include <util/generic/string.h> -#include <grpc/event_engine/event_engine.h> - -#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolved_address.h" /* Returns true if addr is an IPv4-mapped IPv6 address within the ::ffff:0.0.0.0/96 range, or false otherwise. @@ -68,11 +66,6 @@ int grpc_sockaddr_set_port(grpc_resolved_address* addr, int port); TString grpc_sockaddr_to_string(const grpc_resolved_address* addr, bool normalize) GRPC_MUST_USE_RESULT; -// 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 */ TString grpc_sockaddr_to_uri(const grpc_resolved_address* addr); @@ -99,12 +92,4 @@ bool grpc_sockaddr_match_subnet(const grpc_resolved_address* address, const grpc_resolved_address* subnet_address, uint32_t mask_bits); -namespace grpc_event_engine { -namespace experimental { - -TString ResolvedAddressToURI(const EventEngine::ResolvedAddress& addr); - -} // namespace experimental -} // namespace grpc_event_engine - #endif /* GRPC_CORE_LIB_ADDRESS_UTILS_SOCKADDR_UTILS_H */ diff --git a/contrib/libs/grpc/src/core/lib/backoff/backoff.cc b/contrib/libs/grpc/src/core/lib/backoff/backoff.cc index edca1de4ce..bffd558a4f 100644 --- a/contrib/libs/grpc/src/core/lib/backoff/backoff.cc +++ b/contrib/libs/grpc/src/core/lib/backoff/backoff.cc @@ -26,31 +26,7 @@ namespace grpc_core { -namespace { - -/* Generate a random number between 0 and 1. We roll our own RNG because seeding - * rand() modifies a global variable we have no control over. */ -double generate_uniform_random_number(uint32_t* rng_state) { - constexpr uint32_t two_raise_31 = uint32_t(1) << 31; - *rng_state = (1103515245 * *rng_state + 12345) % two_raise_31; - return *rng_state / static_cast<double>(two_raise_31); -} - -double generate_uniform_random_number_between(uint32_t* rng_state, double a, - double b) { - if (a == b) return a; - if (a > b) std::swap(a, b); // make sure a < b - const double range = b - a; - return a + generate_uniform_random_number(rng_state) * range; -} - -} // namespace - -BackOff::BackOff(const Options& options) - : options_(options), - rng_state_(static_cast<uint32_t>(gpr_now(GPR_CLOCK_REALTIME).tv_nsec)) { - Reset(); -} +BackOff::BackOff(const Options& options) : options_(options) { Reset(); } grpc_millis BackOff::NextAttemptTime() { if (initial_) { @@ -60,9 +36,9 @@ grpc_millis BackOff::NextAttemptTime() { current_backoff_ = static_cast<grpc_millis>( std::min(current_backoff_ * options_.multiplier(), static_cast<double>(options_.max_backoff()))); - const double jitter = generate_uniform_random_number_between( - &rng_state_, -options_.jitter() * current_backoff_, - options_.jitter() * current_backoff_); + const double jitter = + y_absl::Uniform(rand_gen_, -options_.jitter() * current_backoff_, + options_.jitter() * current_backoff_); const grpc_millis next_timeout = static_cast<grpc_millis>(current_backoff_ + jitter); return next_timeout + ExecCtx::Get()->Now(); @@ -73,6 +49,4 @@ void BackOff::Reset() { initial_ = true; } -void BackOff::SetRandomSeed(uint32_t seed) { rng_state_ = seed; } - } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/backoff/backoff.h b/contrib/libs/grpc/src/core/lib/backoff/backoff.h index e769d150ef..ab56dfeef4 100644 --- a/contrib/libs/grpc/src/core/lib/backoff/backoff.h +++ b/contrib/libs/grpc/src/core/lib/backoff/backoff.h @@ -21,6 +21,8 @@ #include <grpc/support/port_platform.h> +#include "y_absl/random/random.h" + #include "src/core/lib/iomgr/exec_ctx.h" namespace grpc_core { @@ -41,8 +43,6 @@ class BackOff { /// will be the time of the second attempt (rather than the Nth). void Reset(); - void SetRandomSeed(unsigned int seed); - class Options { public: Options& set_initial_backoff(grpc_millis initial_backoff) { @@ -79,7 +79,7 @@ class BackOff { private: const Options options_; - uint32_t rng_state_; + y_absl::BitGen rand_gen_; bool initial_; /// current delay before retries grpc_millis current_backoff_; diff --git a/contrib/libs/grpc/src/core/lib/channel/channel_args.cc b/contrib/libs/grpc/src/core/lib/channel/channel_args.cc index d9e4d81f7a..aa3f1caaf2 100644 --- a/contrib/libs/grpc/src/core/lib/channel/channel_args.cc +++ b/contrib/libs/grpc/src/core/lib/channel/channel_args.cc @@ -30,7 +30,6 @@ #include "y_absl/strings/str_join.h" #include <grpc/impl/codegen/grpc_types.h> -#include <grpc/impl/codegen/log.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> diff --git a/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc b/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc index a7f890e26d..711c0a00a6 100644 --- a/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc +++ b/contrib/libs/grpc/src/core/lib/channel/channel_stack.cc @@ -29,6 +29,7 @@ #include "src/core/lib/gpr/alloc.h" grpc_core::TraceFlag grpc_trace_channel(false, "channel"); +grpc_core::TraceFlag grpc_trace_channel_stack(false, "channel_stack"); /* Memory layouts. @@ -105,6 +106,13 @@ grpc_error_handle grpc_channel_stack_init( const grpc_channel_filter** filters, size_t filter_count, const grpc_channel_args* channel_args, grpc_transport* optional_transport, const char* name, grpc_channel_stack* stack) { + if (grpc_trace_channel_stack.enabled()) { + gpr_log(GPR_INFO, "CHANNEL_STACK: init %s", name); + for (size_t i = 0; i < filter_count; i++) { + gpr_log(GPR_INFO, "CHANNEL_STACK: filter %s", filters[i]->name); + } + } + size_t call_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(grpc_call_stack)) + GPR_ROUND_UP_TO_ALIGNMENT_SIZE(filter_count * sizeof(grpc_call_element)); diff --git a/contrib/libs/grpc/src/core/lib/channel/channel_stack.h b/contrib/libs/grpc/src/core/lib/channel/channel_stack.h index 5e6b3594db..0f3504f85b 100644 --- a/contrib/libs/grpc/src/core/lib/channel/channel_stack.h +++ b/contrib/libs/grpc/src/core/lib/channel/channel_stack.h @@ -54,9 +54,9 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/gpr/time_precise.h" -#include "src/core/lib/gprpp/arena.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/polling_entity.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/transport/transport.h" typedef struct grpc_channel_element grpc_channel_element; diff --git a/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.cc b/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.cc index b9c0e4c7f9..9cbd47d86c 100644 --- a/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.cc +++ b/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.cc @@ -51,7 +51,8 @@ struct grpc_channel_stack_builder_iterator { filter_node* node; }; -grpc_channel_stack_builder* grpc_channel_stack_builder_create(void) { +grpc_channel_stack_builder* grpc_channel_stack_builder_create( + const char* name) { grpc_channel_stack_builder* b = grpc_core::Zalloc<grpc_channel_stack_builder>(); b->begin.filter = nullptr; @@ -60,6 +61,7 @@ grpc_channel_stack_builder* grpc_channel_stack_builder_create(void) { b->begin.prev = &b->end; b->end.next = &b->begin; b->end.prev = &b->begin; + b->name = name; return b; } @@ -69,9 +71,9 @@ void grpc_channel_stack_builder_set_target(grpc_channel_stack_builder* b, b->target = gpr_strdup(target); } -const char* grpc_channel_stack_builder_get_target( +TString grpc_channel_stack_builder_get_target( grpc_channel_stack_builder* b) { - return b->target; + return b->target == nullptr ? TString("unknown") : TString(b->target); } static grpc_channel_stack_builder_iterator* create_iterator_at_filter_node( @@ -143,12 +145,6 @@ grpc_channel_stack_builder_iterator* grpc_channel_stack_builder_iterator_find( bool grpc_channel_stack_builder_move_prev( grpc_channel_stack_builder_iterator* iterator); -void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder* builder, - const char* name) { - GPR_ASSERT(builder->name == nullptr); - builder->name = name; -} - void grpc_channel_stack_builder_set_channel_arguments( grpc_channel_stack_builder* builder, const grpc_channel_args* args) { if (builder->args != nullptr) { diff --git a/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.h b/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.h index 0071aa960f..227d1a9f95 100644 --- a/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.h +++ b/contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.h @@ -32,18 +32,15 @@ typedef struct grpc_channel_stack_builder grpc_channel_stack_builder; typedef struct grpc_channel_stack_builder_iterator grpc_channel_stack_builder_iterator; -/// Create a new channel stack builder -grpc_channel_stack_builder* grpc_channel_stack_builder_create(void); - -/// Assign a name to the channel stack: \a name must be statically allocated -void grpc_channel_stack_builder_set_name(grpc_channel_stack_builder* builder, - const char* name); +/// Create a new channel stack builder. +/// \a name must be statically allocated. +grpc_channel_stack_builder* grpc_channel_stack_builder_create(const char* name); /// Set the target uri void grpc_channel_stack_builder_set_target(grpc_channel_stack_builder* b, const char* target); -const char* grpc_channel_stack_builder_get_target( +TString grpc_channel_stack_builder_get_target( grpc_channel_stack_builder* b); /// Attach \a transport to the builder (does not take ownership) diff --git a/contrib/libs/grpc/src/core/lib/channel/channelz.cc b/contrib/libs/grpc/src/core/lib/channel/channelz.cc index 870427757b..93588abadf 100644 --- a/contrib/libs/grpc/src/core/lib/channel/channelz.cc +++ b/contrib/libs/grpc/src/core/lib/channel/channelz.cc @@ -34,6 +34,7 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> +#include "src/core/lib/address_utils/parse_address.h" #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" diff --git a/contrib/libs/grpc/src/core/lib/compression/algorithm_metadata.h b/contrib/libs/grpc/src/core/lib/compression/algorithm_metadata.h deleted file mode 100644 index d053d121e5..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/algorithm_metadata.h +++ /dev/null @@ -1,62 +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. - * - */ - -#ifndef GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H -#define GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H - -#include <grpc/support/port_platform.h> - -#include <grpc/compression.h> - -#include "src/core/lib/compression/compression_internal.h" -#include "src/core/lib/transport/metadata.h" - -/** Return compression algorithm based metadata value */ -grpc_slice grpc_compression_algorithm_slice( - grpc_compression_algorithm algorithm); - -/** Find compression algorithm based on passed in mdstr - returns - * GRPC_COMPRESS_ALGORITHM_COUNT on failure */ -grpc_compression_algorithm grpc_compression_algorithm_from_slice( - const grpc_slice& str); - -/** Return compression algorithm based metadata element */ -grpc_mdelem grpc_compression_encoding_mdelem( - grpc_compression_algorithm algorithm); - -/** Return message compression algorithm based metadata element (grpc-encoding: - * xxx) */ -grpc_mdelem grpc_message_compression_encoding_mdelem( - grpc_message_compression_algorithm algorithm); - -/** Return stream compression algorithm based metadata element - * (content-encoding: xxx) */ -grpc_mdelem grpc_stream_compression_encoding_mdelem( - grpc_stream_compression_algorithm algorithm); - -/** Find compression algorithm based on passed in mdstr - returns - * GRPC_COMPRESS_ALGORITHM_COUNT on failure */ -grpc_message_compression_algorithm -grpc_message_compression_algorithm_from_slice(const grpc_slice& str); - -/** Find stream compression algorithm based on passed in mdstr - returns - * GRPC_STREAM_COMPRESS_ALGORITHM_COUNT on failure */ -grpc_stream_compression_algorithm grpc_stream_compression_algorithm_from_slice( - const grpc_slice& str); - -#endif /* GRPC_CORE_LIB_COMPRESSION_ALGORITHM_METADATA_H */ diff --git a/contrib/libs/grpc/src/core/lib/compression/compression.cc b/contrib/libs/grpc/src/core/lib/compression/compression.cc index 3d5d11f6b7..f0aef4c657 100644 --- a/contrib/libs/grpc/src/core/lib/compression/compression.cc +++ b/contrib/libs/grpc/src/core/lib/compression/compression.cc @@ -23,89 +23,47 @@ #include <grpc/compression.h> -#include "src/core/lib/compression/algorithm_metadata.h" #include "src/core/lib/compression/compression_internal.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/slice/slice_utils.h" #include "src/core/lib/surface/api_trace.h" -#include "src/core/lib/transport/static_metadata.h" -int grpc_compression_algorithm_is_message( - grpc_compression_algorithm algorithm) { - return (algorithm >= GRPC_COMPRESS_DEFLATE && algorithm <= GRPC_COMPRESS_GZIP) - ? 1 - : 0; +int grpc_compression_algorithm_is_message(grpc_compression_algorithm) { + return 1; } -int grpc_compression_algorithm_is_stream(grpc_compression_algorithm algorithm) { - return (algorithm == GRPC_COMPRESS_STREAM_GZIP) ? 1 : 0; +int grpc_compression_algorithm_is_stream(grpc_compression_algorithm) { + return 0; } int grpc_compression_algorithm_parse(grpc_slice name, grpc_compression_algorithm* algorithm) { - if (grpc_slice_eq_static_interned(name, GRPC_MDSTR_IDENTITY)) { - *algorithm = GRPC_COMPRESS_NONE; - return 1; - } else if (grpc_slice_eq_static_interned(name, GRPC_MDSTR_DEFLATE)) { - *algorithm = GRPC_COMPRESS_DEFLATE; + y_absl::optional<grpc_compression_algorithm> alg = + grpc_core::ParseCompressionAlgorithm( + grpc_core::StringViewFromSlice(name)); + if (alg.has_value()) { + *algorithm = alg.value(); return 1; - } else if (grpc_slice_eq_static_interned(name, GRPC_MDSTR_GZIP)) { - *algorithm = GRPC_COMPRESS_GZIP; - return 1; - } else if (grpc_slice_eq_static_interned(name, - GRPC_MDSTR_STREAM_SLASH_GZIP)) { - *algorithm = GRPC_COMPRESS_STREAM_GZIP; - return 1; - } else { - return 0; } + return 0; } int grpc_compression_algorithm_name(grpc_compression_algorithm algorithm, const char** name) { GRPC_API_TRACE("grpc_compression_algorithm_name(algorithm=%d, name=%p)", 2, ((int)algorithm, name)); - switch (algorithm) { - case GRPC_COMPRESS_NONE: - *name = "identity"; - return 1; - case GRPC_COMPRESS_DEFLATE: - *name = "deflate"; - return 1; - case GRPC_COMPRESS_GZIP: - *name = "gzip"; - return 1; - case GRPC_COMPRESS_STREAM_GZIP: - *name = "stream/gzip"; - return 1; - case GRPC_COMPRESS_ALGORITHMS_COUNT: - return 0; + const char* result = grpc_core::CompressionAlgorithmAsString(algorithm); + if (result != nullptr) { + *name = result; + return 1; } return 0; } grpc_compression_algorithm grpc_compression_algorithm_for_level( grpc_compression_level level, uint32_t accepted_encodings) { - grpc_compression_algorithm algo; - if (level == GRPC_COMPRESS_LEVEL_NONE) { - return GRPC_COMPRESS_NONE; - } else if (level <= GRPC_COMPRESS_LEVEL_HIGH) { - // TODO(mxyan): Design algorithm to select from all algorithms, including - // stream compression algorithm - if (!grpc_compression_algorithm_from_message_stream_compression_algorithm( - &algo, - grpc_message_compression_algorithm_for_level( - level, - grpc_compression_bitset_to_message_bitset(accepted_encodings)), - static_cast<grpc_stream_compression_algorithm>(0))) { - gpr_log(GPR_ERROR, "Parse compression level error"); - return GRPC_COMPRESS_NONE; - } - return algo; - } else { - gpr_log(GPR_ERROR, "Unknown compression level: %d", level); - return GRPC_COMPRESS_NONE; - } + return grpc_core::CompressionAlgorithmSet::FromUint32(accepted_encodings) + .CompressionAlgorithmForLevel(level); } void grpc_compression_options_init(grpc_compression_options* opts) { @@ -127,57 +85,7 @@ void grpc_compression_options_disable_algorithm( int grpc_compression_options_is_algorithm_enabled( const grpc_compression_options* opts, grpc_compression_algorithm algorithm) { - return grpc_compression_options_is_algorithm_enabled_internal(opts, - algorithm); -} - -grpc_slice grpc_compression_algorithm_slice( - grpc_compression_algorithm algorithm) { - switch (algorithm) { - case GRPC_COMPRESS_NONE: - return GRPC_MDSTR_IDENTITY; - case GRPC_COMPRESS_DEFLATE: - return GRPC_MDSTR_DEFLATE; - case GRPC_COMPRESS_GZIP: - return GRPC_MDSTR_GZIP; - case GRPC_COMPRESS_STREAM_GZIP: - return GRPC_MDSTR_STREAM_SLASH_GZIP; - case GRPC_COMPRESS_ALGORITHMS_COUNT: - return grpc_empty_slice(); - } - return grpc_empty_slice(); -} - -grpc_compression_algorithm grpc_compression_algorithm_from_slice( - const grpc_slice& str) { - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_IDENTITY)) { - return GRPC_COMPRESS_NONE; - } - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_DEFLATE)) { - return GRPC_COMPRESS_DEFLATE; - } - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_GZIP)) { - return GRPC_COMPRESS_GZIP; - } - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_STREAM_SLASH_GZIP)) { - return GRPC_COMPRESS_STREAM_GZIP; - } - return GRPC_COMPRESS_ALGORITHMS_COUNT; -} - -grpc_mdelem grpc_compression_encoding_mdelem( - grpc_compression_algorithm algorithm) { - switch (algorithm) { - case GRPC_COMPRESS_NONE: - return GRPC_MDELEM_GRPC_ENCODING_IDENTITY; - case GRPC_COMPRESS_DEFLATE: - return GRPC_MDELEM_GRPC_ENCODING_DEFLATE; - case GRPC_COMPRESS_GZIP: - return GRPC_MDELEM_GRPC_ENCODING_GZIP; - case GRPC_COMPRESS_STREAM_GZIP: - return GRPC_MDELEM_GRPC_ENCODING_GZIP; - default: - break; - } - return GRPC_MDNULL; + return grpc_core::CompressionAlgorithmSet::FromUint32( + opts->enabled_algorithms_bitset) + .IsSet(algorithm); } diff --git a/contrib/libs/grpc/src/core/lib/compression/compression_args.cc b/contrib/libs/grpc/src/core/lib/compression/compression_args.cc deleted file mode 100644 index 0db9eb266a..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/compression_args.cc +++ /dev/null @@ -1,140 +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. - * - */ - -#include <grpc/support/port_platform.h> - -#include "src/core/lib/compression/compression_args.h" - -#include <limits.h> -#include <string.h> - -#include <grpc/compression.h> -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> - -#include "src/core/lib/channel/channel_args.h" -#include "src/core/lib/gpr/string.h" -#include "src/core/lib/gpr/useful.h" - -grpc_compression_algorithm -grpc_channel_args_get_channel_default_compression_algorithm( - const grpc_channel_args* a) { - size_t i; - if (a == nullptr) return GRPC_COMPRESS_NONE; - for (i = 0; i < a->num_args; ++i) { - if (a->args[i].type == GRPC_ARG_INTEGER && - !strcmp(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, a->args[i].key)) { - grpc_compression_algorithm default_algorithm = - static_cast<grpc_compression_algorithm>(a->args[i].value.integer); - return default_algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT - ? default_algorithm - : GRPC_COMPRESS_NONE; - } - } - return GRPC_COMPRESS_NONE; -} - -const grpc_channel_args* -grpc_channel_args_set_channel_default_compression_algorithm( - const grpc_channel_args* a, grpc_compression_algorithm algorithm) { - GPR_ASSERT(algorithm < GRPC_COMPRESS_ALGORITHMS_COUNT); - grpc_arg tmp; - tmp.type = GRPC_ARG_INTEGER; - tmp.key = const_cast<char*>(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM); - tmp.value.integer = algorithm; - return grpc_channel_args_copy_and_add(a, &tmp, 1); -} - -/** Returns 1 if the argument for compression algorithm's enabled states bitset - * was found in \a a, returning the arg's value in \a states. Otherwise, returns - * 0. */ -static int find_compression_algorithm_states_bitset(const grpc_channel_args* a, - int** states_arg) { - if (a != nullptr) { - size_t i; - for (i = 0; i < a->num_args; ++i) { - if (a->args[i].type == GRPC_ARG_INTEGER && - !strcmp(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, - a->args[i].key)) { - *states_arg = &a->args[i].value.integer; - **states_arg = - (**states_arg & ((1 << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1)) | - 0x1; /* forcefully enable support for no compression */ - return 1; - } - } - } - return 0; /* GPR_FALSE */ -} - -const grpc_channel_args* grpc_channel_args_compression_algorithm_set_state( - const grpc_channel_args** a, grpc_compression_algorithm algorithm, - int state) { - int* states_arg = nullptr; - const grpc_channel_args* result = *a; - const int states_arg_found = - find_compression_algorithm_states_bitset(*a, &states_arg); - - if (grpc_channel_args_get_channel_default_compression_algorithm(*a) == - algorithm && - state == 0) { - const char* algo_name = nullptr; - GPR_ASSERT(grpc_compression_algorithm_name(algorithm, &algo_name) != 0); - gpr_log(GPR_ERROR, - "Tried to disable default compression algorithm '%s'. The " - "operation has been ignored.", - algo_name); - } else if (states_arg_found) { - if (state != 0) { - grpc_core::SetBit(reinterpret_cast<unsigned*>(states_arg), algorithm); - } else if (algorithm != GRPC_COMPRESS_NONE) { - grpc_core::ClearBit(reinterpret_cast<unsigned*>(states_arg), algorithm); - } - } else { - /* create a new arg */ - grpc_arg tmp; - tmp.type = GRPC_ARG_INTEGER; - tmp.key = - const_cast<char*>(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET); - /* all enabled by default */ - tmp.value.integer = (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; - if (state != 0) { - grpc_core::SetBit(reinterpret_cast<unsigned*>(&tmp.value.integer), - algorithm); - } else if (algorithm != GRPC_COMPRESS_NONE) { - grpc_core::ClearBit(reinterpret_cast<unsigned*>(&tmp.value.integer), - algorithm); - } - result = grpc_channel_args_copy_and_add(*a, &tmp, 1); - grpc_channel_args_destroy(*a); - *a = result; - } - return result; -} - -uint32_t grpc_channel_args_compression_algorithm_get_states( - const grpc_channel_args* a) { - int* states_arg; - if (find_compression_algorithm_states_bitset(a, &states_arg)) { - return static_cast<uint32_t>(*states_arg); - } else { - return (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; /* All algs. enabled */ - } -} diff --git a/contrib/libs/grpc/src/core/lib/compression/compression_args.h b/contrib/libs/grpc/src/core/lib/compression/compression_args.h deleted file mode 100644 index bd203384ef..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/compression_args.h +++ /dev/null @@ -1,58 +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. - * - */ - -#ifndef GRPC_CORE_LIB_COMPRESSION_COMPRESSION_ARGS_H -#define GRPC_CORE_LIB_COMPRESSION_COMPRESSION_ARGS_H - -#include <grpc/support/port_platform.h> - -#include <grpc/compression.h> -#include <grpc/impl/codegen/grpc_types.h> - -/** Returns the compression algorithm set in \a a. */ -grpc_compression_algorithm -grpc_channel_args_get_channel_default_compression_algorithm( - const grpc_channel_args* a); - -/** Returns a channel arg instance with compression enabled. If \a a is - * non-NULL, its args are copied. N.B. GRPC_COMPRESS_NONE disables compression - * for the channel. */ -const grpc_channel_args* -grpc_channel_args_set_channel_default_compression_algorithm( - const grpc_channel_args* a, grpc_compression_algorithm algorithm); - -/** Sets the support for the given compression algorithm. By default, all - * compression algorithms are enabled. It's an error to disable an algorithm set - * by grpc_channel_args_set_compression_algorithm. - * - * Returns an instance with the updated algorithm states. The \a a pointer is - * modified to point to the returned instance (which may be different from the - * input value of \a a). */ -const grpc_channel_args* grpc_channel_args_compression_algorithm_set_state( - const grpc_channel_args** a, grpc_compression_algorithm algorithm, - int state); - -/** Returns the bitset representing the support state (true for enabled, false - * for disabled) for compression algorithms. - * - * The i-th bit of the returned bitset corresponds to the i-th entry in the - * grpc_compression_algorithm enum. */ -uint32_t grpc_channel_args_compression_algorithm_get_states( - const grpc_channel_args* a); - -#endif /* GRPC_CORE_LIB_COMPRESSION_COMPRESSION_ARGS_H */ diff --git a/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc b/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc index ae2d745828..f719140c86 100644 --- a/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc +++ b/contrib/libs/grpc/src/core/lib/compression/compression_internal.cc @@ -23,181 +23,51 @@ #include <stdlib.h> #include <string.h> +#include <cstdint> + +#include "y_absl/container/inlined_vector.h" +#include "y_absl/strings/str_join.h" +#include "y_absl/strings/str_split.h" + #include <grpc/compression.h> -#include "src/core/lib/compression/algorithm_metadata.h" +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/slice/slice_utils.h" #include "src/core/lib/surface/api_trace.h" -#include "src/core/lib/transport/static_metadata.h" - -/* Interfaces related to MD */ - -grpc_message_compression_algorithm -grpc_message_compression_algorithm_from_slice(const grpc_slice& str) { - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_IDENTITY)) { - return GRPC_MESSAGE_COMPRESS_NONE; - } - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_DEFLATE)) { - return GRPC_MESSAGE_COMPRESS_DEFLATE; - } - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_GZIP)) { - return GRPC_MESSAGE_COMPRESS_GZIP; - } - return GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT; -} - -grpc_stream_compression_algorithm grpc_stream_compression_algorithm_from_slice( - const grpc_slice& str) { - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_IDENTITY)) { - return GRPC_STREAM_COMPRESS_NONE; - } - if (grpc_slice_eq_static_interned(str, GRPC_MDSTR_GZIP)) { - return GRPC_STREAM_COMPRESS_GZIP; - } - return GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT; -} -grpc_mdelem grpc_message_compression_encoding_mdelem( - grpc_message_compression_algorithm algorithm) { - switch (algorithm) { - case GRPC_MESSAGE_COMPRESS_NONE: - return GRPC_MDELEM_GRPC_ENCODING_IDENTITY; - case GRPC_MESSAGE_COMPRESS_DEFLATE: - return GRPC_MDELEM_GRPC_ENCODING_DEFLATE; - case GRPC_MESSAGE_COMPRESS_GZIP: - return GRPC_MDELEM_GRPC_ENCODING_GZIP; - default: - break; - } - return GRPC_MDNULL; -} +namespace grpc_core { -grpc_mdelem grpc_stream_compression_encoding_mdelem( - grpc_stream_compression_algorithm algorithm) { +const char* CompressionAlgorithmAsString(grpc_compression_algorithm algorithm) { switch (algorithm) { - case GRPC_STREAM_COMPRESS_NONE: - return GRPC_MDELEM_CONTENT_ENCODING_IDENTITY; - case GRPC_STREAM_COMPRESS_GZIP: - return GRPC_MDELEM_CONTENT_ENCODING_GZIP; - default: - break; - } - return GRPC_MDNULL; -} - -/* Interfaces performing transformation between compression algorithms and - * levels. */ -grpc_message_compression_algorithm -grpc_compression_algorithm_to_message_compression_algorithm( - grpc_compression_algorithm algo) { - switch (algo) { + case GRPC_COMPRESS_NONE: + return "identity"; case GRPC_COMPRESS_DEFLATE: - return GRPC_MESSAGE_COMPRESS_DEFLATE; + return "deflate"; case GRPC_COMPRESS_GZIP: - return GRPC_MESSAGE_COMPRESS_GZIP; + return "gzip"; + case GRPC_COMPRESS_ALGORITHMS_COUNT: default: - return GRPC_MESSAGE_COMPRESS_NONE; + return nullptr; } } -grpc_stream_compression_algorithm -grpc_compression_algorithm_to_stream_compression_algorithm( - grpc_compression_algorithm algo) { - switch (algo) { - case GRPC_COMPRESS_STREAM_GZIP: - return GRPC_STREAM_COMPRESS_GZIP; - default: - return GRPC_STREAM_COMPRESS_NONE; - } -} - -uint32_t grpc_compression_bitset_to_message_bitset(uint32_t bitset) { - return bitset & ((1u << GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT) - 1); -} - -uint32_t grpc_compression_bitset_to_stream_bitset(uint32_t bitset) { - uint32_t identity = (bitset & 1u); - uint32_t other_bits = - (bitset >> (GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT - 1)) & - ((1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 2); - return identity | other_bits; -} - -uint32_t grpc_compression_bitset_from_message_stream_compression_bitset( - uint32_t message_bitset, uint32_t stream_bitset) { - uint32_t offset_stream_bitset = - (stream_bitset & 1u) | - ((stream_bitset & (~1u)) << (GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT - 1)); - return message_bitset | offset_stream_bitset; -} - -int grpc_compression_algorithm_from_message_stream_compression_algorithm( - grpc_compression_algorithm* algorithm, - grpc_message_compression_algorithm message_algorithm, - grpc_stream_compression_algorithm stream_algorithm) { - if (message_algorithm != GRPC_MESSAGE_COMPRESS_NONE && - stream_algorithm != GRPC_STREAM_COMPRESS_NONE) { - *algorithm = GRPC_COMPRESS_NONE; - return 0; - } - if (message_algorithm == GRPC_MESSAGE_COMPRESS_NONE) { - switch (stream_algorithm) { - case GRPC_STREAM_COMPRESS_NONE: - *algorithm = GRPC_COMPRESS_NONE; - return 1; - case GRPC_STREAM_COMPRESS_GZIP: - *algorithm = GRPC_COMPRESS_STREAM_GZIP; - return 1; - default: - *algorithm = GRPC_COMPRESS_NONE; - return 0; - } +y_absl::optional<grpc_compression_algorithm> ParseCompressionAlgorithm( + y_absl::string_view algorithm) { + if (algorithm == "identity") { + return GRPC_COMPRESS_NONE; + } else if (algorithm == "deflate") { + return GRPC_COMPRESS_DEFLATE; + } else if (algorithm == "gzip") { + return GRPC_COMPRESS_GZIP; } else { - switch (message_algorithm) { - case GRPC_MESSAGE_COMPRESS_NONE: - *algorithm = GRPC_COMPRESS_NONE; - return 1; - case GRPC_MESSAGE_COMPRESS_DEFLATE: - *algorithm = GRPC_COMPRESS_DEFLATE; - return 1; - case GRPC_MESSAGE_COMPRESS_GZIP: - *algorithm = GRPC_COMPRESS_GZIP; - return 1; - default: - *algorithm = GRPC_COMPRESS_NONE; - return 0; - } - } -} - -/* Interfaces for message compression. */ - -int grpc_message_compression_algorithm_name( - grpc_message_compression_algorithm algorithm, const char** name) { - GRPC_API_TRACE( - "grpc_message_compression_algorithm_name(algorithm=%d, name=%p)", 2, - ((int)algorithm, name)); - switch (algorithm) { - case GRPC_MESSAGE_COMPRESS_NONE: - *name = "identity"; - return 1; - case GRPC_MESSAGE_COMPRESS_DEFLATE: - *name = "deflate"; - return 1; - case GRPC_MESSAGE_COMPRESS_GZIP: - *name = "gzip"; - return 1; - case GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT: - return 0; + return y_absl::nullopt; } - return 0; } -/* TODO(dgq): Add the ability to specify parameters to the individual - * compression algorithms */ -grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level( - grpc_compression_level level, uint32_t accepted_encodings) { +grpc_compression_algorithm +CompressionAlgorithmSet::CompressionAlgorithmForLevel( + grpc_compression_level level) const { GRPC_API_TRACE("grpc_message_compression_algorithm_for_level(level=%d)", 1, ((int)level)); if (level > GRPC_COMPRESS_LEVEL_HIGH) { @@ -206,10 +76,8 @@ grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level( abort(); } - const size_t num_supported = - grpc_core::BitCount(accepted_encodings) - 1; /* discard NONE */ - if (level == GRPC_COMPRESS_LEVEL_NONE || num_supported == 0) { - return GRPC_MESSAGE_COMPRESS_NONE; + if (level == GRPC_COMPRESS_LEVEL_NONE) { + return GRPC_COMPRESS_NONE; } GPR_ASSERT(level > 0); @@ -218,66 +86,138 @@ grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level( * compression. * This is simplistic and we will probably want to introduce other dimensions * in the future (cpu/memory cost, etc). */ - const grpc_message_compression_algorithm algos_ranking[] = { - GRPC_MESSAGE_COMPRESS_GZIP, GRPC_MESSAGE_COMPRESS_DEFLATE}; - - /* intersect algos_ranking with the supported ones keeping the ranked order */ - grpc_message_compression_algorithm - sorted_supported_algos[GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT]; - size_t algos_supported_idx = 0; - for (size_t i = 0; i < GPR_ARRAY_SIZE(algos_ranking); i++) { - const grpc_message_compression_algorithm alg = algos_ranking[i]; - for (size_t j = 0; j < num_supported; j++) { - if (grpc_core::GetBit(accepted_encodings, alg) == 1) { - /* if \a alg in supported */ - sorted_supported_algos[algos_supported_idx++] = alg; - break; - } + y_absl::InlinedVector<grpc_compression_algorithm, + GRPC_COMPRESS_ALGORITHMS_COUNT> + algos; + for (auto algo : {GRPC_COMPRESS_GZIP, GRPC_COMPRESS_DEFLATE}) { + if (set_.is_set(algo)) { + algos.push_back(algo); } - if (algos_supported_idx == num_supported) break; + } + + if (algos.empty()) { + return GRPC_COMPRESS_NONE; } switch (level) { case GRPC_COMPRESS_LEVEL_NONE: abort(); /* should have been handled already */ case GRPC_COMPRESS_LEVEL_LOW: - return sorted_supported_algos[0]; + return algos[0]; case GRPC_COMPRESS_LEVEL_MED: - return sorted_supported_algos[num_supported / 2]; + return algos[algos.size() / 2]; case GRPC_COMPRESS_LEVEL_HIGH: - return sorted_supported_algos[num_supported - 1]; + return algos.back(); default: abort(); }; } -int grpc_message_compression_algorithm_parse( - grpc_slice value, grpc_message_compression_algorithm* algorithm) { - if (grpc_slice_eq_static_interned(value, GRPC_MDSTR_IDENTITY)) { - *algorithm = GRPC_MESSAGE_COMPRESS_NONE; - return 1; - } else if (grpc_slice_eq_static_interned(value, GRPC_MDSTR_DEFLATE)) { - *algorithm = GRPC_MESSAGE_COMPRESS_DEFLATE; - return 1; - } else if (grpc_slice_eq_static_interned(value, GRPC_MDSTR_GZIP)) { - *algorithm = GRPC_MESSAGE_COMPRESS_GZIP; - return 1; +CompressionAlgorithmSet CompressionAlgorithmSet::FromUint32(uint32_t value) { + CompressionAlgorithmSet set; + for (size_t i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + if (value & (1u << i)) { + set.set_.set(i); + } + } + return set; +} + +CompressionAlgorithmSet CompressionAlgorithmSet::FromChannelArgs( + const grpc_channel_args* args) { + CompressionAlgorithmSet set; + static const uint32_t kEverything = + (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1; + if (args != nullptr) { + set = CompressionAlgorithmSet::FromUint32(grpc_channel_args_find_integer( + args, GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET, + grpc_integer_options{kEverything, 0, kEverything})); + set.Set(GRPC_COMPRESS_NONE); } else { - return 0; + set = CompressionAlgorithmSet::FromUint32(kEverything); } + return set; } -/* Interfaces for stream compression. */ +CompressionAlgorithmSet::CompressionAlgorithmSet() = default; -int grpc_stream_compression_algorithm_parse( - grpc_slice value, grpc_stream_compression_algorithm* algorithm) { - if (grpc_slice_eq_static_interned(value, GRPC_MDSTR_IDENTITY)) { - *algorithm = GRPC_STREAM_COMPRESS_NONE; - return 1; - } else if (grpc_slice_eq_static_interned(value, GRPC_MDSTR_GZIP)) { - *algorithm = GRPC_STREAM_COMPRESS_GZIP; - return 1; +CompressionAlgorithmSet::CompressionAlgorithmSet( + std::initializer_list<grpc_compression_algorithm> algorithms) { + for (auto algorithm : algorithms) { + Set(algorithm); + } +} + +bool CompressionAlgorithmSet::IsSet( + grpc_compression_algorithm algorithm) const { + size_t i = static_cast<size_t>(algorithm); + if (i < GRPC_COMPRESS_ALGORITHMS_COUNT) { + return set_.is_set(i); } else { - return 0; + return false; + } +} + +void CompressionAlgorithmSet::Set(grpc_compression_algorithm algorithm) { + size_t i = static_cast<size_t>(algorithm); + if (i < GRPC_COMPRESS_ALGORITHMS_COUNT) { + set_.set(i); + } +} + +TString CompressionAlgorithmSet::ToString() const { + y_absl::InlinedVector<const char*, GRPC_COMPRESS_ALGORITHMS_COUNT> segments; + for (size_t i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + if (set_.is_set(i)) { + segments.push_back(CompressionAlgorithmAsString( + static_cast<grpc_compression_algorithm>(i))); + } + } + return y_absl::StrJoin(segments, ", "); +} + +Slice CompressionAlgorithmSet::ToSlice() const { + return Slice::FromCopiedString(ToString()); +} + +CompressionAlgorithmSet CompressionAlgorithmSet::FromString( + y_absl::string_view str) { + CompressionAlgorithmSet set{GRPC_COMPRESS_NONE}; + for (auto algorithm : y_absl::StrSplit(str, ',')) { + auto parsed = + ParseCompressionAlgorithm(y_absl::StripAsciiWhitespace(algorithm)); + if (parsed.has_value()) { + set.Set(*parsed); + } + } + return set; +} + +uint32_t CompressionAlgorithmSet::ToLegacyBitmask() const { + uint32_t x = 0; + for (size_t i = 0; i < GRPC_COMPRESS_ALGORITHMS_COUNT; i++) { + if (set_.is_set(i)) { + x |= (1u << i); + } } + return x; } + +y_absl::optional<grpc_compression_algorithm> +DefaultCompressionAlgorithmFromChannelArgs(const grpc_channel_args* args) { + if (args == nullptr) return y_absl::nullopt; + for (size_t i = 0; i < args->num_args; i++) { + if (strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM) == + 0) { + if (args->args[i].type == GRPC_ARG_INTEGER) { + return static_cast<grpc_compression_algorithm>( + args->args[i].value.integer); + } else if (args->args[i].type == GRPC_ARG_STRING) { + return ParseCompressionAlgorithm(args->args[i].value.string); + } + } + } + return y_absl::nullopt; +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/compression/compression_internal.h b/contrib/libs/grpc/src/core/lib/compression/compression_internal.h index 6e1f51a198..f5440e6f95 100644 --- a/contrib/libs/grpc/src/core/lib/compression/compression_internal.h +++ b/contrib/libs/grpc/src/core/lib/compression/compression_internal.h @@ -21,77 +21,72 @@ #include <grpc/support/port_platform.h> -#include <grpc/compression.h> -#include <grpc/slice.h> - -#include "src/core/lib/gpr/useful.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - GRPC_MESSAGE_COMPRESS_NONE = 0, - GRPC_MESSAGE_COMPRESS_DEFLATE, - GRPC_MESSAGE_COMPRESS_GZIP, - /* TODO(ctiller): snappy */ - GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT -} grpc_message_compression_algorithm; - -/** Stream compression algorithms supported by gRPC */ -typedef enum { - GRPC_STREAM_COMPRESS_NONE = 0, - GRPC_STREAM_COMPRESS_GZIP, - GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT -} grpc_stream_compression_algorithm; - -/* Interfaces performing transformation between compression algorithms and - * levels. */ - -grpc_message_compression_algorithm -grpc_compression_algorithm_to_message_compression_algorithm( - grpc_compression_algorithm algo); - -grpc_stream_compression_algorithm -grpc_compression_algorithm_to_stream_compression_algorithm( - grpc_compression_algorithm algo); - -uint32_t grpc_compression_bitset_to_message_bitset(uint32_t bitset); +#include <initializer_list> -uint32_t grpc_compression_bitset_to_stream_bitset(uint32_t bitset); +#include "y_absl/strings/string_view.h" +#include "y_absl/types/optional.h" -uint32_t grpc_compression_bitset_from_message_stream_compression_bitset( - uint32_t message_bitset, uint32_t stream_bitset); - -int grpc_compression_algorithm_from_message_stream_compression_algorithm( - grpc_compression_algorithm* algorithm, - grpc_message_compression_algorithm message_algorithm, - grpc_stream_compression_algorithm stream_algorithm); - -/* Interfaces for message compression. */ - -int grpc_message_compression_algorithm_name( - grpc_message_compression_algorithm algorithm, const char** name); - -grpc_message_compression_algorithm grpc_message_compression_algorithm_for_level( - grpc_compression_level level, uint32_t accepted_encodings); - -int grpc_message_compression_algorithm_parse( - grpc_slice value, grpc_message_compression_algorithm* algorithm); - -/* Interfaces for stream compression. */ - -int grpc_stream_compression_algorithm_parse( - grpc_slice value, grpc_stream_compression_algorithm* algorithm); - -#ifdef __cplusplus -} -#endif +#include <grpc/compression.h> +#include <grpc/impl/codegen/grpc_types.h> +#include <grpc/slice.h> -inline int grpc_compression_options_is_algorithm_enabled_internal( - const grpc_compression_options* opts, - grpc_compression_algorithm algorithm) { - return grpc_core::GetBit(opts->enabled_algorithms_bitset, algorithm); -} +#include "src/core/lib/gprpp/bitset.h" +#include "src/core/lib/slice/slice.h" + +namespace grpc_core { + +// Given a string naming a compression algorithm, return the corresponding enum +// or nullopt on error. +y_absl::optional<grpc_compression_algorithm> ParseCompressionAlgorithm( + y_absl::string_view algorithm); +// Convert a compression algorithm to a string. Returns nullptr if a name is not +// known. +const char* CompressionAlgorithmAsString(grpc_compression_algorithm algorithm); +// Retrieve the default compression algorithm from channel args, return nullopt +// if not found. +y_absl::optional<grpc_compression_algorithm> +DefaultCompressionAlgorithmFromChannelArgs(const grpc_channel_args* args); + +// A set of grpc_compression_algorithm values. +class CompressionAlgorithmSet { + public: + // Construct from a uint32_t bitmask - bit 0 => algorithm 0, bit 1 => + // algorithm 1, etc. + static CompressionAlgorithmSet FromUint32(uint32_t value); + // Locate in channel args and construct from the found value. + static CompressionAlgorithmSet FromChannelArgs(const grpc_channel_args* args); + // Parse a string of comma-separated compression algorithms. + static CompressionAlgorithmSet FromString(y_absl::string_view str); + // Construct an empty set. + CompressionAlgorithmSet(); + // Construct from a std::initializer_list of grpc_compression_algorithm + // values. + CompressionAlgorithmSet( + std::initializer_list<grpc_compression_algorithm> algorithms); + + // Given a compression level, choose an appropriate algorithm from this set. + grpc_compression_algorithm CompressionAlgorithmForLevel( + grpc_compression_level level) const; + // Return true if this set contains algorithm, false otherwise. + bool IsSet(grpc_compression_algorithm algorithm) const; + // Add algorithm to this set. + void Set(grpc_compression_algorithm algorithm); + + // Return a comma separated string of the algorithms in this set. + TString ToString() const; + Slice ToSlice() const; + + // Return a bitmask of the algorithms in this set. + uint32_t ToLegacyBitmask() const; + + bool operator==(const CompressionAlgorithmSet& other) const { + return set_ == other.set_; + } + + private: + BitSet<GRPC_COMPRESS_ALGORITHMS_COUNT> set_; +}; + +} // namespace grpc_core #endif /* GRPC_CORE_LIB_COMPRESSION_COMPRESSION_INTERNAL_H */ diff --git a/contrib/libs/grpc/src/core/lib/compression/message_compress.cc b/contrib/libs/grpc/src/core/lib/compression/message_compress.cc index 797d5edfe8..b88f5103c7 100644 --- a/contrib/libs/grpc/src/core/lib/compression/message_compress.cc +++ b/contrib/libs/grpc/src/core/lib/compression/message_compress.cc @@ -148,25 +148,25 @@ static int copy(grpc_slice_buffer* input, grpc_slice_buffer* output) { return 1; } -static int compress_inner(grpc_message_compression_algorithm algorithm, +static int compress_inner(grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output) { switch (algorithm) { - case GRPC_MESSAGE_COMPRESS_NONE: + case GRPC_COMPRESS_NONE: /* the fallback path always needs to be send uncompressed: we simply rely on that here */ return 0; - case GRPC_MESSAGE_COMPRESS_DEFLATE: + case GRPC_COMPRESS_DEFLATE: return zlib_compress(input, output, 0); - case GRPC_MESSAGE_COMPRESS_GZIP: + case GRPC_COMPRESS_GZIP: return zlib_compress(input, output, 1); - case GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT: + case GRPC_COMPRESS_ALGORITHMS_COUNT: break; } gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm); return 0; } -int grpc_msg_compress(grpc_message_compression_algorithm algorithm, +int grpc_msg_compress(grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output) { if (!compress_inner(algorithm, input, output)) { copy(input, output); @@ -175,16 +175,16 @@ int grpc_msg_compress(grpc_message_compression_algorithm algorithm, return 1; } -int grpc_msg_decompress(grpc_message_compression_algorithm algorithm, +int grpc_msg_decompress(grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output) { switch (algorithm) { - case GRPC_MESSAGE_COMPRESS_NONE: + case GRPC_COMPRESS_NONE: return copy(input, output); - case GRPC_MESSAGE_COMPRESS_DEFLATE: + case GRPC_COMPRESS_DEFLATE: return zlib_decompress(input, output, 0); - case GRPC_MESSAGE_COMPRESS_GZIP: + case GRPC_COMPRESS_GZIP: return zlib_decompress(input, output, 1); - case GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT: + case GRPC_COMPRESS_ALGORITHMS_COUNT: break; } gpr_log(GPR_ERROR, "invalid compression algorithm %d", algorithm); diff --git a/contrib/libs/grpc/src/core/lib/compression/message_compress.h b/contrib/libs/grpc/src/core/lib/compression/message_compress.h index 91654e47e3..b84120c19e 100644 --- a/contrib/libs/grpc/src/core/lib/compression/message_compress.h +++ b/contrib/libs/grpc/src/core/lib/compression/message_compress.h @@ -28,13 +28,13 @@ /* compress 'input' to 'output' using 'algorithm'. On success, appends compressed slices to output and returns 1. On failure, appends uncompressed slices to output and returns 0. */ -int grpc_msg_compress(grpc_message_compression_algorithm algorithm, +int grpc_msg_compress(grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output); /* decompress 'input' to 'output' using 'algorithm'. On success, appends slices to output and returns 1. On failure, output is unchanged, and returns 0. */ -int grpc_msg_decompress(grpc_message_compression_algorithm algorithm, +int grpc_msg_decompress(grpc_compression_algorithm algorithm, grpc_slice_buffer* input, grpc_slice_buffer* output); #endif /* GRPC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H */ diff --git a/contrib/libs/grpc/src/core/lib/compression/stream_compression.cc b/contrib/libs/grpc/src/core/lib/compression/stream_compression.cc deleted file mode 100644 index d827aeb938..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/stream_compression.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * 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 <grpc/support/port_platform.h> - -#include "src/core/lib/compression/stream_compression.h" - -#include <grpc/support/log.h> - -#include "src/core/lib/compression/stream_compression_gzip.h" -#include "src/core/lib/slice/slice_utils.h" - -extern const grpc_stream_compression_vtable - grpc_stream_compression_identity_vtable; - -bool grpc_stream_compress(grpc_stream_compression_context* ctx, - grpc_slice_buffer* in, grpc_slice_buffer* out, - size_t* output_size, size_t max_output_size, - grpc_stream_compression_flush flush) { - return ctx->vtable->compress(ctx, in, out, output_size, max_output_size, - flush); -} - -bool grpc_stream_decompress(grpc_stream_compression_context* ctx, - grpc_slice_buffer* in, grpc_slice_buffer* out, - size_t* output_size, size_t max_output_size, - bool* end_of_context) { - return ctx->vtable->decompress(ctx, in, out, output_size, max_output_size, - end_of_context); -} - -grpc_stream_compression_context* grpc_stream_compression_context_create( - grpc_stream_compression_method method) { - switch (method) { - case GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS: - case GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS: - return grpc_stream_compression_identity_vtable.context_create(method); - case GRPC_STREAM_COMPRESSION_GZIP_COMPRESS: - case GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS: - return grpc_stream_compression_gzip_vtable.context_create(method); - default: - gpr_log(GPR_ERROR, "Unknown stream compression method: %d", method); - return nullptr; - } -} - -void grpc_stream_compression_context_destroy( - grpc_stream_compression_context* ctx) { - ctx->vtable->context_destroy(ctx); -} - -int grpc_stream_compression_method_parse( - grpc_slice value, bool is_compress, - grpc_stream_compression_method* method) { - if (grpc_slice_eq_static_interned(value, GRPC_MDSTR_IDENTITY)) { - *method = is_compress ? GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS - : GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS; - return 1; - } else if (grpc_slice_eq_static_interned(value, GRPC_MDSTR_GZIP)) { - *method = is_compress ? GRPC_STREAM_COMPRESSION_GZIP_COMPRESS - : GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS; - return 1; - } else { - return 0; - } -} diff --git a/contrib/libs/grpc/src/core/lib/compression/stream_compression.h b/contrib/libs/grpc/src/core/lib/compression/stream_compression.h deleted file mode 100644 index cfa1bf00d9..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/stream_compression.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_H -#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_H - -#include <grpc/support/port_platform.h> - -#include <stdbool.h> - -#include <zlib.h> - -#include <grpc/slice_buffer.h> - -#include "src/core/lib/transport/static_metadata.h" - -typedef struct grpc_stream_compression_vtable grpc_stream_compression_vtable; - -/* Stream compression/decompression context */ -typedef struct grpc_stream_compression_context { - const grpc_stream_compression_vtable* vtable; -} grpc_stream_compression_context; - -typedef enum grpc_stream_compression_method { - GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS = 0, - GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS, - GRPC_STREAM_COMPRESSION_GZIP_COMPRESS, - GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS, - GRPC_STREAM_COMPRESSION_METHOD_COUNT -} grpc_stream_compression_method; - -typedef enum grpc_stream_compression_flush { - GRPC_STREAM_COMPRESSION_FLUSH_NONE = 0, - GRPC_STREAM_COMPRESSION_FLUSH_SYNC, - GRPC_STREAM_COMPRESSION_FLUSH_FINISH, - GRPC_STREAM_COMPRESSION_FLUSH_COUNT -} grpc_stream_compression_flush; - -struct grpc_stream_compression_vtable { - bool (*compress)(grpc_stream_compression_context* ctx, grpc_slice_buffer* in, - grpc_slice_buffer* out, size_t* output_size, - size_t max_output_size, grpc_stream_compression_flush flush); - bool (*decompress)(grpc_stream_compression_context* ctx, - grpc_slice_buffer* in, grpc_slice_buffer* out, - size_t* output_size, size_t max_output_size, - bool* end_of_context); - grpc_stream_compression_context* (*context_create)( - grpc_stream_compression_method method); - void (*context_destroy)(grpc_stream_compression_context* ctx); -}; - -/** - * Compress bytes provided in \a in with a given context, with an optional flush - * at the end of compression. Emits at most \a max_output_size compressed bytes - * into \a out. If all the bytes in input buffer \a in are depleted and \a flush - * is not GRPC_STREAM_COMPRESSION_FLUSH_NONE, the corresponding flush method is - * executed. The total number of bytes emitted is outputted in \a output_size. - * - * A SYNC flush indicates that the entire messages in \a in can be decompressed - * from \a out. A FINISH flush implies a SYNC flush, and that any further - * compression will not be dependent on the state of the current context and any - * previous compressed bytes. It allows corresponding decompression context to - * be dropped when reaching this boundary. - */ -bool grpc_stream_compress(grpc_stream_compression_context* ctx, - grpc_slice_buffer* in, grpc_slice_buffer* out, - size_t* output_size, size_t max_output_size, - grpc_stream_compression_flush flush); - -/** - * Decompress bytes provided in \a in with a given context. Emits at most \a - * max_output_size decompressed bytes into \a out. If decompression process - * reached the end of a gzip stream, \a end_of_context is set to true; otherwise - * it is set to false. The total number of bytes emitted is outputted in \a - * output_size. - */ -bool grpc_stream_decompress(grpc_stream_compression_context* ctx, - grpc_slice_buffer* in, grpc_slice_buffer* out, - size_t* output_size, size_t max_output_size, - bool* end_of_context); - -/** - * Creates a stream compression context. \a pending_bytes_buffer is the input - * buffer for compression/decompression operations. \a method specifies whether - * the context is for compression or decompression. - */ -grpc_stream_compression_context* grpc_stream_compression_context_create( - grpc_stream_compression_method method); - -/** - * Destroys a stream compression context. - */ -void grpc_stream_compression_context_destroy( - grpc_stream_compression_context* ctx); - -/** - * Parse stream compression method based on algorithm name - */ -int grpc_stream_compression_method_parse( - grpc_slice value, bool is_compress, grpc_stream_compression_method* method); - -#endif // GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_H diff --git a/contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.cc b/contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.cc deleted file mode 100644 index 92a44eab64..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.cc +++ /dev/null @@ -1,231 +0,0 @@ -/* - * - * 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 <grpc/support/port_platform.h> - -#include "src/core/lib/compression/stream_compression_gzip.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -#include "src/core/lib/iomgr/exec_ctx.h" -#include "src/core/lib/slice/slice_internal.h" - -#define OUTPUT_BLOCK_SIZE (1024) - -typedef struct grpc_stream_compression_context_gzip { - grpc_stream_compression_context base; - - z_stream zs; - int (*flate)(z_stream* zs, int flush); -} grpc_stream_compression_context_gzip; - -static bool gzip_flate(grpc_stream_compression_context_gzip* ctx, - grpc_slice_buffer* in, grpc_slice_buffer* out, - size_t* output_size, size_t max_output_size, int flush, - bool* end_of_context) { - GPR_ASSERT(flush == 0 || flush == Z_SYNC_FLUSH || flush == Z_FINISH); - /* Full flush is not allowed when inflating. */ - GPR_ASSERT(!(ctx->flate == inflate && (flush == Z_FINISH))); - - grpc_core::ExecCtx exec_ctx; - int r; - bool eoc = false; - size_t original_max_output_size = max_output_size; - while (max_output_size > 0 && (in->length > 0 || flush) && !eoc) { - size_t slice_size = max_output_size < OUTPUT_BLOCK_SIZE ? max_output_size - : OUTPUT_BLOCK_SIZE; - grpc_slice slice_out = GRPC_SLICE_MALLOC(slice_size); - ctx->zs.avail_out = static_cast<uInt>(slice_size); - ctx->zs.next_out = GRPC_SLICE_START_PTR(slice_out); - while (ctx->zs.avail_out > 0 && in->length > 0 && !eoc) { - grpc_slice* slice = grpc_slice_buffer_peek_first(in); - ctx->zs.avail_in = static_cast<uInt> GRPC_SLICE_LENGTH(*slice); - ctx->zs.next_in = GRPC_SLICE_START_PTR(*slice); - r = ctx->flate(&ctx->zs, Z_NO_FLUSH); - if (r < 0 && r != Z_BUF_ERROR) { - gpr_log(GPR_ERROR, "zlib error (%d)", r); - grpc_slice_unref_internal(slice_out); - grpc_slice_buffer_remove_first(in); - return false; - } else if (r == Z_STREAM_END && ctx->flate == inflate) { - eoc = true; - } - if (ctx->zs.avail_in > 0) { - grpc_slice_buffer_sub_first( - in, GRPC_SLICE_LENGTH(*slice) - ctx->zs.avail_in, - GRPC_SLICE_LENGTH(*slice)); - } else { - grpc_slice_buffer_remove_first(in); - } - } - if (flush != 0 && ctx->zs.avail_out > 0 && !eoc) { - GPR_ASSERT(in->length == 0); - r = ctx->flate(&ctx->zs, flush); - if (flush == Z_SYNC_FLUSH) { - switch (r) { - case Z_OK: - /* Maybe flush is not complete; just made some partial progress. */ - if (ctx->zs.avail_out > 0) { - flush = 0; - } - break; - case Z_BUF_ERROR: - case Z_STREAM_END: - flush = 0; - break; - default: - gpr_log(GPR_ERROR, "zlib error (%d)", r); - grpc_slice_unref_internal(slice_out); - - return false; - } - } else if (flush == Z_FINISH) { - switch (r) { - case Z_OK: - case Z_BUF_ERROR: - /* Wait for the next loop to assign additional output space. */ - GPR_ASSERT(ctx->zs.avail_out == 0); - break; - case Z_STREAM_END: - flush = 0; - break; - default: - gpr_log(GPR_ERROR, "zlib error (%d)", r); - grpc_slice_unref_internal(slice_out); - - return false; - } - } - } - - if (ctx->zs.avail_out == 0) { - grpc_slice_buffer_add(out, slice_out); - } else if (ctx->zs.avail_out < slice_size) { - size_t len = GRPC_SLICE_LENGTH(slice_out); - GRPC_SLICE_SET_LENGTH(slice_out, len - ctx->zs.avail_out); - grpc_slice_buffer_add(out, slice_out); - } else { - grpc_slice_unref_internal(slice_out); - } - max_output_size -= (slice_size - ctx->zs.avail_out); - } - - if (end_of_context) { - *end_of_context = eoc; - } - if (output_size) { - *output_size = original_max_output_size - max_output_size; - } - return true; -} - -static bool grpc_stream_compress_gzip(grpc_stream_compression_context* ctx, - grpc_slice_buffer* in, - grpc_slice_buffer* out, - size_t* output_size, - size_t max_output_size, - grpc_stream_compression_flush flush) { - if (ctx == nullptr) { - return false; - } - grpc_stream_compression_context_gzip* gzip_ctx = - reinterpret_cast<grpc_stream_compression_context_gzip*>(ctx); - GPR_ASSERT(gzip_ctx->flate == deflate); - int gzip_flush; - switch (flush) { - case GRPC_STREAM_COMPRESSION_FLUSH_NONE: - gzip_flush = 0; - break; - case GRPC_STREAM_COMPRESSION_FLUSH_SYNC: - gzip_flush = Z_SYNC_FLUSH; - break; - case GRPC_STREAM_COMPRESSION_FLUSH_FINISH: - gzip_flush = Z_FINISH; - break; - default: - gzip_flush = 0; - } - return gzip_flate(gzip_ctx, in, out, output_size, max_output_size, gzip_flush, - nullptr); -} - -static bool grpc_stream_decompress_gzip(grpc_stream_compression_context* ctx, - grpc_slice_buffer* in, - grpc_slice_buffer* out, - size_t* output_size, - size_t max_output_size, - bool* end_of_context) { - if (ctx == nullptr) { - return false; - } - grpc_stream_compression_context_gzip* gzip_ctx = - reinterpret_cast<grpc_stream_compression_context_gzip*>(ctx); - GPR_ASSERT(gzip_ctx->flate == inflate); - return gzip_flate(gzip_ctx, in, out, output_size, max_output_size, - Z_SYNC_FLUSH, end_of_context); -} - -static grpc_stream_compression_context* -grpc_stream_compression_context_create_gzip( - grpc_stream_compression_method method) { - GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_GZIP_COMPRESS || - method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); - grpc_stream_compression_context_gzip* gzip_ctx = - static_cast<grpc_stream_compression_context_gzip*>( - gpr_zalloc(sizeof(grpc_stream_compression_context_gzip))); - int r; - if (gzip_ctx == nullptr) { - return nullptr; - } - if (method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS) { - r = inflateInit2(&gzip_ctx->zs, 0x1F); - gzip_ctx->flate = inflate; - } else { - r = deflateInit2(&gzip_ctx->zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8, - Z_DEFAULT_STRATEGY); - gzip_ctx->flate = deflate; - } - if (r != Z_OK) { - gpr_free(gzip_ctx); - return nullptr; - } - - gzip_ctx->base.vtable = &grpc_stream_compression_gzip_vtable; - return reinterpret_cast<grpc_stream_compression_context*>(gzip_ctx); -} - -static void grpc_stream_compression_context_destroy_gzip( - grpc_stream_compression_context* ctx) { - if (ctx == nullptr) { - return; - } - grpc_stream_compression_context_gzip* gzip_ctx = - reinterpret_cast<grpc_stream_compression_context_gzip*>(ctx); - if (gzip_ctx->flate == inflate) { - inflateEnd(&gzip_ctx->zs); - } else { - deflateEnd(&gzip_ctx->zs); - } - gpr_free(ctx); -} - -const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable = { - grpc_stream_compress_gzip, grpc_stream_decompress_gzip, - grpc_stream_compression_context_create_gzip, - grpc_stream_compression_context_destroy_gzip}; diff --git a/contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.h b/contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.h deleted file mode 100644 index 0f3be6d306..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H -#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H - -#include <grpc/support/port_platform.h> - -#include "src/core/lib/compression/stream_compression.h" - -extern const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable; - -#endif // GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H diff --git a/contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.cc b/contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.cc deleted file mode 100644 index adef4c44cd..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.cc +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * 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 <grpc/support/port_platform.h> - -#include "src/core/lib/compression/stream_compression_identity.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -#include "src/core/lib/slice/slice_internal.h" - -#define OUTPUT_BLOCK_SIZE (1024) - -/* Singleton context used for all identity streams. */ -static grpc_stream_compression_context identity_ctx = { - &grpc_stream_compression_identity_vtable}; - -static void grpc_stream_compression_pass_through(grpc_slice_buffer* in, - grpc_slice_buffer* out, - size_t* output_size, - size_t max_output_size) { - if (max_output_size >= in->length) { - if (output_size) { - *output_size = in->length; - } - grpc_slice_buffer_move_into(in, out); - } else { - if (output_size) { - *output_size = max_output_size; - } - grpc_slice_buffer_move_first(in, max_output_size, out); - } -} - -static bool grpc_stream_compress_identity( - grpc_stream_compression_context* ctx, grpc_slice_buffer* in, - grpc_slice_buffer* out, size_t* output_size, size_t max_output_size, - grpc_stream_compression_flush /*flush*/) { - if (ctx == nullptr) { - return false; - } - grpc_stream_compression_pass_through(in, out, output_size, max_output_size); - return true; -} - -static bool grpc_stream_decompress_identity( - grpc_stream_compression_context* ctx, grpc_slice_buffer* in, - grpc_slice_buffer* out, size_t* output_size, size_t max_output_size, - bool* end_of_context) { - if (ctx == nullptr) { - return false; - } - grpc_stream_compression_pass_through(in, out, output_size, max_output_size); - if (end_of_context) { - *end_of_context = false; - } - return true; -} - -static grpc_stream_compression_context* -grpc_stream_compression_context_create_identity( - grpc_stream_compression_method method) { - GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS || - method == GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS); - /* No context needed in this case. Use fake context instead. */ - return &identity_ctx; -} - -static void grpc_stream_compression_context_destroy_identity( - grpc_stream_compression_context* /*ctx*/) {} - -const grpc_stream_compression_vtable grpc_stream_compression_identity_vtable = { - grpc_stream_compress_identity, grpc_stream_decompress_identity, - grpc_stream_compression_context_create_identity, - grpc_stream_compression_context_destroy_identity}; diff --git a/contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.h b/contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.h deleted file mode 100644 index 9c3693c744..0000000000 --- a/contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_IDENTITY_H -#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_IDENTITY_H - -#include <grpc/support/port_platform.h> - -#include "src/core/lib/compression/stream_compression.h" - -extern const grpc_stream_compression_vtable - grpc_stream_compression_identity_vtable; - -#endif // GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_IDENTITY_H diff --git a/contrib/libs/grpc/src/core/lib/gpr/useful.h b/contrib/libs/grpc/src/core/lib/gpr/useful.h index 2e0025752b..b151ca3738 100644 --- a/contrib/libs/grpc/src/core/lib/gpr/useful.h +++ b/contrib/libs/grpc/src/core/lib/gpr/useful.h @@ -106,6 +106,10 @@ constexpr size_t HashPointer(T* p, size_t range) { range; } +inline uint32_t MixHash32(uint32_t a, uint32_t b) { + return RotateLeft(a, 2u) ^ b; +} + } // namespace grpc_core #define GPR_ARRAY_SIZE(array) (sizeof(array) / sizeof(*(array))) diff --git a/contrib/libs/grpc/src/core/lib/gprpp/bitset.h b/contrib/libs/grpc/src/core/lib/gprpp/bitset.h index 1732f4e0e4..dded433d08 100644 --- a/contrib/libs/grpc/src/core/lib/gprpp/bitset.h +++ b/contrib/libs/grpc/src/core/lib/gprpp/bitset.h @@ -146,6 +146,13 @@ class BitSet { return count; } + bool operator==(const BitSet& other) const { + for (size_t i = 0; i < kUnits; i++) { + if (units_[i] != other.units_[i]) return false; + } + return true; + } + private: // Given a bit index, return which unit it's stored in. static constexpr size_t unit_for(size_t bit) { return bit / kUnitBits; } diff --git a/contrib/libs/grpc/src/core/lib/gprpp/chunked_vector.h b/contrib/libs/grpc/src/core/lib/gprpp/chunked_vector.h index 256fa908b4..c415427621 100644 --- a/contrib/libs/grpc/src/core/lib/gprpp/chunked_vector.h +++ b/contrib/libs/grpc/src/core/lib/gprpp/chunked_vector.h @@ -17,8 +17,10 @@ #include <grpc/support/port_platform.h> -#include "src/core/lib/gprpp/arena.h" +#include <cstddef> + #include "src/core/lib/gprpp/manual_constructor.h" +#include "src/core/lib/resource_quota/arena.h" namespace grpc_core { @@ -48,8 +50,9 @@ class ChunkedVector { } ChunkedVector(const ChunkedVector& other) : ChunkedVector(other.arena_, other.begin(), other.end()) {} - ChunkedVector& operator=(ChunkedVector other) { - Swap(&other); + ChunkedVector& operator=(const ChunkedVector& other) { + ChunkedVector tmp(other); + Swap(&tmp); return *this; } ChunkedVector(ChunkedVector&& other) noexcept @@ -113,6 +116,12 @@ class ChunkedVector { public: ForwardIterator(Chunk* chunk, size_t n) : chunk_(chunk), n_(n) {} + using difference_type = std::ptrdiff_t; + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using pointer = T*; + using reference = T&; + T& operator*() const { return *chunk_->data[n_]; } T* operator->() const { return &*chunk_->data[n_]; } ForwardIterator& operator++() { @@ -123,6 +132,11 @@ class ChunkedVector { } return *this; } + ForwardIterator& operator++(int) { + ForwardIterator tmp = *this; + ++*this; + return tmp; + } bool operator==(const ForwardIterator& other) const { return chunk_ == other.chunk_ && n_ == other.n_; } @@ -131,6 +145,8 @@ class ChunkedVector { } private: + friend class ChunkedVector; + Chunk* chunk_; size_t n_; }; @@ -140,6 +156,8 @@ class ChunkedVector { public: ConstForwardIterator(const Chunk* chunk, size_t n) : chunk_(chunk), n_(n) {} + using iterator_category = std::forward_iterator_tag; + const T& operator*() const { return *chunk_->data[n_]; } const T* operator->() const { return &*chunk_->data[n_]; } ConstForwardIterator& operator++() { @@ -150,6 +168,11 @@ class ChunkedVector { } return *this; } + ConstForwardIterator& operator++(int) { + ConstForwardIterator tmp = *this; + ++*this; + return tmp; + } bool operator==(const ConstForwardIterator& other) const { return chunk_ == other.chunk_ && n_ == other.n_; } @@ -186,6 +209,25 @@ class ChunkedVector { return n; } + // Return true if the vector is empty. + bool empty() const { return first_ == nullptr || first_->count == 0; } + + void SetEnd(ForwardIterator it) { + if (it == end()) return; + Chunk* chunk = it.chunk_; + for (size_t i = it.n_; i < chunk->count; i++) { + chunk->data[i].Destroy(); + } + chunk->count = it.n_; + append_ = chunk; + while ((chunk = chunk->next) != nullptr) { + for (size_t i = 0; i < chunk->count; i++) { + chunk->data[i].Destroy(); + } + chunk->count = 0; + } + } + private: ManualConstructor<T>* AppendSlot() { if (append_ == nullptr) { diff --git a/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc b/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc index cbc25deae6..d260b3760c 100644 --- a/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc +++ b/contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc @@ -85,6 +85,8 @@ const char* GetStatusIntPropertyUrl(StatusIntProperty key) { return TYPE_URL(TYPE_INT_TAG "channel_connectivity_state"); case StatusIntProperty::kLbPolicyDrop: return TYPE_URL(TYPE_INT_TAG "lb_policy_drop"); + case StatusIntProperty::kStreamNetworkState: + return TYPE_URL(TYPE_INT_TAG "stream_network_state"); } GPR_UNREACHABLE_CODE(return "unknown"); } @@ -161,7 +163,7 @@ std::vector<y_absl::Status> ParseChildren(y_absl::Cord children) { y_absl::Status StatusCreate(y_absl::StatusCode code, y_absl::string_view msg, const DebugLocation& location, - std::initializer_list<y_absl::Status> children) { + std::vector<y_absl::Status> children) { y_absl::Status s(code, msg); if (location.file() != nullptr) { StatusSetStr(&s, StatusStrProperty::kFile, location.file()); @@ -232,7 +234,10 @@ y_absl::optional<y_absl::Time> StatusGetTime(const y_absl::Status& status, if (p.has_value()) { y_absl::optional<y_absl::string_view> sv = p->TryFlat(); if (sv.has_value()) { - return *reinterpret_cast<const y_absl::Time*>(sv->data()); + // copy the content before casting to avoid misaligned address access + alignas(y_absl::Time) char buf[sizeof(const y_absl::Time)]; + memcpy(buf, sv->data(), sizeof(const y_absl::Time)); + return *reinterpret_cast<const y_absl::Time*>(buf); } else { TString s = TString(*p); return *reinterpret_cast<const y_absl::Time*>(s.c_str()); @@ -381,32 +386,8 @@ y_absl::Status StatusFromProto(google_rpc_Status* msg) { return status; } -uintptr_t StatusAllocPtr(y_absl::Status s) { - // This relies the fact that y_absl::Status has only one member, StatusRep* - // so the sizeof(y_absl::Status) has the same size of intptr_t and StatusRep* - // can be stolen using placement allocation. - static_assert(sizeof(intptr_t) == sizeof(y_absl::Status), - "y_absl::Status should be as big as intptr_t"); - // This does two things; - // 1. Copies StatusRep* of y_absl::Status to ptr - // 2. Increases the counter of StatusRep if it's not inlined - uintptr_t ptr; - new (&ptr) y_absl::Status(s); - return ptr; -} - -void StatusFreePtr(uintptr_t ptr) { - // Decreases the counter of StatusRep if it's not inlined. - reinterpret_cast<y_absl::Status*>(&ptr)->~Status(); -} - -y_absl::Status StatusGetFromPtr(uintptr_t ptr) { - // Constructs Status from ptr having the address of StatusRep. - return *reinterpret_cast<y_absl::Status*>(&ptr); -} - uintptr_t StatusAllocHeapPtr(y_absl::Status s) { - if (s.ok()) return kOkStatusPtr; + if (s.ok()) return 0; y_absl::Status* ptr = new y_absl::Status(s); return reinterpret_cast<uintptr_t>(ptr); } @@ -417,13 +398,24 @@ void StatusFreeHeapPtr(uintptr_t ptr) { } y_absl::Status StatusGetFromHeapPtr(uintptr_t ptr) { - if (ptr == kOkStatusPtr) { + if (ptr == 0) { return y_absl::OkStatus(); } else { return *reinterpret_cast<y_absl::Status*>(ptr); } } +y_absl::Status StatusMoveFromHeapPtr(uintptr_t ptr) { + if (ptr == 0) { + return y_absl::OkStatus(); + } else { + y_absl::Status* s = reinterpret_cast<y_absl::Status*>(ptr); + y_absl::Status ret = std::move(*s); + delete s; + return ret; + } +} + } // namespace internal } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/gprpp/status_helper.h b/contrib/libs/grpc/src/core/lib/gprpp/status_helper.h index b66ed35d26..9580fb0ad8 100644 --- a/contrib/libs/grpc/src/core/lib/gprpp/status_helper.h +++ b/contrib/libs/grpc/src/core/lib/gprpp/status_helper.h @@ -37,7 +37,6 @@ 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 y_absl::Status is done. enum class StatusIntProperty { /// 'errno' from the operating system kErrorNo, @@ -72,10 +71,11 @@ enum class StatusIntProperty { ChannelConnectivityState, /// LB policy drop kLbPolicyDrop, + /// stream network state + kStreamNetworkState, }; /// This enum should have the same value of grpc_error_strs -// TODO(veblush): Use camel-case names once migration to y_absl::Status is done. enum class StatusStrProperty { /// top-level textual description of this error kDescription, @@ -110,7 +110,7 @@ enum class StatusTimeProperty { /// Creates a status with given additional information y_absl::Status StatusCreate( y_absl::StatusCode code, y_absl::string_view msg, const DebugLocation& location, - std::initializer_list<y_absl::Status> children) GRPC_MUST_USE_RESULT; + std::vector<y_absl::Status> children) GRPC_MUST_USE_RESULT; /// Sets the int property to the status void StatusSetInt(y_absl::Status* status, StatusIntProperty key, intptr_t value); @@ -160,22 +160,6 @@ google_rpc_Status* StatusToProto(const y_absl::Status& status, /// This is for internal implementation & test only y_absl::Status StatusFromProto(google_rpc_Status* msg) GRPC_MUST_USE_RESULT; -/// The same value of internal::StatusAllocPtr(y_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(y_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. -y_absl::Status StatusGetFromPtr(uintptr_t ptr); - /// Returns ptr that is allocated in the heap memory and the given status is /// copied into. This ptr can be used to get Status later and should be /// freed by StatusFreeHeapPtr. This can be 0 in case of OkStatus. @@ -187,6 +171,9 @@ void StatusFreeHeapPtr(uintptr_t ptr); /// Get the status from a heap ptr. y_absl::Status StatusGetFromHeapPtr(uintptr_t ptr); +/// Move the status from a heap ptr. (GetFrom & FreeHeap) +y_absl::Status StatusMoveFromHeapPtr(uintptr_t ptr); + } // namespace internal } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/gprpp/table.h b/contrib/libs/grpc/src/core/lib/gprpp/table.h index 570a3d5d9b..41b7179a14 100644 --- a/contrib/libs/grpc/src/core/lib/gprpp/table.h +++ b/contrib/libs/grpc/src/core/lib/gprpp/table.h @@ -311,6 +311,12 @@ class Table { // Count the number of set fields in the table size_t count() const { return present_bits_.count(); } + // Check if the table is completely empty + bool empty() const { return present_bits_.none(); } + + // Clear all elements in the table. + void ClearAll() { ClearAllImpl(y_absl::make_index_sequence<sizeof...(Ts)>()); } + private: // Bit field for which elements of the table are set (true) or un-set (false, // the default) -- one bit for each type in Ts. @@ -412,6 +418,11 @@ class Table { table_detail::do_these_things<int>({(CallIf<I>(&f), 1)...}); } + template <size_t... I> + void ClearAllImpl(y_absl::index_sequence<I...>) { + table_detail::do_these_things<int>({(clear<I>(), 1)...}); + } + // Bit field indicating which elements are set. GPR_NO_UNIQUE_ADDRESS PresentBits present_bits_; // The memory to store the elements themselves. diff --git a/contrib/libs/grpc/src/core/lib/http/httpcli.cc b/contrib/libs/grpc/src/core/lib/http/httpcli.cc index 9b53dc1f1f..d0295b69bf 100644 --- a/contrib/libs/grpc/src/core/lib/http/httpcli.cc +++ b/contrib/libs/grpc/src/core/lib/http/httpcli.cc @@ -24,6 +24,7 @@ #include <util/generic/string.h> +#include "y_absl/functional/bind_front.h" #include "y_absl/strings/str_format.h" #include "y_absl/strings/string_view.h" @@ -44,6 +45,7 @@ #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/resource_quota/api.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/transport/error_utils.h" namespace grpc_core { namespace { @@ -55,8 +57,8 @@ class InternalRequest { ResourceQuotaRefPtr resource_quota, y_absl::string_view host, y_absl::string_view ssl_host_override, grpc_millis deadline, const grpc_httpcli_handshaker* handshaker, - grpc_closure* on_done, grpc_httpcli_context* context, - grpc_polling_entity* pollent, const char* name) + grpc_closure* on_done, grpc_polling_entity* pollent, + const char* name) : request_text_(request_text), resource_quota_(std::move(resource_quota)), host_(host), @@ -64,8 +66,8 @@ class InternalRequest { deadline_(deadline), handshaker_(handshaker), on_done_(on_done), - context_(context), - pollent_(pollent) { + pollent_(pollent), + pollset_set_(grpc_pollset_set_create()) { grpc_http_parser_init(&parser_, GRPC_HTTP_RESPONSE, response); grpc_slice_buffer_init(&incoming_); grpc_slice_buffer_init(&outgoing_); @@ -74,18 +76,15 @@ class InternalRequest { GRPC_CLOSURE_INIT(&on_read_, OnRead, this, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&done_write_, DoneWrite, this, grpc_schedule_on_exec_ctx); GPR_ASSERT(pollent); - grpc_polling_entity_add_to_pollset_set(pollent_, context->pollset_set); - grpc_resolve_address( - host_.c_str(), handshaker_->default_port, context_->pollset_set, - GRPC_CLOSURE_CREATE(OnResolved, this, grpc_schedule_on_exec_ctx), - &addresses_); + grpc_polling_entity_add_to_pollset_set(pollent, pollset_set_); + dns_request_ = GetDNSResolver()->ResolveName( + host_.c_str(), handshaker_->default_port, pollset_set_, + y_absl::bind_front(&InternalRequest::OnResolved, this)); + dns_request_->Start(); } ~InternalRequest() { grpc_http_parser_destroy(&parser_); - if (addresses_ != nullptr) { - grpc_resolved_addresses_destroy(addresses_); - } if (ep_ != nullptr) { grpc_endpoint_destroy(ep_); } @@ -94,11 +93,12 @@ class InternalRequest { grpc_slice_buffer_destroy_internal(&incoming_); grpc_slice_buffer_destroy_internal(&outgoing_); GRPC_ERROR_UNREF(overall_error_); + grpc_pollset_set_destroy(pollset_set_); } private: void Finish(grpc_error_handle error) { - grpc_polling_entity_del_from_pollset_set(pollent_, context_->pollset_set); + grpc_polling_entity_del_from_pollset_set(pollent_, pollset_set_); ExecCtx::Run(DEBUG_LOCATION, on_done_, error); delete this; } @@ -108,7 +108,7 @@ class InternalRequest { overall_error_ = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed HTTP/1 client request"); } - grpc_resolved_address* addr = &addresses_->addrs[next_address_ - 1]; + const grpc_resolved_address* addr = &addresses_[next_address_ - 1]; TString addr_text = grpc_sockaddr_to_uri(addr); overall_error_ = grpc_error_add_child( overall_error_, @@ -193,16 +193,15 @@ class InternalRequest { } void NextAddress(grpc_error_handle error) { - grpc_resolved_address* addr; if (error != GRPC_ERROR_NONE) { AppendError(error); } - if (next_address_ == addresses_->naddrs) { + if (next_address_ == addresses_.size()) { Finish(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Failed HTTP requests to all targets", &overall_error_, 1)); return; } - addr = &addresses_->addrs[next_address_++]; + const grpc_resolved_address* addr = &addresses_[next_address_++]; GRPC_CLOSURE_INIT(&connected_, OnConnected, this, grpc_schedule_on_exec_ctx); grpc_arg rq_arg = grpc_channel_arg_pointer_create( @@ -212,24 +211,26 @@ class InternalRequest { auto* args = CoreConfiguration::Get() .channel_args_preconditioning() .PreconditionChannelArgs(&channel_args); - grpc_tcp_client_connect(&connected_, &ep_, context_->pollset_set, args, - addr, deadline_); + grpc_tcp_client_connect(&connected_, &ep_, pollset_set_, args, addr, + deadline_); grpc_channel_args_destroy(args); } - static void OnResolved(void* arg, grpc_error_handle error) { - InternalRequest* req = static_cast<InternalRequest*>(arg); - if (error != GRPC_ERROR_NONE) { - req->Finish(GRPC_ERROR_REF(error)); + void OnResolved( + y_absl::StatusOr<std::vector<grpc_resolved_address>> addresses_or) { + dns_request_.reset(); + if (!addresses_or.ok()) { + Finish(absl_status_to_grpc_error(addresses_or.status())); return; } - req->next_address_ = 0; - req->NextAddress(GRPC_ERROR_NONE); + addresses_ = std::move(*addresses_or); + next_address_ = 0; + NextAddress(GRPC_ERROR_NONE); } grpc_slice request_text_; grpc_http_parser parser_; - grpc_resolved_addresses* addresses_ = nullptr; + std::vector<grpc_resolved_address> addresses_; size_t next_address_ = 0; grpc_endpoint* ep_ = nullptr; ResourceQuotaRefPtr resource_quota_; @@ -239,8 +240,8 @@ class InternalRequest { int have_read_byte_ = 0; const grpc_httpcli_handshaker* handshaker_; grpc_closure* on_done_; - grpc_httpcli_context* context_; grpc_polling_entity* pollent_; + grpc_pollset_set* pollset_set_; grpc_iomgr_object iomgr_obj_; grpc_slice_buffer incoming_; grpc_slice_buffer outgoing_; @@ -248,6 +249,7 @@ class InternalRequest { grpc_closure done_write_; grpc_closure connected_; grpc_error_handle overall_error_ = GRPC_ERROR_NONE; + OrphanablePtr<DNSResolver::Request> dns_request_; }; } // namespace @@ -266,17 +268,8 @@ static void plaintext_handshake(void* arg, grpc_endpoint* endpoint, const grpc_httpcli_handshaker grpc_httpcli_plaintext = {"http", plaintext_handshake}; -void grpc_httpcli_context_init(grpc_httpcli_context* context) { - context->pollset_set = grpc_pollset_set_create(); -} - -void grpc_httpcli_context_destroy(grpc_httpcli_context* context) { - grpc_pollset_set_destroy(context->pollset_set); -} - static void internal_request_begin( - grpc_httpcli_context* context, grpc_polling_entity* pollent, - grpc_core::ResourceQuotaRefPtr resource_quota, + grpc_polling_entity* pollent, grpc_core::ResourceQuotaRefPtr resource_quota, const grpc_httpcli_request* request, grpc_millis deadline, grpc_closure* on_done, grpc_httpcli_response* response, const char* name, const grpc_slice& request_text) { @@ -284,11 +277,10 @@ static void internal_request_begin( request_text, response, std::move(resource_quota), request->host, request->ssl_host_override, deadline, request->handshaker ? request->handshaker : &grpc_httpcli_plaintext, - on_done, context, pollent, name); + on_done, pollent, name); } -void grpc_httpcli_get(grpc_httpcli_context* context, - grpc_polling_entity* pollent, +void grpc_httpcli_get(grpc_polling_entity* pollent, grpc_core::ResourceQuotaRefPtr resource_quota, const grpc_httpcli_request* request, grpc_millis deadline, grpc_closure* on_done, grpc_httpcli_response* response) { @@ -297,13 +289,12 @@ void grpc_httpcli_get(grpc_httpcli_context* context, } TString name = y_absl::StrFormat("HTTP:GET:%s:%s", request->host, request->http.path); - internal_request_begin(context, pollent, std::move(resource_quota), request, - deadline, on_done, response, name.c_str(), + internal_request_begin(pollent, std::move(resource_quota), request, deadline, + on_done, response, name.c_str(), grpc_httpcli_format_get_request(request)); } -void grpc_httpcli_post(grpc_httpcli_context* context, - grpc_polling_entity* pollent, +void grpc_httpcli_post(grpc_polling_entity* pollent, grpc_core::ResourceQuotaRefPtr resource_quota, const grpc_httpcli_request* request, const char* body_bytes, size_t body_size, @@ -316,8 +307,8 @@ void grpc_httpcli_post(grpc_httpcli_context* context, TString name = y_absl::StrFormat("HTTP:POST:%s:%s", request->host, request->http.path); internal_request_begin( - context, pollent, std::move(resource_quota), request, deadline, on_done, - response, name.c_str(), + pollent, std::move(resource_quota), request, deadline, on_done, response, + name.c_str(), grpc_httpcli_format_post_request(request, body_bytes, body_size)); } diff --git a/contrib/libs/grpc/src/core/lib/http/httpcli.h b/contrib/libs/grpc/src/core/lib/http/httpcli.h index 6c257900f1..8cd23d6a67 100644 --- a/contrib/libs/grpc/src/core/lib/http/httpcli.h +++ b/contrib/libs/grpc/src/core/lib/http/httpcli.h @@ -35,13 +35,8 @@ /* User agent this library reports */ #define GRPC_HTTPCLI_USER_AGENT "grpc-httpcli/0.0" -/* Tracks in-progress http requests - TODO(ctiller): allow caching and capturing multiple requests for the +/* TODO(ctiller): allow caching and capturing multiple requests for the same content and combining them */ -typedef struct grpc_httpcli_context { - grpc_pollset_set* pollset_set; -} grpc_httpcli_context; - struct grpc_httpcli_handshaker { const char* default_port; void (*handshake)(void* arg, grpc_endpoint* endpoint, const char* host, @@ -68,11 +63,7 @@ typedef struct grpc_httpcli_request { /* Expose the parser response type as a httpcli response too */ typedef struct grpc_http_response grpc_httpcli_response; -void grpc_httpcli_context_init(grpc_httpcli_context* context); -void grpc_httpcli_context_destroy(grpc_httpcli_context* context); - /* Asynchronously perform a HTTP GET. - 'context' specifies the http context under which to do the get 'pollent' indicates a grpc_polling_entity that is interested in the result of the get - work on this entity may be used to progress the get operation @@ -82,14 +73,12 @@ void grpc_httpcli_context_destroy(grpc_httpcli_context* context); can be destroyed once the call returns 'deadline' contains a deadline for the request (or gpr_inf_future) 'on_response' is a callback to report results to */ -void grpc_httpcli_get(grpc_httpcli_context* context, - grpc_polling_entity* pollent, +void grpc_httpcli_get(grpc_polling_entity* pollent, grpc_core::ResourceQuotaRefPtr resource_quota, const grpc_httpcli_request* request, grpc_millis deadline, grpc_closure* on_done, grpc_httpcli_response* response); /* Asynchronously perform a HTTP POST. - 'context' specifies the http context under which to do the post 'pollent' indicates a grpc_polling_entity that is interested in the result of the post - work on this entity may be used to progress the post operation @@ -104,8 +93,7 @@ void grpc_httpcli_get(grpc_httpcli_context* context, lifetime of the request 'on_response' is a callback to report results to Does not support ?var1=val1&var2=val2 in the path. */ -void grpc_httpcli_post(grpc_httpcli_context* context, - grpc_polling_entity* pollent, +void grpc_httpcli_post(grpc_polling_entity* pollent, grpc_core::ResourceQuotaRefPtr resource_quota, const grpc_httpcli_request* request, const char* body_bytes, size_t body_size, diff --git a/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.cc b/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.cc index d2c40d38e4..720fd47a27 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/call_combiner.cc @@ -150,7 +150,11 @@ void CallCombiner::Start(grpc_closure* closure, grpc_error_handle error, gpr_log(GPR_INFO, " QUEUING"); } // Queue was not empty, so add closure to queue. - closure->error_data.error = error; +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + closure->error_data.error = internal::StatusAllocHeapPtr(error); +#else + closure->error_data.error = reinterpret_cast<intptr_t>(error); +#endif queue_.Push( reinterpret_cast<MultiProducerSingleConsumerQueue::Node*>(closure)); } @@ -185,12 +189,19 @@ void CallCombiner::Stop(DEBUG_ARGS const char* reason) { } continue; } +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + grpc_error_handle error = + internal::StatusMoveFromHeapPtr(closure->error_data.error); +#else + grpc_error_handle error = + reinterpret_cast<grpc_error_handle>(closure->error_data.error); +#endif + closure->error_data.error = 0; if (GRPC_TRACE_FLAG_ENABLED(grpc_call_combiner_trace)) { gpr_log(GPR_INFO, " EXECUTING FROM QUEUE: closure=%p error=%s", - closure, - grpc_error_std_string(closure->error_data.error).c_str()); + closure, grpc_error_std_string(error).c_str()); } - ScheduleClosure(closure, closure->error_data.error); + ScheduleClosure(closure, error); break; } } else if (GRPC_TRACE_FLAG_ENABLED(grpc_call_combiner_trace)) { diff --git a/contrib/libs/grpc/src/core/lib/iomgr/closure.h b/contrib/libs/grpc/src/core/lib/iomgr/closure.h index b429c9e3eb..0b79368a9f 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/closure.h +++ b/contrib/libs/grpc/src/core/lib/iomgr/closure.h @@ -72,7 +72,7 @@ struct grpc_closure { /** Once queued, the result of the closure. Before then: scratch space */ union { - grpc_error_handle error; + uintptr_t error; uintptr_t scratch; } error_data; @@ -98,7 +98,7 @@ inline grpc_closure* grpc_closure_init(grpc_closure* closure, #endif closure->cb = cb; closure->cb_arg = cb_arg; - closure->error_data.error = GRPC_ERROR_NONE; + closure->error_data.error = 0; #ifndef NDEBUG closure->scheduled = false; closure->file_initiated = nullptr; @@ -172,16 +172,12 @@ inline void grpc_closure_list_init(grpc_closure_list* closure_list) { } /** add \a closure to the end of \a 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_handle error) { + grpc_closure* closure) { if (closure == nullptr) { - GRPC_ERROR_UNREF(error); return false; } - closure->error_data.error = error; closure->next_data.next = nullptr; bool was_empty = (closure_list->head == nullptr); if (was_empty) { @@ -193,12 +189,36 @@ inline bool grpc_closure_list_append(grpc_closure_list* closure_list, return was_empty; } +/** add \a closure to the end of \a 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_handle error) { + if (closure == nullptr) { + GRPC_ERROR_UNREF(error); + return false; + } +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + closure->error_data.error = grpc_core::internal::StatusAllocHeapPtr(error); +#else + closure->error_data.error = reinterpret_cast<intptr_t>(error); +#endif + return grpc_closure_list_append(closure_list, closure); +} + /** force all success bits in \a list to false */ inline void grpc_closure_list_fail_all(grpc_closure_list* list, 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); + if (c->error_data.error == 0) { +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + c->error_data.error = + grpc_core::internal::StatusAllocHeapPtr(forced_failure); +#else + c->error_data.error = + reinterpret_cast<intptr_t>(GRPC_ERROR_REF(forced_failure)); +#endif } } GRPC_ERROR_UNREF(forced_failure); diff --git a/contrib/libs/grpc/src/core/lib/iomgr/combiner.cc b/contrib/libs/grpc/src/core/lib/iomgr/combiner.cc index 1b5add88cd..a51364ca4b 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/combiner.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/combiner.cc @@ -149,7 +149,11 @@ static void combiner_exec(grpc_core::Combiner* lock, grpc_closure* cl, } GPR_ASSERT(last & STATE_UNORPHANED); // ensure lock has not been destroyed assert(cl->cb); - cl->error_data.error = error; +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + cl->error_data.error = grpc_core::internal::StatusAllocHeapPtr(error); +#else + cl->error_data.error = reinterpret_cast<intptr_t>(error); +#endif lock->queue.Push(cl->next_data.mpscq_node.get()); } @@ -221,12 +225,21 @@ bool grpc_combiner_continue_exec_ctx() { return true; } grpc_closure* cl = reinterpret_cast<grpc_closure*>(n); - grpc_error_handle cl_err = cl->error_data.error; #ifndef NDEBUG cl->scheduled = false; #endif +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + grpc_error_handle cl_err = + grpc_core::internal::StatusMoveFromHeapPtr(cl->error_data.error); + cl->error_data.error = 0; + cl->cb(cl->cb_arg, std::move(cl_err)); +#else + grpc_error_handle cl_err = + reinterpret_cast<grpc_error_handle>(cl->error_data.error); + cl->error_data.error = 0; cl->cb(cl->cb_arg, cl_err); GRPC_ERROR_UNREF(cl_err); +#endif } else { grpc_closure* c = lock->final_list.head; GPR_ASSERT(c != nullptr); @@ -236,12 +249,21 @@ 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_handle error = c->error_data.error; #ifndef NDEBUG c->scheduled = false; #endif +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + grpc_error_handle error = + grpc_core::internal::StatusMoveFromHeapPtr(c->error_data.error); + c->error_data.error = 0; + c->cb(c->cb_arg, std::move(error)); +#else + grpc_error_handle error = + reinterpret_cast<grpc_error_handle>(c->error_data.error); + c->error_data.error = 0; c->cb(c->cb_arg, error); GRPC_ERROR_UNREF(error); +#endif c = next; } } diff --git a/contrib/libs/grpc/src/core/lib/iomgr/error.cc b/contrib/libs/grpc/src/core/lib/iomgr/error.cc index 4366536f7d..15e9f6b2be 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/error.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/error.cc @@ -252,6 +252,8 @@ static const char* error_int_name(grpc_error_ints key) { return "channel_connectivity_state"; case GRPC_ERROR_INT_LB_POLICY_DROP: return "lb_policy_drop"; + case GRPC_ERROR_INT_STREAM_NETWORK_STATE: + return "stream_network_state"; case GRPC_ERROR_INT_MAX: GPR_UNREACHABLE_CODE(return "unknown"); } diff --git a/contrib/libs/grpc/src/core/lib/iomgr/error.h b/contrib/libs/grpc/src/core/lib/iomgr/error.h index 35244bdcf6..52cf0683b9 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/error.h +++ b/contrib/libs/grpc/src/core/lib/iomgr/error.h @@ -96,6 +96,9 @@ typedef enum { /// LB policy drop GRPC_ERROR_INT_LB_POLICY_DROP = static_cast<int>(grpc_core::StatusIntProperty::kLbPolicyDrop), + /// stream network state + GRPC_ERROR_INT_STREAM_NETWORK_STATE = + static_cast<int>(grpc_core::StatusIntProperty::kStreamNetworkState), /// Must always be last GRPC_ERROR_INT_MAX, diff --git a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/iomgr.cc b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/iomgr.cc index c392100855..5cd502008b 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/iomgr.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/iomgr.cc @@ -18,6 +18,7 @@ #include "src/core/lib/debug/trace.h" #include "src/core/lib/iomgr/closure.h" +#error #include "src/core/lib/iomgr/event_engine/resolver.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_server.h" @@ -29,7 +30,6 @@ extern grpc_tcp_server_vtable grpc_event_engine_tcp_server_vtable; extern grpc_timer_vtable grpc_event_engine_timer_vtable; extern grpc_pollset_vtable grpc_event_engine_pollset_vtable; extern grpc_pollset_set_vtable grpc_event_engine_pollset_set_vtable; -extern grpc_address_resolver_vtable grpc_event_engine_resolver_vtable; // Disabled by default. grpc_polling_trace must be defined in all iomgr // implementations due to its usage in lockfree_event. @@ -75,7 +75,8 @@ void grpc_set_default_iomgr_platform() { grpc_set_timer_impl(&grpc_event_engine_timer_vtable); grpc_set_pollset_vtable(&grpc_event_engine_pollset_vtable); grpc_set_pollset_set_vtable(&grpc_event_engine_pollset_set_vtable); - grpc_set_resolver_impl(&grpc_event_engine_resolver_vtable); + grpc_core::SetDNSResolver( + grpc_core::experimental::EventEngineDNSResolver::GetOrCreate()); grpc_set_iomgr_platform_vtable(&vtable); } diff --git a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.cc b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.cc index 561d91ed01..136df80944 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.cc @@ -37,5 +37,11 @@ grpc_resolved_address CreateGRPCResolvedAddress( return grpc_addr; } +// TODO(ctiller): Move this to somewhere more permanent as we're deleting iomgr. +TString ResolvedAddressToURI(const EventEngine::ResolvedAddress& addr) { + auto gra = CreateGRPCResolvedAddress(addr); + return grpc_sockaddr_to_uri(&gra); +} + } // namespace experimental } // namespace grpc_event_engine diff --git a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.h b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.h index ae79480525..7ed8a10a27 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.h +++ b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.h @@ -29,6 +29,8 @@ EventEngine::ResolvedAddress CreateResolvedAddress( grpc_resolved_address CreateGRPCResolvedAddress( const EventEngine::ResolvedAddress& ra); +TString ResolvedAddressToURI(const EventEngine::ResolvedAddress& addr); + } // namespace experimental } // namespace grpc_event_engine diff --git a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolver.cc b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolver.cc index fd3559eef5..77a3331659 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolver.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolver.cc @@ -24,11 +24,15 @@ #include "src/core/lib/iomgr/error.h" #error #include "src/core/lib/iomgr/event_engine/promise.h" #include "src/core/lib/iomgr/event_engine/resolved_address_internal.h" +#error #include "src/core/lib/iomgr/event_engine/resolver.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolve_address_impl.h" #include "src/core/lib/iomgr/work_serializer.h" #include "src/core/lib/surface/init.h" #include "src/core/lib/transport/error_utils.h" +namespace grpc_core { +namespace experimental { namespace { using ::grpc_event_engine::experimental::CreateGRPCResolvedAddress; using ::grpc_event_engine::experimental::EventEngine; @@ -39,77 +43,91 @@ using ::grpc_event_engine::experimental::Promise; /// /// This provides a place to store the ownership of the DNSResolver object until /// the request is complete. -class DnsRequest { +class EventEngineDNSRequest : DNSRequest { public: - DnsRequest(std::unique_ptr<EventEngine::DNSResolver> dns_resolver, - y_absl::string_view address, y_absl::string_view default_port, - grpc_closure* on_done, grpc_resolved_addresses** addresses) + EventEngineDNSRequest(std::unique_ptr<EventEngine::DNSResolver> dns_resolver, + y_absl::string_view name, y_absl::string_view default_port, + grpc_closure* on_done, + std::vector<grpc_resolved_address>* addresses) : dns_resolver_(std::move(dns_resolver)), - cb_(on_done), - addresses_(addresses) { + name_(TString(name)), + default_port_(TString(default_port)), + on_done_(std::move(on_done)) {} + + void Start() override { + if (dns_resolver_ == nullptr) { + new DNSCallbackExecCtxScheduler( + std::move(on_done_), + y_absl::UnknownError("Failed to get DNS Resolver.")); + return; + } + Ref().release(); // ref held by pending resolution dns_resolver_->LookupHostname( - y_absl::bind_front(&DnsRequest::OnLookupComplete, this), address, - default_port, y_absl::InfiniteFuture()); + y_absl::bind_front(&EventEngineDNSRequest::OnLookupComplete, this), name_, + default_port_, y_absl::InfiniteFuture()); } + // TOOD(hork): implement cancellation; currently it's a no-op + void Orphan() override { Unref(); } + private: void OnLookupComplete( y_absl::StatusOr<std::vector<EventEngine::ResolvedAddress>> addresses) { - grpc_core::ExecCtx exec_ctx; + ExecCtx exec_ctx; // Convert addresses to iomgr form. - *addresses_ = static_cast<grpc_resolved_addresses*>( - gpr_malloc(sizeof(grpc_resolved_addresses))); - (*addresses_)->naddrs = addresses->size(); - (*addresses_)->addrs = static_cast<grpc_resolved_address*>( - gpr_malloc(sizeof(grpc_resolved_address) * addresses->size())); + std::vector<grpc_resolved_address> result; + results.reserve(addresses->size()); for (size_t i = 0; i < addresses->size(); ++i) { - (*addresses_)->addrs[i] = CreateGRPCResolvedAddress((*addresses)[i]); + results.push_back(CreateGRPCResolvedAddress(addresses[i])); + } + if (addresses.ok()) { + on_done_(std::move(result)); + } else { + on_done_(addresses.status()); } - grpc_closure* cb = cb_; - delete this; - grpc_core::Closure::Run(DEBUG_LOCATION, cb, - absl_status_to_grpc_error(addresses.status())); + Unref(); } std::unique_ptr<EventEngine::DNSResolver> dns_resolver_; - grpc_closure* cb_; - grpc_resolved_addresses** addresses_; + const TString name_; + const TString default_port_; + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done_; }; -void resolve_address(const char* addr, const char* default_port, - grpc_pollset_set* /* interested_parties */, - grpc_closure* on_done, - grpc_resolved_addresses** addresses) { - std::unique_ptr<EventEngine::DNSResolver> dns_resolver = - GetDefaultEventEngine()->GetDNSResolver(); - if (dns_resolver == nullptr) { - grpc_core::ExecCtx::Run( - DEBUG_LOCATION, on_done, - GRPC_ERROR_CREATE_FROM_STATIC_STRING("Failed to get DNS Resolver.")); - return; - } - new DnsRequest(std::move(dns_resolver), addr, default_port, on_done, - addresses); +} // namespace + +DNSResolver* EventEngineDNSResolver::GetOrCreate() { + static EventEngineDNSResolver* instance = new EventEngineDNSResolver(); + return instance; } -void blocking_handle_async_resolve_done(void* arg, grpc_error_handle error) { - static_cast<Promise<grpc_error_handle>*>(arg)->Set(std::move(error)); +OrphanablePtr<DNSResolver::Request> EventEngineDNSResolver::ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* /* interested_parties */, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) { + std::unique_ptr<EventEngine::DNSResolver> dns_resolver = + GetDefaultEventEngine()->GetDNSResolver(); + return MakeOrphanable<EventEngineDNSRequest>( + std::move(dns_resolver), name, default_port, std::move(on_done)); } -grpc_error_handle blocking_resolve_address( - const char* name, const char* default_port, - grpc_resolved_addresses** addresses) { +y_absl::StatusOr<std::vector<grpc_resolved_address>> +EventEngineDNSResolver::ResolveNameBlocking(y_absl::string_view name, + y_absl::string_view default_port) { grpc_closure on_done; - Promise<grpc_error_handle> evt; - GRPC_CLOSURE_INIT(&on_done, blocking_handle_async_resolve_done, &evt, - grpc_schedule_on_exec_ctx); - resolve_address(name, default_port, nullptr, &on_done, addresses); + Promise<y_absl::StatusOr<std::vector<grpc_resolved_address>>> evt; + auto r = ResolveName( + name, default_port, + [&evt](void(y_absl::StatusOr<std::vector<grpc_resolved_address>> result) { + evt.Set(std::move(result)); + })); + r->Start(); return evt.Get(); } -} // namespace - -grpc_address_resolver_vtable grpc_event_engine_resolver_vtable{ - resolve_address, blocking_resolve_address}; +} // namespace experimental +} // namespace grpc_core #endif // GRPC_USE_EVENT_ENGINE diff --git a/contrib/libs/grpc/src/core/lib/iomgr/exec_ctx.cc b/contrib/libs/grpc/src/core/lib/iomgr/exec_ctx.cc index ed480d8f74..ef4248112e 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/exec_ctx.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/exec_ctx.cc @@ -27,7 +27,7 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/profiling/timers.h" -static void exec_ctx_run(grpc_closure* closure, grpc_error_handle error) { +static void exec_ctx_run(grpc_closure* closure) { #ifndef NDEBUG closure->scheduled = false; if (grpc_trace_closure.enabled()) { @@ -37,18 +37,27 @@ static void exec_ctx_run(grpc_closure* closure, grpc_error_handle error) { closure->line_initiated); } #endif +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + grpc_error_handle error = + grpc_core::internal::StatusMoveFromHeapPtr(closure->error_data.error); + closure->error_data.error = 0; + closure->cb(closure->cb_arg, std::move(error)); +#else + grpc_error_handle error = + reinterpret_cast<grpc_error_handle>(closure->error_data.error); + closure->error_data.error = 0; closure->cb(closure->cb_arg, error); + GRPC_ERROR_UNREF(error); +#endif #ifndef NDEBUG if (grpc_trace_closure.enabled()) { gpr_log(GPR_DEBUG, "closure %p finished", closure); } #endif - GRPC_ERROR_UNREF(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); +static void exec_ctx_sched(grpc_closure* closure) { + grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(), closure); } static gpr_timespec g_start_time; @@ -151,9 +160,8 @@ bool ExecCtx::Flush() { closure_list_.head = closure_list_.tail = nullptr; while (c != nullptr) { grpc_closure* next = c->next_data.next; - grpc_error_handle error = c->error_data.error; did_something = true; - exec_ctx_run(c, error); + exec_ctx_run(c); c = next; } } else if (!grpc_combiner_continue_exec_ctx()) { @@ -195,7 +203,12 @@ void ExecCtx::Run(const DebugLocation& location, grpc_closure* closure, closure->run = false; GPR_ASSERT(closure->cb != nullptr); #endif - exec_ctx_sched(closure, error); +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + closure->error_data.error = internal::StatusAllocHeapPtr(error); +#else + closure->error_data.error = reinterpret_cast<intptr_t>(error); +#endif + exec_ctx_sched(closure); } void ExecCtx::RunList(const DebugLocation& location, grpc_closure_list* list) { @@ -218,7 +231,7 @@ void ExecCtx::RunList(const DebugLocation& location, grpc_closure_list* list) { c->run = false; GPR_ASSERT(c->cb != nullptr); #endif - exec_ctx_sched(c, c->error_data.error); + exec_ctx_sched(c); c = next; } list->head = list->tail = nullptr; diff --git a/contrib/libs/grpc/src/core/lib/iomgr/executor.cc b/contrib/libs/grpc/src/core/lib/iomgr/executor.cc index 32df221906..eb23aed07f 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/executor.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/executor.cc @@ -125,7 +125,6 @@ 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_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); @@ -133,8 +132,18 @@ size_t Executor::RunClosures(const char* executor_name, #else EXECUTOR_TRACE("(%s) run %p", executor_name, c); #endif +#ifdef GRPC_ERROR_IS_ABSEIL_STATUS + grpc_error_handle error = + internal::StatusMoveFromHeapPtr(c->error_data.error); + c->error_data.error = 0; + c->cb(c->cb_arg, std::move(error)); +#else + grpc_error_handle error = + reinterpret_cast<grpc_error_handle>(c->error_data.error); + c->error_data.error = 0; c->cb(c->cb_arg, error); GRPC_ERROR_UNREF(error); +#endif c = next; n++; ExecCtx::Get()->Flush(); diff --git a/contrib/libs/grpc/src/core/lib/iomgr/fork_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/fork_posix.cc index 82654b5a88..005bbb0f24 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/fork_posix.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/fork_posix.cc @@ -67,12 +67,13 @@ void grpc_prefork() { if (poll_strategy_name == nullptr || (strcmp(poll_strategy_name, "epoll1") != 0 && strcmp(poll_strategy_name, "poll") != 0)) { - gpr_log(GPR_INFO, + gpr_log(GPR_ERROR, "Fork support is only compatible with the epoll1 and poll polling " "strategies"); + return; } if (!grpc_core::Fork::BlockExecCtx()) { - gpr_log(GPR_INFO, + gpr_log(GPR_ERROR, "Other threads are currently calling into gRPC, skipping fork() " "handlers"); return; diff --git a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_custom.cc b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_custom.cc index 70f4e1b7b1..f9acd07526 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_custom.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_custom.cc @@ -68,7 +68,10 @@ void grpc_custom_iomgr_init(grpc_socket_vtable* socket, grpc_custom_timer_init(timer); grpc_custom_pollset_init(poller); grpc_custom_pollset_set_init(); - grpc_custom_resolver_init(resolver); + grpc_core::CustomDNSResolver::Create(resolver); + grpc_core::CustomDNSResolver* custom_dns_resolver = + grpc_core::CustomDNSResolver::Get(); + grpc_core::SetDNSResolver(custom_dns_resolver); grpc_set_iomgr_platform_vtable(&vtable); } diff --git a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix.cc index 2450ef0bee..437d032750 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix.cc @@ -26,6 +26,7 @@ #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolve_address_posix.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/iomgr/tcp_server.h" @@ -36,7 +37,6 @@ extern grpc_tcp_client_vtable grpc_posix_tcp_client_vtable; extern grpc_timer_vtable grpc_generic_timer_vtable; extern grpc_pollset_vtable grpc_posix_pollset_vtable; extern grpc_pollset_set_vtable grpc_posix_pollset_set_vtable; -extern grpc_address_resolver_vtable grpc_posix_resolver_vtable; static void iomgr_platform_init(void) { grpc_wakeup_fd_global_init(); @@ -79,7 +79,7 @@ void grpc_set_default_iomgr_platform() { grpc_set_timer_impl(&grpc_generic_timer_vtable); grpc_set_pollset_vtable(&grpc_posix_pollset_vtable); grpc_set_pollset_set_vtable(&grpc_posix_pollset_set_vtable); - grpc_set_resolver_impl(&grpc_posix_resolver_vtable); + grpc_core::SetDNSResolver(grpc_core::NativeDNSResolver::GetOrCreate()); grpc_set_iomgr_platform_vtable(&vtable); } diff --git a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix_cfstream.cc b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix_cfstream.cc index 27af38e4b0..74cd19cc25 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix_cfstream.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix_cfstream.cc @@ -41,6 +41,7 @@ #include "src/core/lib/iomgr/ev_posix.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolve_address_posix.h" #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_posix.h" #include "src/core/lib/iomgr/tcp_server.h" @@ -55,7 +56,6 @@ extern grpc_tcp_client_vtable grpc_cfstream_client_vtable; extern grpc_timer_vtable grpc_generic_timer_vtable; extern grpc_pollset_vtable grpc_posix_pollset_vtable; extern grpc_pollset_set_vtable grpc_posix_pollset_set_vtable; -extern grpc_address_resolver_vtable grpc_posix_resolver_vtable; static void apple_iomgr_platform_init(void) { grpc_pollset_global_init(); } @@ -178,7 +178,7 @@ void grpc_set_default_iomgr_platform() { grpc_set_iomgr_platform_vtable(&apple_vtable); } grpc_set_timer_impl(&grpc_generic_timer_vtable); - grpc_set_resolver_impl(&grpc_posix_resolver_vtable); + grpc_core::SetDNSResolver(grpc_core::NativeDNSResolver::GetOrCreate()); } bool grpc_iomgr_run_in_background() { diff --git a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc index 93fdaf8587..87509d8a03 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc @@ -28,6 +28,7 @@ #include "src/core/lib/iomgr/iomgr.h" #include "src/core/lib/iomgr/pollset_windows.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolve_address_windows.h" #include "src/core/lib/iomgr/sockaddr_windows.h" #include "src/core/lib/iomgr/socket_windows.h" #include "src/core/lib/iomgr/tcp_client.h" @@ -39,7 +40,6 @@ extern grpc_tcp_client_vtable grpc_windows_tcp_client_vtable; extern grpc_timer_vtable grpc_generic_timer_vtable; extern grpc_pollset_vtable grpc_windows_pollset_vtable; extern grpc_pollset_set_vtable grpc_windows_pollset_set_vtable; -extern grpc_address_resolver_vtable grpc_windows_resolver_vtable; /* Windows' io manager is going to be fully designed using IO completion ports. All of what we're doing here is basically make sure that @@ -96,7 +96,7 @@ void grpc_set_default_iomgr_platform() { grpc_set_timer_impl(&grpc_generic_timer_vtable); grpc_set_pollset_vtable(&grpc_windows_pollset_vtable); grpc_set_pollset_set_vtable(&grpc_windows_pollset_set_vtable); - grpc_set_resolver_impl(&grpc_windows_resolver_vtable); + grpc_core::SetDNSResolver(grpc_core::NativeDNSResolver::GetOrCreate()); grpc_set_iomgr_platform_vtable(&vtable); } diff --git a/contrib/libs/grpc/src/core/lib/iomgr/port.h b/contrib/libs/grpc/src/core/lib/iomgr/port.h index 3e32429d41..9888e8c04b 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/port.h +++ b/contrib/libs/grpc/src/core/lib/iomgr/port.h @@ -73,9 +73,9 @@ #if __GLIBC_PREREQ(2, 10) #define GRPC_LINUX_SOCKETUTILS 1 #endif -#if !(__GLIBC_PREREQ(2, 17)) +#if !(__GLIBC_PREREQ(2, 18)) /* - * TCP_USER_TIMEOUT wasn't imported to glibc until 2.17. Use Linux system + * TCP_USER_TIMEOUT wasn't imported to glibc until 2.18. Use Linux system * header instead. */ #define GRPC_LINUX_TCP_H 1 diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.cc b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.cc index a2e159a670..3dfe1bf548 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.cc @@ -24,32 +24,13 @@ namespace grpc_core { const char* kDefaultSecurePort = "https"; -} // namespace grpc_core - -grpc_address_resolver_vtable* grpc_resolve_address_impl; -void grpc_set_resolver_impl(grpc_address_resolver_vtable* vtable) { - grpc_resolve_address_impl = vtable; +namespace { +DNSResolver* g_dns_resolver; } -void grpc_resolve_address(const char* addr, const char* default_port, - grpc_pollset_set* interested_parties, - grpc_closure* on_done, - grpc_resolved_addresses** addresses) { - grpc_resolve_address_impl->resolve_address( - addr, default_port, interested_parties, on_done, addresses); -} +void SetDNSResolver(DNSResolver* resolver) { g_dns_resolver = resolver; } -void grpc_resolved_addresses_destroy(grpc_resolved_addresses* addresses) { - if (addresses != nullptr) { - gpr_free(addresses->addrs); - } - gpr_free(addresses); -} +DNSResolver* GetDNSResolver() { return g_dns_resolver; } -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); -} +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.h b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.h index b9e25b0f77..6bf5e37876 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.h +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address.h @@ -23,61 +23,64 @@ #include <stddef.h> -#include "src/core/lib/iomgr/port.h" - -#ifdef GRPC_WINSOCK_SOCKET -#include <ws2tcpip.h> -#endif - -#if defined(GRPC_POSIX_SOCKET) || defined(GRPC_CFSTREAM) -#include <sys/socket.h> -#endif +#include "y_absl/status/statusor.h" +#include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/iomgr/port.h" +#include "src/core/lib/iomgr/resolved_address.h" #define GRPC_MAX_SOCKADDR_SIZE 128 -struct grpc_resolved_address { - char addr[GRPC_MAX_SOCKADDR_SIZE]; - socklen_t len; -}; -struct grpc_resolved_addresses { - size_t naddrs; - grpc_resolved_address* addrs; -}; - namespace grpc_core { extern const char* kDefaultSecurePort; constexpr int kDefaultSecurePortInt = 443; -} // namespace grpc_core - -typedef struct grpc_address_resolver_vtable { - void (*resolve_address)(const char* addr, const char* default_port, - grpc_pollset_set* interested_parties, - grpc_closure* on_done, - 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); +// A singleton class used for async and blocking DNS resolution +class DNSResolver { + public: + // Tracks a single asynchronous DNS resolution attempt. The DNS + // resolution should be arranged to be cancelled as soon as possible + // when Orphan is called. + class Request : public InternallyRefCounted<Request> { + public: + // Begins async DNS resolution + virtual void Start() = 0; + }; + + virtual ~DNSResolver() {} + + // Asynchronously resolve name. Use \a default_port if a port isn't designated + // in \a name, otherwise use the port in \a name. On completion, \a on_done is + // invoked with the result. + // + // Note for implementations: calls may acquire locks in \a on_done which + // were previously held while calling Request::Start(). Therefore, + // implementations must not invoke \a on_done inline from the call to + // Request::Start(). The DNSCallbackExecCtxScheduler utility may help address + // this. + virtual OrphanablePtr<Request> ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* interested_parties, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) GRPC_MUST_USE_RESULT = 0; + + // Resolve name in a blocking fashion. Use \a default_port if a port isn't + // designated in \a name, otherwise use the port in \a name. + virtual y_absl::StatusOr<std::vector<grpc_resolved_address>> + ResolveNameBlocking(y_absl::string_view name, + y_absl::string_view default_port) = 0; +}; -/* Asynchronously resolve addr. Use default_port if a port isn't designated - in addr, otherwise use the port in addr. */ -/* TODO(apolcyn): add a timeout here */ -void grpc_resolve_address(const char* addr, const char* default_port, - grpc_pollset_set* interested_parties, - grpc_closure* on_done, - grpc_resolved_addresses** addresses); +// Override the active DNS resolver which should be used for all DNS +// resolution in gRPC. Note this should only be used during library +// initialization or within tests. +void SetDNSResolver(DNSResolver* resolver); -/* Destroy resolved addresses */ -void grpc_resolved_addresses_destroy(grpc_resolved_addresses* addresses); +// Get the singleton DNS resolver instance which should be used for all +// DNS resolution in gRPC. +DNSResolver* GetDNSResolver(); -/* Resolve addr in a blocking fashion. On success, - result must be freed with grpc_resolved_addresses_destroy. */ -grpc_error_handle grpc_blocking_resolve_address( - const char* name, const char* default_port, - grpc_resolved_addresses** addresses); +} // namespace grpc_core #endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_H */ diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.cc b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.cc index 7e356c6b6e..e8376ac66a 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.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 <grpc/support/port_platform.h> @@ -22,6 +20,7 @@ #include <string.h> +#include <cstdio> #include <util/generic/string.h> #include "y_absl/strings/str_format.h" @@ -35,135 +34,158 @@ #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/resolve_address_impl.h" +#include "src/core/lib/transport/error_utils.h" -struct grpc_custom_resolver { - grpc_closure* on_done = nullptr; - grpc_resolved_addresses** addresses = nullptr; - TString host; - TString port; -}; - -static grpc_custom_resolver_vtable* resolve_address_vtable = nullptr; - -static int retry_named_port_failure(grpc_custom_resolver* r, - grpc_resolved_addresses** res) { - // This loop is copied from resolve_address_posix.c - const char* svc[][2] = {{"http", "80"}, {"https", "443"}}; - for (size_t i = 0; i < GPR_ARRAY_SIZE(svc); i++) { - if (r->port == svc[i][0]) { - r->port = svc[i][1]; - if (res) { - 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); - return 0; - } - } else { - resolve_address_vtable->resolve_async(r, r->host.c_str(), - r->port.c_str()); - } - return 1; - } +void grpc_resolved_addresses_destroy(grpc_resolved_addresses* addresses) { + if (addresses != nullptr) { + gpr_free(addresses->addrs); } - return 0; + gpr_free(addresses); } -void grpc_custom_resolve_callback(grpc_custom_resolver* r, +void grpc_custom_resolve_callback(grpc_custom_resolver* resolver, grpc_resolved_addresses* result, grpc_error_handle error) { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); grpc_core::ApplicationCallbackExecCtx callback_exec_ctx; grpc_core::ExecCtx exec_ctx; - if (error == GRPC_ERROR_NONE) { - *r->addresses = result; - } else if (retry_named_port_failure(r, nullptr)) { - return; - } - if (r->on_done) { - grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error); + grpc_core::CustomDNSResolver::Request* request = + grpc_core::CustomDNSResolver::Request::FromC(resolver); + if (error != GRPC_ERROR_NONE) { + request->ResolveCallback(grpc_error_to_absl_status(error)); + } else { + std::vector<grpc_resolved_address> addresses; + for (size_t i = 0; i < result->naddrs; i++) { + addresses.push_back(result->addrs[i]); + } + request->ResolveCallback(std::move(addresses)); + grpc_resolved_addresses_destroy(result); } - delete r; + GRPC_ERROR_UNREF(error); } -static grpc_error_handle try_split_host_port(const char* name, - const char* default_port, - TString* host, - TString* port) { - /* parse name, splitting it into host and port parts */ - grpc_core::SplitHostPort(name, host, port); +namespace grpc_core { + +namespace { + +y_absl::Status TrySplitHostPort(y_absl::string_view name, + y_absl::string_view default_port, TString* host, + TString* port) { + // parse name, splitting it into host and port parts + SplitHostPort(name, host, port); if (host->empty()) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( + return y_absl::UnknownError( y_absl::StrFormat("unparseable host:port: '%s'", name)); } if (port->empty()) { // TODO(murgatroid99): add tests for this case - if (default_port == nullptr) { - return GRPC_ERROR_CREATE_FROM_CPP_STRING( - y_absl::StrFormat("no port in name '%s'", name)); + if (default_port.empty()) { + return y_absl::UnknownError(y_absl::StrFormat("no port in name '%s'", name)); + } + *port = TString(default_port); + } + return y_absl::OkStatus(); +} + +y_absl::StatusOr<TString> NamedPortToNumeric(y_absl::string_view named_port) { + if (named_port == "http") { + return "80"; + } else if (named_port == "https") { + return "443"; + } else { + return y_absl::UnknownError(y_absl::StrCat("unknown named port: ", named_port)); + } +} + +} // namespace + +void CustomDNSResolver::Request::ResolveCallback( + y_absl::StatusOr<std::vector<grpc_resolved_address>> result) { + if (!result.ok()) { + auto numeric_port_or = NamedPortToNumeric(port_); + if (numeric_port_or.ok()) { + port_ = *numeric_port_or; + resolve_address_vtable_->resolve_async(c_ptr(), host_.c_str(), + port_.c_str()); + // keep holding ref for active resolution + return; } - *port = default_port; } - return GRPC_ERROR_NONE; + // since we can't guarantee that we're not being called inline from + // Start(), run the callback on the ExecCtx. + new DNSCallbackExecCtxScheduler(std::move(on_done_), std::move(result)); + Unref(); } -static grpc_error_handle blocking_resolve_address_impl( - const char* name, const char* default_port, - grpc_resolved_addresses** addresses) { +namespace { +CustomDNSResolver* g_custom_dns_resolver; +} // namespace + +// Creates the global custom resolver with the specified vtable. +void CustomDNSResolver::Create(grpc_custom_resolver_vtable* vtable) { + if (g_custom_dns_resolver != nullptr) return; + g_custom_dns_resolver = new CustomDNSResolver(vtable); +} + +// Gets the singleton instance. +CustomDNSResolver* CustomDNSResolver::Get() { return g_custom_dns_resolver; } + +y_absl::StatusOr<std::vector<grpc_resolved_address>> +CustomDNSResolver::ResolveNameBlocking(y_absl::string_view name, + y_absl::string_view default_port) { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); - grpc_custom_resolver resolver; - grpc_error_handle err = - try_split_host_port(name, default_port, &resolver.host, &resolver.port); - if (err != GRPC_ERROR_NONE) { - return err; + TString host; + TString port; + y_absl::Status parse_status = + TrySplitHostPort(name, default_port, &host, &port); + if (!parse_status.ok()) { + return parse_status; } - /* Call getaddrinfo */ + // Call getaddrinfo + ExecCtx* curr = ExecCtx::Get(); + ExecCtx::Set(nullptr); grpc_resolved_addresses* addrs; - grpc_core::ExecCtx* curr = grpc_core::ExecCtx::Get(); - grpc_core::ExecCtx::Set(nullptr); - err = resolve_address_vtable->resolve(resolver.host.c_str(), - resolver.port.c_str(), &addrs); + grpc_error_handle err = + resolve_address_vtable_->resolve(host.c_str(), port.c_str(), &addrs); if (err != GRPC_ERROR_NONE) { - if (retry_named_port_failure(&resolver, &addrs)) { + auto numeric_port_or = NamedPortToNumeric(port); + if (numeric_port_or.ok()) { + port = *numeric_port_or; GRPC_ERROR_UNREF(err); - err = GRPC_ERROR_NONE; + err = + resolve_address_vtable_->resolve(host.c_str(), port.c_str(), &addrs); } } - grpc_core::ExecCtx::Set(curr); + ExecCtx::Set(curr); if (err == GRPC_ERROR_NONE) { - *addresses = addrs; + GPR_ASSERT(addrs != nullptr); + std::vector<grpc_resolved_address> result; + for (size_t i = 0; i < addrs->naddrs; i++) { + result.push_back(addrs->addrs[i]); + } + grpc_resolved_addresses_destroy(addrs); + return result; } - return err; + auto error_result = grpc_error_to_absl_status(err); + GRPC_ERROR_UNREF(err); + return error_result; } -static void resolve_address_impl(const char* name, const char* default_port, - grpc_pollset_set* /*interested_parties*/, - grpc_closure* on_done, - grpc_resolved_addresses** addrs) { +void CustomDNSResolver::Request::Start() { GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD(); - TString host; - TString 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); + y_absl::Status parse_status = + TrySplitHostPort(name_, default_port_, &host_, &port_); + if (!parse_status.ok()) { + new DNSCallbackExecCtxScheduler(std::move(on_done_), + std::move(parse_status)); return; } - grpc_custom_resolver* r = new grpc_custom_resolver(); - r->on_done = on_done; - r->addresses = addrs; - r->host = std::move(host); - r->port = std::move(port); - - /* Call getaddrinfo */ - resolve_address_vtable->resolve_async(r, r->host.c_str(), r->port.c_str()); + // Call getaddrinfo + Ref().release(); // ref held by resolution + resolve_address_vtable_->resolve_async(c_ptr(), host_.c_str(), port_.c_str()); } -static grpc_address_resolver_vtable custom_resolver_vtable = { - resolve_address_impl, blocking_resolve_address_impl}; - -void grpc_custom_resolver_init(grpc_custom_resolver_vtable* impl) { - resolve_address_vtable = impl; - grpc_set_resolver_impl(&custom_resolver_vtable); -} +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.h b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.h index 4063dcf155..fbb2058880 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.h +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.h @@ -1,30 +1,43 @@ -/* - * - * 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_LIB_IOMGR_RESOLVE_ADDRESS_CUSTOM_H #define GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_CUSTOM_H #include <grpc/support/port_platform.h> +#include <grpc/support/sync.h> + +#include "src/core/lib/gprpp/cpp_impl_of.h" #include "src/core/lib/iomgr/port.h" #include "src/core/lib/iomgr/resolve_address.h" #include "src/core/lib/iomgr/sockaddr.h" +// User-configured custom DNS resolution APIs + +// TODO(apolcyn): This type could be deleted as a part of converting +// this grpc_custom_resolver API to C++. +struct grpc_resolved_addresses { + size_t naddrs; + grpc_resolved_address* addrs; +}; + +// Destroy resolved addresses +void grpc_resolved_addresses_destroy(grpc_resolved_addresses* addresses); + typedef struct grpc_custom_resolver grpc_custom_resolver; typedef struct grpc_custom_resolver_vtable { @@ -34,11 +47,80 @@ typedef struct grpc_custom_resolver_vtable { const char* port); } grpc_custom_resolver_vtable; +// TODO(apolcyn): as a part of converting this API to C++, +// callers of \a grpc_custom_resolve_callback could instead just invoke +// CustomDNSResolver::Request::ResolveCallback directly. void grpc_custom_resolve_callback(grpc_custom_resolver* resolver, grpc_resolved_addresses* result, grpc_error_handle error); -/* Internal APIs */ -void grpc_custom_resolver_init(grpc_custom_resolver_vtable* impl); +// Internal APIs + +namespace grpc_core { + +class CustomDNSResolver : public DNSResolver { + public: + class Request : public DNSResolver::Request, + public CppImplOf<Request, grpc_custom_resolver> { + public: + Request( + y_absl::string_view name, y_absl::string_view default_port, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done, + const grpc_custom_resolver_vtable* resolve_address_vtable) + : name_(name), + default_port_(default_port), + on_done_(std::move(on_done)), + resolve_address_vtable_(resolve_address_vtable) {} + + // Starts the resolution + void Start() override; + + // This is a no-op for the native resolver. Note + // that no I/O polling is required for the resolution to finish. + void Orphan() override { Unref(); } + + // Continues async resolution with the results passed first in to + // grpc_custom_resolve_callback. + void ResolveCallback( + y_absl::StatusOr<std::vector<grpc_resolved_address>> result); + + private: + const TString name_; + const TString default_port_; + TString host_; + TString port_; + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done_; + // user-defined DNS methods + const grpc_custom_resolver_vtable* resolve_address_vtable_; + }; + + // Creates the global custom resolver with the specified vtable. + static void Create(grpc_custom_resolver_vtable* vtable); + + // Gets the singleton instance. + static CustomDNSResolver* Get(); + + explicit CustomDNSResolver(const grpc_custom_resolver_vtable* vtable) + : resolve_address_vtable_(vtable) {} + + OrphanablePtr<DNSResolver::Request> ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* /* interested_parties */, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) override { + return MakeOrphanable<Request>(name, default_port, std::move(on_done), + resolve_address_vtable_); + } + + y_absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking( + y_absl::string_view name, y_absl::string_view default_port) override; + + private: + // user-defined DNS methods + const grpc_custom_resolver_vtable* resolve_address_vtable_; +}; +} // namespace grpc_core #endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_CUSTOM_H */ diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_impl.h b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_impl.h new file mode 100644 index 0000000000..123be082a5 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_impl.h @@ -0,0 +1,59 @@ +// +// 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_LIB_IOMGR_RESOLVE_ADDRESS_IMPL_H +#define GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_IMPL_H + +#include <grpc/support/port_platform.h> + +#include <stddef.h> + +#include "src/core/lib/iomgr/port.h" +#include "src/core/lib/iomgr/resolve_address.h" + +namespace grpc_core { + +// A fire and forget class used by DNSResolver::Request implementations to +// schedule DNS resolution callbacks on the ExecCtx, which is frequently +// necessary to avoid lock inversion related problems. +class DNSCallbackExecCtxScheduler { + public: + DNSCallbackExecCtxScheduler( + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done, + y_absl::StatusOr<std::vector<grpc_resolved_address>> param) + : on_done_(std::move(on_done)), param_(std::move(param)) { + GRPC_CLOSURE_INIT(&closure_, RunCallback, this, grpc_schedule_on_exec_ctx); + ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE); + } + + private: + static void RunCallback(void* arg, grpc_error_handle /* error */) { + DNSCallbackExecCtxScheduler* self = + static_cast<DNSCallbackExecCtxScheduler*>(arg); + self->on_done_(std::move(self->param_)); + delete self; + } + + const std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done_; + y_absl::StatusOr<std::vector<grpc_resolved_address>> param_; + grpc_closure closure_; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_IMPL_H */ diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.cc index 9f329666b4..68d3ce3bee 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.cc @@ -37,52 +37,108 @@ #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolve_address_posix.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" +#include "src/core/lib/transport/error_utils.h" + +namespace grpc_core { +namespace { + +class NativeDNSRequest : public DNSResolver::Request { + public: + NativeDNSRequest( + y_absl::string_view name, y_absl::string_view default_port, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) + : name_(name), default_port_(default_port), on_done_(std::move(on_done)) { + GRPC_CLOSURE_INIT(&request_closure_, DoRequestThread, this, nullptr); + } + + // Starts the resolution + void Start() override { + Ref().release(); // ref held by callback + Executor::Run(&request_closure_, GRPC_ERROR_NONE, ExecutorType::RESOLVER); + } + + // This is a no-op for the native resolver. Note + // that no I/O polling is required for the resolution to finish. + void Orphan() override { Unref(); } + + private: + // Callback to be passed to grpc Executor to asynch-ify + // ResolveNameBlocking + static void DoRequestThread(void* rp, grpc_error_handle /*error*/) { + NativeDNSRequest* r = static_cast<NativeDNSRequest*>(rp); + auto result = + GetDNSResolver()->ResolveNameBlocking(r->name_, r->default_port_); + // running inline is safe since we've already been scheduled on the executor + r->on_done_(std::move(result)); + r->Unref(); + } + + const TString name_; + const TString default_port_; + const std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done_; + grpc_closure request_closure_; +}; -static grpc_error_handle posix_blocking_resolve_address( - const char* name, const char* default_port, - grpc_resolved_addresses** addresses) { - grpc_core::ExecCtx exec_ctx; +} // namespace + +NativeDNSResolver* NativeDNSResolver::GetOrCreate() { + static NativeDNSResolver* instance = new NativeDNSResolver(); + return instance; +} + +OrphanablePtr<DNSResolver::Request> NativeDNSResolver::ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* /* interested_parties */, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) { + return MakeOrphanable<NativeDNSRequest>(name, default_port, + std::move(on_done)); +} + +y_absl::StatusOr<std::vector<grpc_resolved_address>> +NativeDNSResolver::ResolveNameBlocking(y_absl::string_view name, + y_absl::string_view default_port) { + ExecCtx exec_ctx; struct addrinfo hints; struct addrinfo *result = nullptr, *resp; int s; size_t i; grpc_error_handle err; - + std::vector<grpc_resolved_address> addresses; TString host; TString port; - /* parse name, splitting it into host and port parts */ - grpc_core::SplitHostPort(name, &host, &port); + // parse name, splitting it into host and port parts + SplitHostPort(name, &host, &port); if (host.empty()) { err = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"), GRPC_ERROR_STR_TARGET_ADDRESS, name); goto done; } - if (port.empty()) { - if (default_port == nullptr) { + if (default_port.empty()) { err = grpc_error_set_str( GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"), GRPC_ERROR_STR_TARGET_ADDRESS, name); goto done; } - port = default_port; + port = TString(default_port); } - - /* Call getaddrinfo */ + // Call getaddrinfo memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ hints.ai_socktype = SOCK_STREAM; /* stream socket */ hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */ - GRPC_SCHEDULING_START_BLOCKING_REGION; s = getaddrinfo(host.c_str(), port.c_str(), &hints, &result); GRPC_SCHEDULING_END_BLOCKING_REGION; - if (s != 0) { - /* Retry if well-known service name is recognized */ + // Retry if well-known service name is recognized const char* svc[][2] = {{"http", "80"}, {"https", "443"}}; for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) { if (port == svc[i][0]) { @@ -93,7 +149,6 @@ static grpc_error_handle posix_blocking_resolve_address( } } } - if (s != 0) { err = grpc_error_set_str( grpc_error_set_str( @@ -106,65 +161,26 @@ static grpc_error_handle posix_blocking_resolve_address( GRPC_ERROR_STR_TARGET_ADDRESS, name); goto done; } - - /* Success path: set addrs non-NULL, fill it in */ - *addresses = static_cast<grpc_resolved_addresses*>( - gpr_malloc(sizeof(grpc_resolved_addresses))); - (*addresses)->naddrs = 0; - for (resp = result; resp != nullptr; resp = resp->ai_next) { - (*addresses)->naddrs++; - } - (*addresses)->addrs = static_cast<grpc_resolved_address*>( - gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs)); - i = 0; + // Success path: fill in addrs for (resp = result; resp != nullptr; resp = resp->ai_next) { - memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); - (*addresses)->addrs[i].len = resp->ai_addrlen; - i++; + grpc_resolved_address addr; + memcpy(&addr.addr, resp->ai_addr, resp->ai_addrlen); + addr.len = resp->ai_addrlen; + addresses.push_back(addr); } err = GRPC_ERROR_NONE; - done: if (result) { freeaddrinfo(result); } - return err; -} - -struct request { - char* name; - char* default_port; - grpc_closure* on_done; - grpc_resolved_addresses** addrs_out; - grpc_closure request_closure; - void* arg; -}; -/* Callback to be passed to grpc Executor to asynch-ify - * grpc_blocking_resolve_address */ -static void do_request_thread(void* rp, grpc_error_handle /*error*/) { - request* r = static_cast<request*>(rp); - grpc_core::ExecCtx::Run( - DEBUG_LOCATION, r->on_done, - grpc_blocking_resolve_address(r->name, r->default_port, r->addrs_out)); - gpr_free(r->name); - gpr_free(r->default_port); - gpr_free(r); + if (err == GRPC_ERROR_NONE) { + return addresses; + } + auto error_result = grpc_error_to_absl_status(err); + GRPC_ERROR_UNREF(err); + return error_result; } -static void posix_resolve_address(const char* name, const char* default_port, - grpc_pollset_set* /*interested_parties*/, - grpc_closure* on_done, - grpc_resolved_addresses** addrs) { - request* r = static_cast<request*>(gpr_malloc(sizeof(request))); - GRPC_CLOSURE_INIT(&r->request_closure, do_request_thread, r, nullptr); - r->name = gpr_strdup(name); - r->default_port = gpr_strdup(default_port); - r->on_done = on_done; - r->addrs_out = addrs; - grpc_core::Executor::Run(&r->request_closure, GRPC_ERROR_NONE, - grpc_core::ExecutorType::RESOLVER); -} +} // namespace grpc_core -grpc_address_resolver_vtable grpc_posix_resolver_vtable = { - posix_resolve_address, posix_blocking_resolve_address}; #endif diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.h b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.h new file mode 100644 index 0000000000..feb7bc92b0 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.h @@ -0,0 +1,47 @@ +// +// 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_LIB_IOMGR_RESOLVE_ADDRESS_POSIX_H +#define GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_POSIX_H + +#include <grpc/support/port_platform.h> + +#include <functional> + +#include "src/core/lib/iomgr/port.h" +#include "src/core/lib/iomgr/resolve_address.h" + +namespace grpc_core { + +// A DNS resolver which uses the native platform's getaddrinfo API. +class NativeDNSResolver : public DNSResolver { + public: + // Gets the singleton instance, creating it first if it doesn't exist + static NativeDNSResolver* GetOrCreate(); + + OrphanablePtr<DNSResolver::Request> ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* interested_parties, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) override; + + y_absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking( + y_absl::string_view name, y_absl::string_view default_port) override; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_POSIX_H diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.cc b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.cc index 733de96a70..5ac80bcbb5 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.cc @@ -1,20 +1,18 @@ -/* - * - * 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 <grpc/support/port_platform.h> @@ -43,44 +41,98 @@ #include "src/core/lib/iomgr/executor.h" #include "src/core/lib/iomgr/iomgr_internal.h" #include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolve_address_windows.h" #include "src/core/lib/iomgr/sockaddr.h" +#include "src/core/lib/transport/error_utils.h" + +namespace grpc_core { +namespace { + +class NativeDNSRequest : public DNSResolver::Request { + public: + NativeDNSRequest( + y_absl::string_view name, y_absl::string_view default_port, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) + : name_(name), default_port_(default_port), on_done_(std::move(on_done)) { + GRPC_CLOSURE_INIT(&request_closure_, DoRequestThread, this, nullptr); + } + + // Starts the resolution + void Start() override { + Ref().release(); // ref held by callback + Executor::Run(&request_closure_, GRPC_ERROR_NONE, ExecutorType::RESOLVER); + } + + // This is a no-op for the native resolver. Note + // that no I/O polling is required for the resolution to finish. + void Orphan() override { Unref(); } + + private: + // Callback to be passed to grpc Executor to asynch-ify + // ResolveNameBlocking + static void DoRequestThread(void* rp, grpc_error_handle /*error*/) { + NativeDNSRequest* r = static_cast<NativeDNSRequest*>(rp); + auto result = + GetDNSResolver()->ResolveNameBlocking(r->name_, r->default_port_); + // running inline is safe since we've already been scheduled on the executor + r->on_done_(std::move(result)); + r->Unref(); + } -struct request { - char* name; - char* default_port; - grpc_closure request_closure; - grpc_closure* on_done; - grpc_resolved_addresses** addresses; + const TString name_; + const TString default_port_; + const std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done_; + grpc_closure request_closure_; }; -static grpc_error_handle windows_blocking_resolve_address( - const char* name, const char* default_port, - grpc_resolved_addresses** addresses) { - grpc_core::ExecCtx exec_ctx; + +} // namespace + +NativeDNSResolver* NativeDNSResolver::GetOrCreate() { + static NativeDNSResolver* instance = new NativeDNSResolver(); + return instance; +} + +OrphanablePtr<DNSResolver::Request> NativeDNSResolver::ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* /* interested_parties */, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) { + return MakeOrphanable<NativeDNSRequest>(name, default_port, + std::move(on_done)); +} + +y_absl::StatusOr<std::vector<grpc_resolved_address>> +NativeDNSResolver::ResolveNameBlocking(y_absl::string_view name, + y_absl::string_view default_port) { + ExecCtx exec_ctx; struct addrinfo hints; struct addrinfo *result = NULL, *resp; int s; size_t i; grpc_error_handle error = GRPC_ERROR_NONE; + std::vector<grpc_resolved_address> addresses; - /* parse name, splitting it into host and port parts */ + // parse name, splitting it into host and port parts TString host; TString port; - grpc_core::SplitHostPort(name, &host, &port); + SplitHostPort(name, &host, &port); if (host.empty()) { error = GRPC_ERROR_CREATE_FROM_CPP_STRING( y_absl::StrFormat("unparseable host:port: '%s'", name)); goto done; } if (port.empty()) { - if (default_port == NULL) { + if (default_port.empty()) { error = GRPC_ERROR_CREATE_FROM_CPP_STRING( y_absl::StrFormat("no port in name '%s'", name)); goto done; } - port = default_port; + port = TString(default_port); } - /* Call getaddrinfo */ + // Call getaddrinfo memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */ hints.ai_socktype = SOCK_STREAM; /* stream socket */ @@ -94,59 +146,26 @@ static grpc_error_handle windows_blocking_resolve_address( goto done; } - /* Success path: set addrs non-NULL, fill it in */ - (*addresses) = - (grpc_resolved_addresses*)gpr_malloc(sizeof(grpc_resolved_addresses)); - (*addresses)->naddrs = 0; - for (resp = result; resp != NULL; resp = resp->ai_next) { - (*addresses)->naddrs++; - } - (*addresses)->addrs = (grpc_resolved_address*)gpr_malloc( - sizeof(grpc_resolved_address) * (*addresses)->naddrs); - i = 0; + // Success path: set addrs non-NULL, fill it in for (resp = result; resp != NULL; resp = resp->ai_next) { - memcpy(&(*addresses)->addrs[i].addr, resp->ai_addr, resp->ai_addrlen); - (*addresses)->addrs[i].len = resp->ai_addrlen; - i++; + grpc_resolved_address addr; + memcpy(&addr.addr, resp->ai_addr, resp->ai_addrlen); + addr.len = resp->ai_addrlen; + addresses.push_back(addr); } done: if (result) { freeaddrinfo(result); } - return error; -} - -/* Callback to be passed to grpc_executor to asynch-ify - * grpc_blocking_resolve_address */ -static void do_request_thread(void* rp, grpc_error_handle error) { - request* r = (request*)rp; if (error == GRPC_ERROR_NONE) { - error = - grpc_blocking_resolve_address(r->name, r->default_port, r->addresses); - } else { - GRPC_ERROR_REF(error); + return addresses; } - grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error); - gpr_free(r->name); - gpr_free(r->default_port); - gpr_free(r); + auto error_result = grpc_error_to_absl_status(error); + GRPC_ERROR_UNREF(error); + return error_result; } -static void windows_resolve_address(const char* name, const char* default_port, - grpc_pollset_set* interested_parties, - grpc_closure* on_done, - grpc_resolved_addresses** addresses) { - request* r = (request*)gpr_malloc(sizeof(request)); - GRPC_CLOSURE_INIT(&r->request_closure, do_request_thread, r, nullptr); - r->name = gpr_strdup(name); - r->default_port = gpr_strdup(default_port); - r->on_done = on_done; - r->addresses = addresses; - grpc_core::Executor::Run(&r->request_closure, GRPC_ERROR_NONE, - grpc_core::ExecutorType::RESOLVER); -} +} // namespace grpc_core -grpc_address_resolver_vtable grpc_windows_resolver_vtable = { - windows_resolve_address, windows_blocking_resolve_address}; #endif diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.h b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.h new file mode 100644 index 0000000000..2feb974ab9 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.h @@ -0,0 +1,47 @@ +// +// 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_LIB_IOMGR_RESOLVE_ADDRESS_WINDOWS_H +#define GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_WINDOWS_H + +#include <grpc/support/port_platform.h> + +#include <functional> + +#include "src/core/lib/iomgr/port.h" +#include "src/core/lib/iomgr/resolve_address.h" + +namespace grpc_core { + +// A DNS resolver which uses the native platform's getaddrinfo API. +class NativeDNSResolver : public DNSResolver { + public: + // Gets the singleton instance, creating it first if it doesn't exist + static NativeDNSResolver* GetOrCreate(); + + OrphanablePtr<DNSResolver::Request> ResolveName( + y_absl::string_view name, y_absl::string_view default_port, + grpc_pollset_set* interested_parties, + std::function<void(y_absl::StatusOr<std::vector<grpc_resolved_address>>)> + on_done) override; + + y_absl::StatusOr<std::vector<grpc_resolved_address>> ResolveNameBlocking( + y_absl::string_view name, y_absl::string_view default_port) override; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_LIB_IOMGR_RESOLVE_ADDRESS_WINDOWS_H diff --git a/contrib/libs/grpc/src/core/lib/iomgr/resolved_address.h b/contrib/libs/grpc/src/core/lib/iomgr/resolved_address.h new file mode 100644 index 0000000000..9ca8c26299 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/iomgr/resolved_address.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_IOMGR_RESOLVED_ADDRESS_H +#define GRPC_CORE_LIB_IOMGR_RESOLVED_ADDRESS_H + +#include <grpc/support/port_platform.h> + +#include <stddef.h> + +#include "src/core/lib/iomgr/port.h" + +#ifdef GRPC_WINSOCK_SOCKET +#include <ws2tcpip.h> +#endif + +#if defined(GRPC_POSIX_SOCKET) || defined(GRPC_CFSTREAM) +#include <sys/socket.h> +#endif + +#define GRPC_MAX_SOCKADDR_SIZE 128 + +struct grpc_resolved_address { + char addr[GRPC_MAX_SOCKADDR_SIZE]; + socklen_t len; +}; + +#endif /* GRPC_CORE_LIB_IOMGR_RESOLVED_ADDRESS_H */ diff --git a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc index a85f4ce39d..ae7d1f76ca 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc @@ -26,6 +26,7 @@ #include <limits.h> #include <stdio.h> #include <string.h> +#include <sys/socket.h> #include <util/generic/string.h> diff --git a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc index 57f2c57c06..274f84b310 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc @@ -26,6 +26,7 @@ #include <ifaddrs.h> #include <stddef.h> #include <string.h> +#include <sys/socket.h> #include <util/generic/string.h> diff --git a/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.cc b/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.cc index 8a20a8d687..6d899557b5 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.cc @@ -35,29 +35,35 @@ #include "src/core/lib/gpr/useful.h" #include "src/core/lib/iomgr/sockaddr.h" #include "src/core/lib/iomgr/unix_sockets_posix.h" +#include "src/core/lib/transport/error_utils.h" void grpc_create_socketpair_if_unix(int sv[2]) { GPR_ASSERT(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == 0); } -grpc_error_handle grpc_resolve_unix_domain_address( - y_absl::string_view name, grpc_resolved_addresses** addresses) { - *addresses = static_cast<grpc_resolved_addresses*>( - gpr_malloc(sizeof(grpc_resolved_addresses))); - (*addresses)->naddrs = 1; - (*addresses)->addrs = static_cast<grpc_resolved_address*>( - gpr_malloc(sizeof(grpc_resolved_address))); - return grpc_core::UnixSockaddrPopulate(name, (*addresses)->addrs); +y_absl::StatusOr<std::vector<grpc_resolved_address>> +grpc_resolve_unix_domain_address(y_absl::string_view name) { + grpc_resolved_address addr; + grpc_error_handle error = grpc_core::UnixSockaddrPopulate(name, &addr); + if (error == GRPC_ERROR_NONE) { + return std::vector<grpc_resolved_address>({addr}); + } + auto result = grpc_error_to_absl_status(error); + GRPC_ERROR_UNREF(error); + return result; } -grpc_error_handle grpc_resolve_unix_abstract_domain_address( - const y_absl::string_view name, grpc_resolved_addresses** addresses) { - *addresses = static_cast<grpc_resolved_addresses*>( - gpr_malloc(sizeof(grpc_resolved_addresses))); - (*addresses)->naddrs = 1; - (*addresses)->addrs = static_cast<grpc_resolved_address*>( - gpr_malloc(sizeof(grpc_resolved_address))); - return grpc_core::UnixAbstractSockaddrPopulate(name, (*addresses)->addrs); +y_absl::StatusOr<std::vector<grpc_resolved_address>> +grpc_resolve_unix_abstract_domain_address(const y_absl::string_view name) { + grpc_resolved_address addr; + grpc_error_handle error = + grpc_core::UnixAbstractSockaddrPopulate(name, &addr); + if (error == GRPC_ERROR_NONE) { + return std::vector<grpc_resolved_address>({addr}); + } + auto result = grpc_error_to_absl_status(error); + GRPC_ERROR_UNREF(error); + return result; } int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr) { @@ -87,22 +93,4 @@ void grpc_unlink_if_unix_domain_socket( } } -TString grpc_sockaddr_to_uri_unix_if_possible( - const grpc_resolved_address* resolved_addr) { - const grpc_sockaddr* addr = - reinterpret_cast<const grpc_sockaddr*>(resolved_addr->addr); - if (addr->sa_family != AF_UNIX) { - return ""; - } - const auto* unix_addr = reinterpret_cast<const struct sockaddr_un*>(addr); - if (unix_addr->sun_path[0] == '\0' && unix_addr->sun_path[1] != '\0') { - return y_absl::StrCat( - "unix-abstract:", - y_absl::string_view( - unix_addr->sun_path + 1, - resolved_addr->len - sizeof(unix_addr->sun_family) - 1)); - } - return y_absl::StrCat("unix:", unix_addr->sun_path); -} - #endif diff --git a/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.h b/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.h index dff9e50afb..ef204938e5 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.h +++ b/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.h @@ -32,18 +32,15 @@ void grpc_create_socketpair_if_unix(int sv[2]); -grpc_error_handle grpc_resolve_unix_domain_address( - y_absl::string_view name, grpc_resolved_addresses** addresses); +y_absl::StatusOr<std::vector<grpc_resolved_address>> +grpc_resolve_unix_domain_address(y_absl::string_view name); -grpc_error_handle grpc_resolve_unix_abstract_domain_address( - y_absl::string_view name, grpc_resolved_addresses** addresses); +y_absl::StatusOr<std::vector<grpc_resolved_address>> +grpc_resolve_unix_abstract_domain_address(y_absl::string_view name); int grpc_is_unix_socket(const grpc_resolved_address* resolved_addr); void grpc_unlink_if_unix_domain_socket( const grpc_resolved_address* resolved_addr); -TString grpc_sockaddr_to_uri_unix_if_possible( - const grpc_resolved_address* resolved_addr); - #endif /* GRPC_CORE_LIB_IOMGR_UNIX_SOCKETS_POSIX_H */ diff --git a/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix_noop.cc b/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix_noop.cc index a388976049..d01eca4b87 100644 --- a/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix_noop.cc +++ b/contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix_noop.cc @@ -33,18 +33,14 @@ void grpc_create_socketpair_if_unix(int /* sv */[2]) { GPR_ASSERT(0); } -grpc_error_handle grpc_resolve_unix_domain_address( - y_absl::string_view /* name */, grpc_resolved_addresses** addresses) { - *addresses = NULL; - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Unix domain sockets are not supported on Windows"); +y_absl::StatusOr<std::vector<grpc_resolved_address>> +grpc_resolve_unix_domain_address(y_absl::string_view /* name */) { + return y_absl::UnknownError("Unix domain sockets are not supported on Windows"); } -grpc_error_handle grpc_resolve_unix_abstract_domain_address( - y_absl::string_view, grpc_resolved_addresses** addresses) { - *addresses = NULL; - return GRPC_ERROR_CREATE_FROM_STATIC_STRING( - "Unix domain sockets are not supported on Windows"); +y_absl::StatusOr<std::vector<grpc_resolved_address>> +grpc_resolve_unix_abstract_domain_address(y_absl::string_view /* name */) { + return y_absl::UnknownError("Unix domain sockets are not supported on Windows"); } int grpc_is_unix_socket(const grpc_resolved_address* /* addr */) { @@ -54,9 +50,4 @@ int grpc_is_unix_socket(const grpc_resolved_address* /* addr */) { void grpc_unlink_if_unix_domain_socket( const grpc_resolved_address* /* addr */) {} -TString grpc_sockaddr_to_uri_unix_if_possible( - const grpc_resolved_address* /* addr */) { - return ""; -} - #endif diff --git a/contrib/libs/grpc/src/core/lib/matchers/matchers.cc b/contrib/libs/grpc/src/core/lib/matchers/matchers.cc index 4fad1a96f7..42dcffb21a 100644 --- a/contrib/libs/grpc/src/core/lib/matchers/matchers.cc +++ b/contrib/libs/grpc/src/core/lib/matchers/matchers.cc @@ -291,7 +291,7 @@ bool HeaderMatcher::Match( match = value.has_value() == present_match_; } else if (!value.has_value()) { // All other types fail to match if field is not present. - match = false; + return false; } else if (type_ == Type::kRange) { int64_t int_value; match = y_absl::SimpleAtoi(value.value(), &int_value) && diff --git a/contrib/libs/grpc/src/core/lib/promise/activity.h b/contrib/libs/grpc/src/core/lib/promise/activity.h index ede38bd7af..3ffc53baae 100644 --- a/contrib/libs/grpc/src/core/lib/promise/activity.h +++ b/contrib/libs/grpc/src/core/lib/promise/activity.h @@ -24,6 +24,7 @@ #include <atomic> #include <functional> #include <memory> +#include <type_traits> #include <utility> #include "y_absl/base/thread_annotations.h" @@ -267,6 +268,8 @@ namespace promise_detail { template <typename Context> class ContextHolder { public: + using ContextType = Context; + explicit ContextHolder(Context value) : value_(std::move(value)) {} Context* GetContext() { return &value_; } @@ -277,6 +280,8 @@ class ContextHolder { template <typename Context> class ContextHolder<Context*> { public: + using ContextType = Context; + explicit ContextHolder(Context* value) : value_(value) {} Context* GetContext() { return value_; } @@ -284,11 +289,35 @@ class ContextHolder<Context*> { Context* value_; }; +template <typename Context, typename Deleter> +class ContextHolder<std::unique_ptr<Context, Deleter>> { + public: + using ContextType = Context; + + explicit ContextHolder(std::unique_ptr<Context, Deleter> value) + : value_(std::move(value)) {} + Context* GetContext() { return value_.get(); } + + private: + std::unique_ptr<Context, Deleter> value_; +}; + +template <typename HeldContext> +using ContextTypeFromHeld = typename ContextHolder<HeldContext>::ContextType; + template <typename... Contexts> -class EnterContexts : public promise_detail::Context<Contexts>... { +class ActivityContexts : public ContextHolder<Contexts>... { public: - explicit EnterContexts(Contexts*... contexts) - : promise_detail::Context<Contexts>(contexts)... {} + explicit ActivityContexts(Contexts&&... contexts) + : ContextHolder<Contexts>(std::forward<Contexts>(contexts))... {} + + class ScopedContext : public Context<ContextTypeFromHeld<Contexts>>... { + public: + explicit ScopedContext(ActivityContexts* contexts) + : Context<ContextTypeFromHeld<Contexts>>( + static_cast<ContextHolder<Contexts>*>(contexts) + ->GetContext())... {} + }; }; // Implementation details for an Activity of an arbitrary type of promise. @@ -303,15 +332,14 @@ class EnterContexts : public promise_detail::Context<Contexts>... { // invoked, and that a given activity will not be concurrently scheduled again // until its RunScheduledWakeup() has been invoked. template <class F, class WakeupScheduler, class OnDone, typename... Contexts> -class PromiseActivity final - : public Activity, - private promise_detail::ContextHolder<Contexts>... { +class PromiseActivity final : public Activity, + private ActivityContexts<Contexts...> { public: using Factory = PromiseFactory<void, F>; PromiseActivity(F promise_factory, WakeupScheduler wakeup_scheduler, - OnDone on_done, Contexts... contexts) + OnDone on_done, Contexts&&... contexts) : Activity(), - ContextHolder<Contexts>(std::move(contexts))..., + ActivityContexts<Contexts...>(std::forward<Contexts>(contexts)...), wakeup_scheduler_(std::move(wakeup_scheduler)), on_done_(std::move(on_done)) { // Lock, construct an initial promise from the factory, and step it. @@ -361,6 +389,8 @@ class PromiseActivity final } private: + using typename ActivityContexts<Contexts...>::ScopedContext; + // Wakeup this activity. Arrange to poll the activity again at a convenient // time: this could be inline if it's deemed safe, or it could be by passing // the activity to an external threadpool to run. If the activity is already @@ -412,28 +442,27 @@ class PromiseActivity final } // The main body of a step: set the current activity, and any contexts, and - // then run the main polling loop. Contained in a function by itself in order - // to keep the scoping rules a little easier in Step(). + // then run the main polling loop. Contained in a function by itself in + // order to keep the scoping rules a little easier in Step(). y_absl::optional<y_absl::Status> RunStep() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { ScopedActivity scoped_activity(this); - EnterContexts<Contexts...> contexts( - static_cast<ContextHolder<Contexts>*>(this)->GetContext()...); + ScopedContext contexts(this); return StepLoop(); } - // Similarly to RunStep, but additionally construct the promise from a promise - // factory before entering the main loop. Called once from the constructor. + // Similarly to RunStep, but additionally construct the promise from a + // promise factory before entering the main loop. Called once from the + // constructor. y_absl::optional<y_absl::Status> Start(Factory promise_factory) Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { ScopedActivity scoped_activity(this); - EnterContexts<Contexts...> contexts( - static_cast<ContextHolder<Contexts>*>(this)->GetContext()...); + ScopedContext contexts(this); Construct(&promise_holder_.promise, promise_factory.Once()); return StepLoop(); } - // Until there are no wakeups from within and the promise is incomplete: poll - // the promise. + // Until there are no wakeups from within and the promise is incomplete: + // poll the promise. y_absl::optional<y_absl::Status> StepLoop() Y_ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) { GPR_ASSERT(is_current()); while (true) { @@ -486,12 +515,12 @@ template <typename Factory, typename WakeupScheduler, typename OnDone, typename... Contexts> ActivityPtr MakeActivity(Factory promise_factory, WakeupScheduler wakeup_scheduler, OnDone on_done, - Contexts... contexts) { + Contexts&&... contexts) { return ActivityPtr( new promise_detail::PromiseActivity<Factory, WakeupScheduler, OnDone, Contexts...>( std::move(promise_factory), std::move(wakeup_scheduler), - std::move(on_done), std::move(contexts)...)); + std::move(on_done), std::forward<Contexts>(contexts)...)); } } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/promise/detail/status.h b/contrib/libs/grpc/src/core/lib/promise/detail/status.h index 4e20ea326a..641bf22eb6 100644 --- a/contrib/libs/grpc/src/core/lib/promise/detail/status.h +++ b/contrib/libs/grpc/src/core/lib/promise/detail/status.h @@ -41,4 +41,9 @@ inline y_absl::Status IntoStatus(y_absl::Status* status) { } // namespace promise_detail } // namespace grpc_core +// Return true if the status represented by the argument is ok, false if not. +// By implementing this function for other, non-y_absl::Status types, those types +// can participate in TrySeq as result types that affect control flow. +inline bool IsStatusOk(const y_absl::Status& status) { return status.ok(); } + #endif // GRPC_CORE_LIB_PROMISE_DETAIL_STATUS_H diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver.cc b/contrib/libs/grpc/src/core/lib/resolver/resolver.cc index a5494b1666..e43e97b4a2 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver.cc +++ b/contrib/libs/grpc/src/core/lib/resolver/resolver.cc @@ -18,7 +18,7 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/filters/client_channel/resolver.h" +#include "src/core/lib/resolver/resolver.h" grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount(false, "resolver_refcount"); @@ -38,35 +38,28 @@ Resolver::Resolver() // Resolver::Result // -Resolver::Result::~Result() { - GRPC_ERROR_UNREF(service_config_error); - grpc_channel_args_destroy(args); -} +Resolver::Result::~Result() { grpc_channel_args_destroy(args); } -Resolver::Result::Result(const Result& other) { - addresses = other.addresses; - service_config = other.service_config; - service_config_error = GRPC_ERROR_REF(other.service_config_error); - args = grpc_channel_args_copy(other.args); -} +Resolver::Result::Result(const Result& other) + : addresses(other.addresses), + service_config(other.service_config), + resolution_note(other.resolution_note), + args(grpc_channel_args_copy(other.args)) {} -Resolver::Result::Result(Result&& other) noexcept { - addresses = std::move(other.addresses); - service_config = std::move(other.service_config); - service_config_error = other.service_config_error; - other.service_config_error = GRPC_ERROR_NONE; - args = other.args; +Resolver::Result::Result(Result&& other) noexcept + : addresses(std::move(other.addresses)), + service_config(std::move(other.service_config)), + resolution_note(std::move(other.resolution_note)), + // TODO(roth): Use std::move() once channel args is converted to C++. + args(other.args) { other.args = nullptr; } Resolver::Result& Resolver::Result::operator=(const Result& other) { - if (&other == this) { - return *this; - } + if (&other == this) return *this; addresses = other.addresses; service_config = other.service_config; - GRPC_ERROR_UNREF(service_config_error); - service_config_error = GRPC_ERROR_REF(other.service_config_error); + resolution_note = other.resolution_note; grpc_channel_args_destroy(args); args = grpc_channel_args_copy(other.args); return *this; @@ -75,9 +68,8 @@ Resolver::Result& Resolver::Result::operator=(const Result& other) { Resolver::Result& Resolver::Result::operator=(Result&& other) noexcept { addresses = std::move(other.addresses); service_config = std::move(other.service_config); - GRPC_ERROR_UNREF(service_config_error); - service_config_error = other.service_config_error; - other.service_config_error = GRPC_ERROR_NONE; + resolution_note = std::move(other.resolution_note); + // TODO(roth): Use std::move() once channel args is converted to C++. grpc_channel_args_destroy(args); args = other.args; other.args = nullptr; diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver.h b/contrib/libs/grpc/src/core/lib/resolver/resolver.h index 028baa9158..278b634f55 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver.h +++ b/contrib/libs/grpc/src/core/lib/resolver/resolver.h @@ -1,34 +1,32 @@ -/* - * - * 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_RESOLVER_H -#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H +// +// 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_LIB_RESOLVER_RESOLVER_H +#define GRPC_CORE_LIB_RESOLVER_RESOLVER_H #include <grpc/support/port_platform.h> +#include "y_absl/status/statusor.h" + #include <grpc/impl/codegen/grpc_types.h> -#include "src/core/ext/filters/client_channel/server_address.h" -#include "src/core/ext/service_config/service_config.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" -#include "src/core/lib/iomgr/iomgr.h" -#include "src/core/lib/iomgr/work_serializer.h" +#include "src/core/lib/resolver/server_address.h" +#include "src/core/lib/service_config/service_config.h" extern grpc_core::DebugOnlyTraceFlag grpc_trace_resolver_refcount; @@ -53,13 +51,23 @@ class Resolver : public InternallyRefCounted<Resolver> { public: /// Results returned by the resolver. struct Result { - ServerAddressList addresses; - RefCountedPtr<ServiceConfig> service_config; - grpc_error_handle service_config_error = GRPC_ERROR_NONE; + /// A list of addresses, or an error. + y_absl::StatusOr<ServerAddressList> addresses; + /// A service config, or an error. + y_absl::StatusOr<RefCountedPtr<ServiceConfig>> service_config = nullptr; + /// An optional human-readable note describing context about the resolution, + /// to be passed along to the LB policy for inclusion in RPC failure status + /// messages in cases where neither \a addresses nor \a service_config + /// has a non-OK status. For example, a resolver that returns an empty + /// address list but a valid service config may set to this to something + /// like "no DNS entries found for <name>". + TString resolution_note; + // TODO(roth): Before making this a public API, figure out a way to + // avoid exposing channel args this way. const grpc_channel_args* args = nullptr; - // TODO(roth): Remove everything below once grpc_error and - // grpc_channel_args are convert to copyable and movable C++ objects. + // TODO(roth): Remove everything below once grpc_channel_args is + // converted to a copyable and movable C++ object. Result() = default; ~Result(); Result(const Result& other); @@ -74,17 +82,11 @@ class Resolver : public InternallyRefCounted<Resolver> { public: virtual ~ResultHandler() {} - /// Returns a result to the channel. - /// Takes ownership of \a result.args. - virtual void ReturnResult(Result result) = 0; // NOLINT - - /// 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_handle error) = 0; - - // TODO(yashkt): As part of the service config error handling - // changes, add a method to parse the service config JSON string. + /// Reports a result to the channel. + // TODO(roth): Add a mechanism for the resolver to get back a signal + // indicating if the result was accepted by the LB policy, so that it + // knows whether to go into backoff to retry to resolution. + virtual void ReportResult(Result result) = 0; // NOLINT }; // Not copyable nor movable. @@ -113,9 +115,6 @@ class Resolver : public InternallyRefCounted<Resolver> { /// Resets the re-resolution backoff, if any. /// This needs to be implemented only by pull-based implementations; /// for push-based implementations, it will be a no-op. - /// TODO(roth): Pull the backoff code out of resolver and into - /// client_channel, so that it can be shared across resolver - /// implementations. At that point, this method can go away. virtual void ResetBackoffLocked() {} // Note: This must be invoked while holding the work_serializer. @@ -133,4 +132,4 @@ class Resolver : public InternallyRefCounted<Resolver> { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_H */ +#endif // GRPC_CORE_LIB_RESOLVER_RESOLVER_H diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_factory.h b/contrib/libs/grpc/src/core/lib/resolver/resolver_factory.h index e06ace31e6..012fa9544b 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_factory.h +++ b/contrib/libs/grpc/src/core/lib/resolver/resolver_factory.h @@ -16,8 +16,8 @@ * */ -#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H -#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H +#ifndef GRPC_CORE_LIB_RESOLVER_RESOLVER_FACTORY_H +#define GRPC_CORE_LIB_RESOLVER_RESOLVER_FACTORY_H #include <grpc/support/port_platform.h> @@ -25,14 +25,19 @@ #include <grpc/support/string_util.h> -#include "src/core/ext/filters/client_channel/resolver.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/orphanable.h" -#include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/resolver/resolver.h" #include "src/core/lib/uri/uri_parser.h" +typedef struct grpc_pollset_set grpc_pollset_set; + namespace grpc_core { +// TODO(yashkt): Move WorkSerializer to its own Bazel target, depend on that +// target from this one, and remove this forward declaration. +class WorkSerializer; + struct ResolverArgs { /// The parsed URI to resolve. URI uri; @@ -72,4 +77,4 @@ class ResolverFactory { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FACTORY_H */ +#endif /* GRPC_CORE_LIB_RESOLVER_RESOLVER_FACTORY_H */ diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_registry.cc b/contrib/libs/grpc/src/core/lib/resolver/resolver_registry.cc index 0d603e5bfb..23f6000d1b 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_registry.cc +++ b/contrib/libs/grpc/src/core/lib/resolver/resolver_registry.cc @@ -18,11 +18,12 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/resolver/resolver_registry.h" #include <string.h> -#include "y_absl/container/inlined_vector.h" +#include <vector> + #include "y_absl/strings/str_cat.h" #include "y_absl/strings/str_format.h" diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_registry.h b/contrib/libs/grpc/src/core/lib/resolver/resolver_registry.h index e46e718122..6ed60a20be 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_registry.h +++ b/contrib/libs/grpc/src/core/lib/resolver/resolver_registry.h @@ -16,15 +16,14 @@ * */ -#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H -#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H +#ifndef GRPC_CORE_LIB_RESOLVER_RESOLVER_REGISTRY_H +#define GRPC_CORE_LIB_RESOLVER_RESOLVER_REGISTRY_H #include <grpc/support/port_platform.h> -#include "src/core/ext/filters/client_channel/resolver_factory.h" #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/orphanable.h" -#include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/resolver/resolver_factory.h" namespace grpc_core { @@ -85,4 +84,4 @@ class ResolverRegistry { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_REGISTRY_H */ +#endif /* GRPC_CORE_LIB_RESOLVER_RESOLVER_REGISTRY_H */ diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/server_address.cc b/contrib/libs/grpc/src/core/lib/resolver/server_address.cc index b672c8aa59..55d6f8893c 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/server_address.cc +++ b/contrib/libs/grpc/src/core/lib/resolver/server_address.cc @@ -18,7 +18,7 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/filters/client_channel/server_address.h" +#include "src/core/lib/resolver/server_address.h" #include <memory> #include <util/generic/string.h> diff --git a/contrib/libs/grpc/src/core/ext/filters/client_channel/server_address.h b/contrib/libs/grpc/src/core/lib/resolver/server_address.h index 8bc4daaecf..ef0154c6e0 100644 --- a/contrib/libs/grpc/src/core/ext/filters/client_channel/server_address.h +++ b/contrib/libs/grpc/src/core/lib/resolver/server_address.h @@ -16,8 +16,8 @@ * */ -#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H -#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H +#ifndef GRPC_CORE_LIB_RESOLVER_SERVER_ADDRESS_H +#define GRPC_CORE_LIB_RESOLVER_SERVER_ADDRESS_H #include <grpc/support/port_platform.h> @@ -29,7 +29,7 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/useful.h" -#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/resolved_address.h" namespace grpc_core { @@ -141,4 +141,4 @@ class ServerAddressWeightAttribute : public ServerAddress::AttributeInterface { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_SERVER_ADDRESS_H */ +#endif /* GRPC_CORE_LIB_RESOLVER_SERVER_ADDRESS_H */ diff --git a/contrib/libs/grpc/src/core/lib/resource_quota/api.h b/contrib/libs/grpc/src/core/lib/resource_quota/api.h index c531813038..40d0a0525f 100644 --- a/contrib/libs/grpc/src/core/lib/resource_quota/api.h +++ b/contrib/libs/grpc/src/core/lib/resource_quota/api.h @@ -27,7 +27,6 @@ namespace grpc_core { // TODO(ctiller): This is a hack. We need to do real accounting instead of // hard coding. -constexpr size_t kResourceQuotaCallSize = 15 * 1024; constexpr size_t kResourceQuotaChannelSize = 50 * 1024; // Retrieve the resource quota from the channel args. diff --git a/contrib/libs/grpc/src/core/lib/gprpp/arena.cc b/contrib/libs/grpc/src/core/lib/resource_quota/arena.cc index 9e979de39a..7d7e1857b5 100644 --- a/contrib/libs/grpc/src/core/lib/gprpp/arena.cc +++ b/contrib/libs/grpc/src/core/lib/resource_quota/arena.cc @@ -18,7 +18,7 @@ #include <grpc/support/port_platform.h> -#include "src/core/lib/gprpp/arena.h" +#include "src/core/lib/resource_quota/arena.h" #include <string.h> @@ -61,22 +61,24 @@ Arena::~Arena() { } } -Arena* Arena::Create(size_t initial_size) { - return new (ArenaStorage(initial_size)) Arena(initial_size); +Arena* Arena::Create(size_t initial_size, MemoryAllocator* memory_allocator) { + return new (ArenaStorage(initial_size)) + Arena(initial_size, 0, memory_allocator); } -std::pair<Arena*, void*> Arena::CreateWithAlloc(size_t initial_size, - size_t alloc_size) { +std::pair<Arena*, void*> Arena::CreateWithAlloc( + size_t initial_size, size_t alloc_size, MemoryAllocator* memory_allocator) { static constexpr size_t base_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Arena)); - auto* new_arena = - new (ArenaStorage(initial_size)) Arena(initial_size, alloc_size); + auto* new_arena = new (ArenaStorage(initial_size)) + Arena(initial_size, alloc_size, memory_allocator); void* first_alloc = reinterpret_cast<char*>(new_arena) + base_size; return std::make_pair(new_arena, first_alloc); } size_t Arena::Destroy() { size_t size = total_used_.load(std::memory_order_relaxed); + memory_allocator_->Release(total_allocated_.load(std::memory_order_relaxed)); this->~Arena(); gpr_free_aligned(this); return size; @@ -91,13 +93,14 @@ void* Arena::AllocZone(size_t size) { static constexpr size_t zone_base_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(Zone)); size_t alloc_size = zone_base_size + size; + memory_allocator_->Reserve(alloc_size); + total_allocated_.fetch_add(alloc_size, std::memory_order_relaxed); Zone* z = new (gpr_malloc_aligned(alloc_size, GPR_MAX_ALIGNMENT)) Zone(); - { - gpr_spinlock_lock(&arena_growth_spinlock_); - z->prev = last_zone_; - last_zone_ = z; - gpr_spinlock_unlock(&arena_growth_spinlock_); - } + auto* prev = last_zone_.load(std::memory_order_relaxed); + do { + z->prev = prev; + } while (!last_zone_.compare_exchange_weak(prev, z, std::memory_order_relaxed, + std::memory_order_relaxed)); return reinterpret_cast<char*>(z) + zone_base_size; } diff --git a/contrib/libs/grpc/src/core/lib/gprpp/arena.h b/contrib/libs/grpc/src/core/lib/resource_quota/arena.h index 3967f2f8e8..542b09a351 100644 --- a/contrib/libs/grpc/src/core/lib/gprpp/arena.h +++ b/contrib/libs/grpc/src/core/lib/resource_quota/arena.h @@ -22,8 +22,8 @@ // Tracks the total memory allocated against it, so that future arenas can // pre-allocate the right amount of memory -#ifndef GRPC_CORE_LIB_GPRPP_ARENA_H -#define GRPC_CORE_LIB_GPRPP_ARENA_H +#ifndef GRPC_CORE_LIB_RESOURCE_QUOTA_ARENA_H +#define GRPC_CORE_LIB_RESOURCE_QUOTA_ARENA_H #include <grpc/support/port_platform.h> @@ -38,20 +38,22 @@ #include <grpc/support/sync.h> #include "src/core/lib/gpr/alloc.h" -#include "src/core/lib/gpr/spinlock.h" +#include "src/core/lib/promise/context.h" +#include "src/core/lib/resource_quota/memory_quota.h" namespace grpc_core { class Arena { public: // Create an arena, with \a initial_size bytes in the first allocated buffer. - static Arena* Create(size_t initial_size); + static Arena* Create(size_t initial_size, MemoryAllocator* memory_allocator); // Create an arena, with \a initial_size bytes in the first allocated buffer, // and return both a void pointer to the returned arena and a void* with the // first allocation. - static std::pair<Arena*, void*> CreateWithAlloc(size_t initial_size, - size_t alloc_size); + static std::pair<Arena*, void*> CreateWithAlloc( + size_t initial_size, size_t alloc_size, + MemoryAllocator* memory_allocator); // Destroy an arena, returning the total number of bytes allocated. size_t Destroy(); @@ -96,9 +98,11 @@ class Arena { // quick optimization (avoiding an atomic fetch-add) for the common case // where we wish to create an arena and then perform an immediate // allocation. - explicit Arena(size_t initial_size, size_t initial_alloc = 0) + explicit Arena(size_t initial_size, size_t initial_alloc, + MemoryAllocator* memory_allocator) : total_used_(GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_alloc)), - initial_zone_size_(initial_size) {} + initial_zone_size_(initial_size), + memory_allocator_(memory_allocator) {} ~Arena(); @@ -107,14 +111,16 @@ class Arena { // Keep track of the total used size. We use this in our call sizing // hysteresis. std::atomic<size_t> total_used_{0}; + std::atomic<size_t> total_allocated_{0}; const size_t initial_zone_size_; - gpr_spinlock arena_growth_spinlock_ = GPR_SPINLOCK_STATIC_INITIALIZER; // If the initial arena allocation wasn't enough, we allocate additional zones // in a reverse linked list. Each additional zone consists of (1) a pointer to // the zone added before this zone (null if this is the first additional zone) // and (2) the allocated memory. The arena itself maintains a pointer to the // last zone; the zone list is reverse-walked during arena destruction only. - Zone* last_zone_ = nullptr; + std::atomic<Zone*> last_zone_{nullptr}; + // The backing memory quota + MemoryAllocator* const memory_allocator_; }; // Smart pointer for arenas when the final size is not required. @@ -122,10 +128,15 @@ struct ScopedArenaDeleter { void operator()(Arena* arena) { arena->Destroy(); } }; using ScopedArenaPtr = std::unique_ptr<Arena, ScopedArenaDeleter>; -inline ScopedArenaPtr MakeScopedArena(size_t initial_size) { - return ScopedArenaPtr(Arena::Create(initial_size)); +inline ScopedArenaPtr MakeScopedArena(size_t initial_size, + MemoryAllocator* memory_allocator) { + return ScopedArenaPtr(Arena::Create(initial_size, memory_allocator)); } +// Arenas form a context for activities +template <> +struct ContextType<Arena> {}; + } // namespace grpc_core -#endif /* GRPC_CORE_LIB_GPRPP_ARENA_H */ +#endif /* GRPC_CORE_LIB_RESOURCE_QUOTA_ARENA_H */ diff --git a/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.cc b/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.cc index 84a6bc2d91..3127736c2f 100644 --- a/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.cc +++ b/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.cc @@ -81,14 +81,13 @@ EvaluateArgs::PerChannelArgs::PerChannelArgs(grpc_auth_context* auth_context, } y_absl::string_view EvaluateArgs::GetPath() const { - y_absl::string_view path; - if (metadata_ != nullptr && - metadata_->legacy_index()->named.path != nullptr) { - grpc_linked_mdelem* elem = metadata_->legacy_index()->named.path; - const grpc_slice& val = GRPC_MDVALUE(elem->md); - path = StringViewFromSlice(val); + if (metadata_ != nullptr) { + const auto* path = metadata_->get_pointer(HttpPathMetadata()); + if (path != nullptr) { + return path->as_string_view(); + } } - return path; + return y_absl::string_view(); } y_absl::string_view EvaluateArgs::GetHost() const { @@ -101,15 +100,24 @@ y_absl::string_view EvaluateArgs::GetHost() const { return host; } +y_absl::string_view EvaluateArgs::GetAuthority() const { + y_absl::string_view authority; + if (metadata_ != nullptr) { + if (auto* authority_md = metadata_->get_pointer(HttpAuthorityMetadata())) { + authority = authority_md->as_string_view(); + } + } + return authority; +} + y_absl::string_view EvaluateArgs::GetMethod() const { - y_absl::string_view method; - if (metadata_ != nullptr && - metadata_->legacy_index()->named.method != nullptr) { - grpc_linked_mdelem* elem = metadata_->legacy_index()->named.method; - const grpc_slice& val = GRPC_MDVALUE(elem->md); - method = StringViewFromSlice(val); + if (metadata_ != nullptr) { + auto method_md = metadata_->get(HttpMethodMetadata()); + if (method_md.has_value()) { + return HttpMethodMetadata::Encode(*method_md).as_string_view(); + } } - return method; + return y_absl::string_view(); } y_absl::optional<y_absl::string_view> EvaluateArgs::GetHeaderValue( @@ -117,7 +125,14 @@ y_absl::optional<y_absl::string_view> EvaluateArgs::GetHeaderValue( if (metadata_ == nullptr) { return y_absl::nullopt; } - return metadata_->GetValue(key, concatenated_value); + if (y_absl::EqualsIgnoreCase(key, "te")) { + return y_absl::nullopt; + } + if (y_absl::EqualsIgnoreCase(key, "host")) { + // Maps legacy host header to :authority. + return GetAuthority(); + } + return metadata_->GetStringValue(key, concatenated_value); } grpc_resolved_address EvaluateArgs::GetLocalAddress() const { diff --git a/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.h b/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.h index c9f588e93f..32cdec46a7 100644 --- a/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.h +++ b/contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.h @@ -58,6 +58,7 @@ class EvaluateArgs { y_absl::string_view GetPath() const; y_absl::string_view GetHost() const; + y_absl::string_view GetAuthority() const; y_absl::string_view GetMethod() const; // Returns metadata value(s) for the specified key. // If the key is not present in the batch, returns y_absl::nullopt. diff --git a/contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.cc b/contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.cc new file mode 100644 index 0000000000..6877845ad1 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.cc @@ -0,0 +1,60 @@ +// 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 <grpc/support/port_platform.h> + +#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 = y_absl::make_unique<PolicyAuthorizationMatcher>( + std::move(sub_policy.second)); + policies_.push_back(std::move(policy)); + } +} + +GrpcAuthorizationEngine::GrpcAuthorizationEngine( + GrpcAuthorizationEngine&& other) noexcept + : action_(other.action_), policies_(std::move(other.policies_)) {} + +GrpcAuthorizationEngine& GrpcAuthorizationEngine::operator=( + GrpcAuthorizationEngine&& other) noexcept { + action_ = other.action_; + policies_ = std::move(other.policies_); + return *this; +} + +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/contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.h b/contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.h new file mode 100644 index 0000000000..cf98b64bbd --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.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_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H +#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H + +#include <grpc/support/port_platform.h> + +#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); + + GrpcAuthorizationEngine(GrpcAuthorizationEngine&& other) noexcept; + GrpcAuthorizationEngine& operator=(GrpcAuthorizationEngine&& other) noexcept; + + Rbac::Action action() const { return action_; } + + // Required only for testing purpose. + size_t num_policies() const { return policies_.size(); } + + // 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 { + TString name; + std::unique_ptr<AuthorizationMatcher> matcher; + }; + Rbac::Action action_; + std::vector<Policy> policies_; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_GRPC_AUTHORIZATION_ENGINE_H diff --git a/contrib/libs/grpc/src/core/lib/security/authorization/matchers.cc b/contrib/libs/grpc/src/core/lib/security/authorization/matchers.cc new file mode 100644 index 0000000000..419e1ff787 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/security/authorization/matchers.cc @@ -0,0 +1,227 @@ +// 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 <grpc/support/port_platform.h> + +#include "src/core/lib/security/authorization/matchers.h" + +#include <grpc/grpc_security_constants.h> + +#include "src/core/lib/address_utils/parse_address.h" +#include "src/core/lib/address_utils/sockaddr_utils.h" + +namespace grpc_core { + +std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create( + Rbac::Permission permission) { + switch (permission.type) { + case Rbac::Permission::RuleType::kAnd: { + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers; + for (const auto& rule : permission.permissions) { + matchers.push_back(AuthorizationMatcher::Create(std::move(*rule))); + } + return y_absl::make_unique<AndAuthorizationMatcher>(std::move(matchers)); + } + case Rbac::Permission::RuleType::kOr: { + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers; + for (const auto& rule : permission.permissions) { + matchers.push_back(AuthorizationMatcher::Create(std::move(*rule))); + } + return y_absl::make_unique<OrAuthorizationMatcher>(std::move(matchers)); + } + case Rbac::Permission::RuleType::kNot: + return y_absl::make_unique<NotAuthorizationMatcher>( + AuthorizationMatcher::Create(std::move(*permission.permissions[0]))); + case Rbac::Permission::RuleType::kAny: + return y_absl::make_unique<AlwaysAuthorizationMatcher>(); + case Rbac::Permission::RuleType::kHeader: + return y_absl::make_unique<HeaderAuthorizationMatcher>( + std::move(permission.header_matcher)); + case Rbac::Permission::RuleType::kPath: + return y_absl::make_unique<PathAuthorizationMatcher>( + std::move(permission.string_matcher)); + case Rbac::Permission::RuleType::kDestIp: + return y_absl::make_unique<IpAuthorizationMatcher>( + IpAuthorizationMatcher::Type::kDestIp, std::move(permission.ip)); + case Rbac::Permission::RuleType::kDestPort: + return y_absl::make_unique<PortAuthorizationMatcher>(permission.port); + case Rbac::Permission::RuleType::kMetadata: + return y_absl::make_unique<MetadataAuthorizationMatcher>(permission.invert); + case Rbac::Permission::RuleType::kReqServerName: + return y_absl::make_unique<ReqServerNameAuthorizationMatcher>( + std::move(permission.string_matcher)); + } + return nullptr; +} + +std::unique_ptr<AuthorizationMatcher> AuthorizationMatcher::Create( + Rbac::Principal principal) { + switch (principal.type) { + case Rbac::Principal::RuleType::kAnd: { + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers; + for (const auto& id : principal.principals) { + matchers.push_back(AuthorizationMatcher::Create(std::move(*id))); + } + return y_absl::make_unique<AndAuthorizationMatcher>(std::move(matchers)); + } + case Rbac::Principal::RuleType::kOr: { + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers; + for (const auto& id : principal.principals) { + matchers.push_back(AuthorizationMatcher::Create(std::move(*id))); + } + return y_absl::make_unique<OrAuthorizationMatcher>(std::move(matchers)); + } + case Rbac::Principal::RuleType::kNot: + return y_absl::make_unique<NotAuthorizationMatcher>( + AuthorizationMatcher::Create(std::move(*principal.principals[0]))); + case Rbac::Principal::RuleType::kAny: + return y_absl::make_unique<AlwaysAuthorizationMatcher>(); + case Rbac::Principal::RuleType::kPrincipalName: + return y_absl::make_unique<AuthenticatedAuthorizationMatcher>( + std::move(principal.string_matcher)); + case Rbac::Principal::RuleType::kSourceIp: + return y_absl::make_unique<IpAuthorizationMatcher>( + IpAuthorizationMatcher::Type::kSourceIp, std::move(principal.ip)); + case Rbac::Principal::RuleType::kDirectRemoteIp: + return y_absl::make_unique<IpAuthorizationMatcher>( + IpAuthorizationMatcher::Type::kDirectRemoteIp, + std::move(principal.ip)); + case Rbac::Principal::RuleType::kRemoteIp: + return y_absl::make_unique<IpAuthorizationMatcher>( + IpAuthorizationMatcher::Type::kRemoteIp, std::move(principal.ip)); + case Rbac::Principal::RuleType::kHeader: + return y_absl::make_unique<HeaderAuthorizationMatcher>( + std::move(principal.header_matcher)); + case Rbac::Principal::RuleType::kPath: + return y_absl::make_unique<PathAuthorizationMatcher>( + std::move(principal.string_matcher)); + case Rbac::Principal::RuleType::kMetadata: + return y_absl::make_unique<MetadataAuthorizationMatcher>(principal.invert); + } + return nullptr; +} + +bool AndAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + for (const auto& matcher : matchers_) { + if (!matcher->Matches(args)) { + return false; + } + } + return true; +} + +bool OrAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + for (const auto& matcher : matchers_) { + if (matcher->Matches(args)) { + return true; + } + } + return false; +} + +bool NotAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + return !matcher_->Matches(args); +} + +bool HeaderAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + TString concatenated_value; + return matcher_.Match( + args.GetHeaderValue(matcher_.name(), &concatenated_value)); +} + +IpAuthorizationMatcher::IpAuthorizationMatcher(Type type, Rbac::CidrRange range) + : type_(type), prefix_len_(range.prefix_len) { + grpc_error_handle error = + grpc_string_to_sockaddr(&subnet_address_, range.address_prefix.c_str(), + /*port does not matter here*/ 0); + if (error == GRPC_ERROR_NONE) { + grpc_sockaddr_mask_bits(&subnet_address_, prefix_len_); + } else { + gpr_log(GPR_DEBUG, "CidrRange address %s is not IPv4/IPv6. Error: %s", + range.address_prefix.c_str(), grpc_error_std_string(error).c_str()); + } + GRPC_ERROR_UNREF(error); +} + +bool IpAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + grpc_resolved_address address; + switch (type_) { + case Type::kDestIp: { + address = args.GetLocalAddress(); + break; + } + case Type::kSourceIp: + case Type::kDirectRemoteIp: + case Type::kRemoteIp: { + address = args.GetPeerAddress(); + break; + } + default: + return false; + } + return grpc_sockaddr_match_subnet(&address, &subnet_address_, prefix_len_); +} + +bool PortAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + return port_ == args.GetLocalPort(); +} + +bool AuthenticatedAuthorizationMatcher::Matches( + const EvaluateArgs& args) const { + if (args.GetTransportSecurityType() != GRPC_SSL_TRANSPORT_SECURITY_TYPE && + args.GetTransportSecurityType() != GRPC_TLS_TRANSPORT_SECURITY_TYPE) { + // Connection is not authenticated. + return false; + } + if (matcher_.string_matcher().empty()) { + // Allows any authenticated user. + return true; + } + std::vector<y_absl::string_view> uri_sans = args.GetUriSans(); + if (!uri_sans.empty()) { + for (const auto& uri : uri_sans) { + if (matcher_.Match(uri)) { + return true; + } + } + } + std::vector<y_absl::string_view> dns_sans = args.GetDnsSans(); + if (!dns_sans.empty()) { + for (const auto& dns : dns_sans) { + if (matcher_.Match(dns)) { + return true; + } + } + } + return matcher_.Match(args.GetSubject()); +} + +bool ReqServerNameAuthorizationMatcher::Matches(const EvaluateArgs&) const { + // Currently we only support matching against an empty string. + return matcher_.Match(""); +} + +bool PathAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + y_absl::string_view path = args.GetPath(); + if (!path.empty()) { + return matcher_.Match(path); + } + return false; +} + +bool PolicyAuthorizationMatcher::Matches(const EvaluateArgs& args) const { + return permissions_->Matches(args) && principals_->Matches(args); +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/security/authorization/matchers.h b/contrib/libs/grpc/src/core/lib/security/authorization/matchers.h new file mode 100644 index 0000000000..6c66a00879 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/security/authorization/matchers.h @@ -0,0 +1,211 @@ +// 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_MATCHERS_H +#define GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H + +#include <grpc/support/port_platform.h> + +#include <memory> + +#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 { + +// Describes the rules for matching permission or principal. +class AuthorizationMatcher { + public: + virtual ~AuthorizationMatcher() = default; + + // Returns whether or not the permission/principal matches the rules of the + // matcher. + virtual bool Matches(const EvaluateArgs& args) const = 0; + + // Creates an instance of a matcher based off the rules defined in Permission + // config. + static std::unique_ptr<AuthorizationMatcher> Create( + Rbac::Permission permission); + + // Creates an instance of a matcher based off the rules defined in Principal + // config. + static std::unique_ptr<AuthorizationMatcher> Create( + Rbac::Principal principal); +}; + +class AlwaysAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit AlwaysAuthorizationMatcher() = default; + + bool Matches(const EvaluateArgs&) const override { return true; } +}; + +class AndAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit AndAuthorizationMatcher( + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers) + : matchers_(std::move(matchers)) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers_; +}; + +class OrAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit OrAuthorizationMatcher( + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers) + : matchers_(std::move(matchers)) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + std::vector<std::unique_ptr<AuthorizationMatcher>> matchers_; +}; + +// Negates matching the provided permission/principal. +class NotAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit NotAuthorizationMatcher( + std::unique_ptr<AuthorizationMatcher> matcher) + : matcher_(std::move(matcher)) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + std::unique_ptr<AuthorizationMatcher> matcher_; +}; + +class MetadataAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit MetadataAuthorizationMatcher(bool invert) : invert_(invert) {} + + // In RBAC, metadata refers to the Envoy metadata which has no relation to + // gRPC metadata. Envoy metadata is a generic state shared between filters, + // which has no gRPC equivalent. RBAC implementations in gRPC will treat Envoy + // metadata as an empty map. Since ValueMatcher can only match if a value is + // present (even NullMatch), the metadata matcher will not match unless invert + // is set to true. + bool Matches(const EvaluateArgs&) const override { return invert_; } + + private: + const bool invert_; +}; + +// Perform a match against HTTP headers. +class HeaderAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit HeaderAuthorizationMatcher(HeaderMatcher matcher) + : matcher_(std::move(matcher)) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const HeaderMatcher matcher_; +}; + +// Perform a match against IP Cidr Range. +class IpAuthorizationMatcher : public AuthorizationMatcher { + public: + enum class Type { + kDestIp, + kSourceIp, + kDirectRemoteIp, + kRemoteIp, + }; + + IpAuthorizationMatcher(Type type, Rbac::CidrRange range); + + bool Matches(const EvaluateArgs& args) const override; + + private: + const Type type_; + // Subnet masked address. + grpc_resolved_address subnet_address_; + const uint32_t prefix_len_; +}; + +// Perform a match against port number of the destination (local) address. +class PortAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit PortAuthorizationMatcher(int port) : port_(port) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const int port_; +}; + +// 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) + : matcher_(std::move(auth)) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const StringMatcher matcher_; +}; + +// 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) + : matcher_(std::move(requested_server_name)) {} + + bool Matches(const EvaluateArgs&) const override; + + private: + const StringMatcher matcher_; +}; + +// Perform a match against the path header of HTTP request. +class PathAuthorizationMatcher : public AuthorizationMatcher { + public: + explicit PathAuthorizationMatcher(StringMatcher path) + : matcher_(std::move(path)) {} + + bool Matches(const EvaluateArgs& args) const override; + + private: + const StringMatcher matcher_; +}; + +// 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: + std::unique_ptr<AuthorizationMatcher> permissions_; + std::unique_ptr<AuthorizationMatcher> principals_; +}; + +} // namespace grpc_core + +#endif // GRPC_CORE_LIB_SECURITY_AUTHORIZATION_MATCHERS_H diff --git a/contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.cc b/contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.cc new file mode 100644 index 0000000000..125272ffc9 --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.cc @@ -0,0 +1,442 @@ +// 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 <grpc/support/port_platform.h> + +#include "src/core/lib/security/authorization/rbac_policy.h" + +#include "y_absl/strings/str_format.h" +#include "y_absl/strings/str_join.h" + +namespace grpc_core { + +// +// Rbac +// + +Rbac::Rbac(Rbac::Action action, std::map<TString, Policy> 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; +} + +TString Rbac::ToString() const { + std::vector<TString> contents; + contents.push_back(y_absl::StrFormat( + "Rbac action=%s{", action == Rbac::Action::kAllow ? "Allow" : "Deny")); + for (const auto& p : policies) { + contents.push_back(y_absl::StrFormat("{\n policy_name=%s\n%s\n}", p.first, + p.second.ToString())); + } + contents.push_back("}"); + return y_absl::StrJoin(contents, "\n"); +} + +// +// CidrRange +// + +Rbac::CidrRange::CidrRange(TString 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; +} + +TString Rbac::CidrRange::ToString() const { + return y_absl::StrFormat("CidrRange{address_prefix=%s,prefix_len=%d}", + address_prefix, prefix_len); +} + +// +// Permission +// + +Rbac::Permission Rbac::Permission::MakeAndPermission( + std::vector<std::unique_ptr<Permission>> permissions) { + Permission permission; + permission.type = Permission::RuleType::kAnd; + permission.permissions = std::move(permissions); + return permission; +} + +Rbac::Permission Rbac::Permission::MakeOrPermission( + std::vector<std::unique_ptr<Permission>> permissions) { + Permission permission; + permission.type = Permission::RuleType::kOr; + permission.permissions = std::move(permissions); + return permission; +} + +Rbac::Permission Rbac::Permission::MakeNotPermission(Permission permission) { + Permission not_permission; + not_permission.type = Permission::RuleType::kNot; + not_permission.permissions.push_back( + y_absl::make_unique<Rbac::Permission>(std::move(permission))); + return not_permission; +} + +Rbac::Permission Rbac::Permission::MakeAnyPermission() { + Permission permission; + permission.type = Permission::RuleType::kAny; + return permission; +} + +Rbac::Permission Rbac::Permission::MakeHeaderPermission( + HeaderMatcher header_matcher) { + Permission permission; + permission.type = Permission::RuleType::kHeader; + permission.header_matcher = std::move(header_matcher); + return permission; +} + +Rbac::Permission Rbac::Permission::MakePathPermission( + StringMatcher string_matcher) { + Permission permission; + permission.type = Permission::RuleType::kPath; + permission.string_matcher = std::move(string_matcher); + return permission; +} + +Rbac::Permission Rbac::Permission::MakeDestIpPermission(CidrRange ip) { + Permission permission; + permission.type = Permission::RuleType::kDestIp; + permission.ip = std::move(ip); + return permission; +} + +Rbac::Permission Rbac::Permission::MakeDestPortPermission(int port) { + Permission permission; + permission.type = Permission::RuleType::kDestPort; + permission.port = port; + return permission; +} + +Rbac::Permission Rbac::Permission::MakeMetadataPermission(bool invert) { + Permission permission; + permission.type = Permission::RuleType::kMetadata; + permission.invert = invert; + return permission; +} + +Rbac::Permission Rbac::Permission::MakeReqServerNamePermission( + StringMatcher string_matcher) { + Permission permission; + permission.type = Permission::RuleType::kReqServerName; + permission.string_matcher = std::move(string_matcher); + return permission; +} + +Rbac::Permission::Permission(Rbac::Permission&& other) noexcept + : type(other.type), invert(other.invert) { + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + case RuleType::kNot: + 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; + invert = other.invert; + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + case RuleType::kNot: + 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; +} + +TString Rbac::Permission::ToString() const { + switch (type) { + case RuleType::kAnd: { + std::vector<TString> contents; + contents.reserve(permissions.size()); + for (const auto& permission : permissions) { + contents.push_back(permission->ToString()); + } + return y_absl::StrFormat("and=[%s]", y_absl::StrJoin(contents, ",")); + } + case RuleType::kOr: { + std::vector<TString> contents; + contents.reserve(permissions.size()); + for (const auto& permission : permissions) { + contents.push_back(permission->ToString()); + } + return y_absl::StrFormat("or=[%s]", y_absl::StrJoin(contents, ",")); + } + case RuleType::kNot: + return y_absl::StrFormat("not %s", permissions[0]->ToString()); + case RuleType::kAny: + return "any"; + case RuleType::kHeader: + return y_absl::StrFormat("header=%s", header_matcher.ToString()); + case RuleType::kPath: + return y_absl::StrFormat("path=%s", string_matcher.ToString()); + case RuleType::kDestIp: + return y_absl::StrFormat("dest_ip=%s", ip.ToString()); + case RuleType::kDestPort: + return y_absl::StrFormat("dest_port=%d", port); + case RuleType::kMetadata: + return y_absl::StrFormat("%smetadata", invert ? "invert " : ""); + case RuleType::kReqServerName: + return y_absl::StrFormat("requested_server_name=%s", + string_matcher.ToString()); + default: + return ""; + } +} + +// +// Principal +// + +Rbac::Principal Rbac::Principal::MakeAndPrincipal( + std::vector<std::unique_ptr<Principal>> principals) { + Principal principal; + principal.type = Principal::RuleType::kAnd; + principal.principals = std::move(principals); + return principal; +} + +Rbac::Principal Rbac::Principal::MakeOrPrincipal( + std::vector<std::unique_ptr<Principal>> principals) { + Principal principal; + principal.type = Principal::RuleType::kOr; + principal.principals = std::move(principals); + return principal; +} + +Rbac::Principal Rbac::Principal::MakeNotPrincipal(Principal principal) { + Principal not_principal; + not_principal.type = Principal::RuleType::kNot; + not_principal.principals.push_back( + y_absl::make_unique<Rbac::Principal>(std::move(principal))); + return not_principal; +} + +Rbac::Principal Rbac::Principal::MakeAnyPrincipal() { + Principal principal; + principal.type = Principal::RuleType::kAny; + return principal; +} + +Rbac::Principal Rbac::Principal::MakeAuthenticatedPrincipal( + StringMatcher string_matcher) { + Principal principal; + principal.type = Principal::RuleType::kPrincipalName; + principal.string_matcher = std::move(string_matcher); + return principal; +} + +Rbac::Principal Rbac::Principal::MakeSourceIpPrincipal(CidrRange ip) { + Principal principal; + principal.type = Principal::RuleType::kSourceIp; + principal.ip = std::move(ip); + return principal; +} + +Rbac::Principal Rbac::Principal::MakeDirectRemoteIpPrincipal(CidrRange ip) { + Principal principal; + principal.type = Principal::RuleType::kDirectRemoteIp; + principal.ip = std::move(ip); + return principal; +} + +Rbac::Principal Rbac::Principal::MakeRemoteIpPrincipal(CidrRange ip) { + Principal principal; + principal.type = Principal::RuleType::kRemoteIp; + principal.ip = std::move(ip); + return principal; +} + +Rbac::Principal Rbac::Principal::MakeHeaderPrincipal( + HeaderMatcher header_matcher) { + Principal principal; + principal.type = Principal::RuleType::kHeader; + principal.header_matcher = std::move(header_matcher); + return principal; +} + +Rbac::Principal Rbac::Principal::MakePathPrincipal( + StringMatcher string_matcher) { + Principal principal; + principal.type = Principal::RuleType::kPath; + principal.string_matcher = std::move(string_matcher); + return principal; +} + +Rbac::Principal Rbac::Principal::MakeMetadataPrincipal(bool invert) { + Principal principal; + principal.type = Principal::RuleType::kMetadata; + principal.invert = invert; + return principal; +} + +Rbac::Principal::Principal(Rbac::Principal&& other) noexcept + : type(other.type), invert(other.invert) { + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + case RuleType::kNot: + 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; + invert = other.invert; + switch (type) { + case RuleType::kAnd: + case RuleType::kOr: + case RuleType::kNot: + 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; +} + +TString Rbac::Principal::ToString() const { + switch (type) { + case RuleType::kAnd: { + std::vector<TString> contents; + contents.reserve(principals.size()); + for (const auto& principal : principals) { + contents.push_back(principal->ToString()); + } + return y_absl::StrFormat("and=[%s]", y_absl::StrJoin(contents, ",")); + } + case RuleType::kOr: { + std::vector<TString> contents; + contents.reserve(principals.size()); + for (const auto& principal : principals) { + contents.push_back(principal->ToString()); + } + return y_absl::StrFormat("or=[%s]", y_absl::StrJoin(contents, ",")); + } + case RuleType::kNot: + return y_absl::StrFormat("not %s", principals[0]->ToString()); + case RuleType::kAny: + return "any"; + case RuleType::kPrincipalName: + return y_absl::StrFormat("principal_name=%s", string_matcher.ToString()); + case RuleType::kSourceIp: + return y_absl::StrFormat("source_ip=%s", ip.ToString()); + case RuleType::kDirectRemoteIp: + return y_absl::StrFormat("direct_remote_ip=%s", ip.ToString()); + case RuleType::kRemoteIp: + return y_absl::StrFormat("remote_ip=%s", ip.ToString()); + case RuleType::kHeader: + return y_absl::StrFormat("header=%s", header_matcher.ToString()); + case RuleType::kPath: + return y_absl::StrFormat("path=%s", string_matcher.ToString()); + case RuleType::kMetadata: + return y_absl::StrFormat("%smetadata", invert ? "invert " : ""); + 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; +} + +TString Rbac::Policy::ToString() const { + return y_absl::StrFormat( + " Policy {\n Permissions{%s}\n Principals{%s}\n }", + permissions.ToString(), principals.ToString()); +} + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.h b/contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.h new file mode 100644 index 0000000000..0bbb29942c --- /dev/null +++ b/contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.h @@ -0,0 +1,170 @@ +// 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 <grpc/support/port_platform.h> + +#include <memory> + +#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(TString address_prefix, uint32_t prefix_len); + + CidrRange(CidrRange&& other) noexcept; + CidrRange& operator=(CidrRange&& other) noexcept; + + TString ToString() const; + + TString address_prefix; + uint32_t prefix_len; + }; + + // TODO(ashithasantosh): Support for destination_port_range. + struct Permission { + enum class RuleType { + kAnd, + kOr, + kNot, + kAny, + kHeader, + kPath, + kDestIp, + kDestPort, + kMetadata, + kReqServerName, + }; + + static Permission MakeAndPermission( + std::vector<std::unique_ptr<Permission>> permissions); + static Permission MakeOrPermission( + std::vector<std::unique_ptr<Permission>> permissions); + static Permission MakeNotPermission(Permission permission); + static Permission MakeAnyPermission(); + static Permission MakeHeaderPermission(HeaderMatcher header_matcher); + static Permission MakePathPermission(StringMatcher string_matcher); + static Permission MakeDestIpPermission(CidrRange ip); + static Permission MakeDestPortPermission(int port); + // All the other fields in MetadataMatcher are ignored except invert. + static Permission MakeMetadataPermission(bool invert); + static Permission MakeReqServerNamePermission(StringMatcher string_matcher); + + Permission() = default; + + Permission(Permission&& other) noexcept; + Permission& operator=(Permission&& other) noexcept; + + TString ToString() const; + + RuleType type = RuleType::kAnd; + HeaderMatcher header_matcher; + StringMatcher string_matcher; + CidrRange ip; + int port; + // For type kAnd/kOr/kNot. For kNot type, the vector will have only one + // element. + std::vector<std::unique_ptr<Permission>> permissions; + // For kMetadata + bool invert = false; + }; + + struct Principal { + enum class RuleType { + kAnd, + kOr, + kNot, + kAny, + kPrincipalName, + kSourceIp, + kDirectRemoteIp, + kRemoteIp, + kHeader, + kPath, + kMetadata, + }; + + static Principal MakeAndPrincipal( + std::vector<std::unique_ptr<Principal>> principals); + static Principal MakeOrPrincipal( + std::vector<std::unique_ptr<Principal>> principals); + static Principal MakeNotPrincipal(Principal principal); + static Principal MakeAnyPrincipal(); + static Principal MakeAuthenticatedPrincipal(StringMatcher string_matcher); + static Principal MakeSourceIpPrincipal(CidrRange ip); + static Principal MakeDirectRemoteIpPrincipal(CidrRange ip); + static Principal MakeRemoteIpPrincipal(CidrRange ip); + static Principal MakeHeaderPrincipal(HeaderMatcher header_matcher); + static Principal MakePathPrincipal(StringMatcher string_matcher); + // All the other fields in MetadataMatcher are ignored except invert. + static Principal MakeMetadataPrincipal(bool invert); + + Principal() = default; + + Principal(Principal&& other) noexcept; + Principal& operator=(Principal&& other) noexcept; + + TString ToString() const; + + RuleType type = RuleType::kAnd; + HeaderMatcher header_matcher; + StringMatcher string_matcher; + CidrRange ip; + // For type kAnd/kOr/kNot. For kNot type, the vector will have only one + // element. + std::vector<std::unique_ptr<Principal>> principals; + // For kMetadata + bool invert = false; + }; + + struct Policy { + Policy() = default; + Policy(Permission permissions, Principal principals); + + Policy(Policy&& other) noexcept; + Policy& operator=(Policy&& other) noexcept; + + TString ToString() const; + + Permission permissions; + Principal principals; + }; + + Rbac() = default; + Rbac(Rbac::Action action, std::map<TString, Policy> policies); + + Rbac(Rbac&& other) noexcept; + Rbac& operator=(Rbac&& other) noexcept; + + TString ToString() const; + + Action action; + std::map<TString, Policy> policies; +}; + +} // namespace grpc_core + +#endif /* GRPC_CORE_LIB_SECURITY_AUTHORIZATION_RBAC_POLICY_H */ diff --git a/contrib/libs/grpc/src/core/lib/security/context/security_context.cc b/contrib/libs/grpc/src/core/lib/security/context/security_context.cc index 257f5c25cb..903bcb0ed8 100644 --- a/contrib/libs/grpc/src/core/lib/security/context/security_context.cc +++ b/contrib/libs/grpc/src/core/lib/security/context/security_context.cc @@ -29,9 +29,9 @@ #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" @@ -235,7 +235,9 @@ void grpc_auth_context::add_property(const char* name, const char* value, grpc_auth_property* prop = &properties_.array[properties_.count++]; prop->name = gpr_strdup(name); prop->value = static_cast<char*>(gpr_malloc(value_length + 1)); - memcpy(prop->value, value, value_length); + if (value != nullptr) { + memcpy(prop->value, value, value_length); + } prop->value[value_length] = '\0'; prop->value_length = value_length; } diff --git a/contrib/libs/grpc/src/core/lib/security/context/security_context.h b/contrib/libs/grpc/src/core/lib/security/context/security_context.h index 6ff4856e6b..2c695931b5 100644 --- a/contrib/libs/grpc/src/core/lib/security/context/security_context.h +++ b/contrib/libs/grpc/src/core/lib/security/context/security_context.h @@ -21,10 +21,10 @@ #include <grpc/support/port_platform.h> -#include "src/core/lib/gprpp/arena.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/pollset.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/security/credentials/credentials.h" extern grpc_core::DebugOnlyTraceFlag grpc_trace_auth_context_refcount; diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.cc index dbdaeb6bdb..4edbf82ef2 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.cc @@ -44,7 +44,7 @@ struct grpc_composite_call_credentials_metadata_context { grpc_composite_call_credentials_metadata_context( grpc_composite_call_credentials* composite_creds, grpc_polling_entity* pollent, grpc_auth_metadata_context auth_md_context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata) : composite_creds(composite_creds), pollent(pollent), @@ -59,7 +59,7 @@ struct grpc_composite_call_credentials_metadata_context { size_t creds_index = 0; grpc_polling_entity* pollent; grpc_auth_metadata_context auth_md_context; - grpc_credentials_mdelem_array* md_array; + grpc_core::CredentialsMetadataArray* md_array; grpc_closure* on_request_metadata; grpc_closure internal_on_request_metadata; }; @@ -91,8 +91,8 @@ static void composite_call_metadata_cb(void* arg, grpc_error_handle 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_handle* error) { + grpc_core::CredentialsMetadataArray* md_array, + grpc_closure* on_request_metadata, grpc_error_handle* error) { grpc_composite_call_credentials_metadata_context* ctx; ctx = new grpc_composite_call_credentials_metadata_context( this, pollent, auth_md_context, md_array, on_request_metadata); @@ -113,7 +113,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_handle error) { + grpc_core::CredentialsMetadataArray* md_array, grpc_error_handle error) { for (size_t i = 0; i < inner_.size(); ++i) { inner_[i]->cancel_get_request_metadata(md_array, GRPC_ERROR_REF(error)); } diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.h index 4c3b840bf7..b5ce865c4f 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.h @@ -81,12 +81,13 @@ class grpc_composite_call_credentials : public grpc_call_credentials { bool get_request_metadata(grpc_polling_entity* pollent, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata, grpc_error_handle* error) override; - void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error_handle error) override; + void cancel_get_request_metadata( + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) override; grpc_security_level min_security_level() const override { return min_security_level_; diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/credentials.h index 6d761703a8..5bf4a02061 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/credentials.h @@ -153,21 +153,11 @@ grpc_channel_credentials* grpc_channel_credentials_from_arg( grpc_channel_credentials* grpc_channel_credentials_find_in_args( const grpc_channel_args* args); -/* --- grpc_credentials_mdelem_array. --- */ +/* --- grpc_core::CredentialsMetadataArray. --- */ -struct grpc_credentials_mdelem_array { - grpc_mdelem* md = nullptr; - size_t size = 0; -}; -/// Takes a new ref to \a md. -void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array* list, - grpc_mdelem md); - -/// Appends all elements from \a src to \a dst, taking a new ref to each one. -void grpc_credentials_mdelem_array_append(grpc_credentials_mdelem_array* dst, - grpc_credentials_mdelem_array* src); - -void grpc_credentials_mdelem_array_destroy(grpc_credentials_mdelem_array* list); +namespace grpc_core { +using CredentialsMetadataArray = std::vector<std::pair<Slice, Slice>>; +} /* --- grpc_call_credentials. --- */ @@ -188,17 +178,17 @@ struct grpc_call_credentials // be set to indicate the result. Otherwise, \a on_request_metadata will // be invoked asynchronously when complete. \a md_array will be populated // with the resulting metadata once complete. - virtual bool get_request_metadata(grpc_polling_entity* pollent, - grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, - grpc_closure* on_request_metadata, - grpc_error_handle* error) = 0; + virtual bool get_request_metadata( + grpc_polling_entity* pollent, grpc_auth_metadata_context context, + grpc_core::CredentialsMetadataArray* md_array, + grpc_closure* on_request_metadata, grpc_error_handle* error) = 0; // Cancels a pending asynchronous operation started by // grpc_call_credentials_get_request_metadata() with the corresponding // value of \a md_array. virtual void cancel_get_request_metadata( - grpc_credentials_mdelem_array* md_array, grpc_error_handle error) = 0; + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) = 0; virtual grpc_security_level min_security_level() const { return min_security_level_; diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/credentials_metadata.cc b/contrib/libs/grpc/src/core/lib/security/credentials/credentials_metadata.cc deleted file mode 100644 index 9d0284d3eb..0000000000 --- a/contrib/libs/grpc/src/core/lib/security/credentials/credentials_metadata.cc +++ /dev/null @@ -1,61 +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. - * - */ - -#include <grpc/support/port_platform.h> - -#include <string.h> - -#include <grpc/support/alloc.h> - -#include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/slice/slice_internal.h" - -static void mdelem_list_ensure_capacity(grpc_credentials_mdelem_array* list, - size_t additional_space_needed) { - size_t target_size = list->size + additional_space_needed; - // Find the next power of two greater than the target size (i.e., - // whenever we add more space, we double what we already have). - size_t new_size = 2; - while (new_size < target_size) { - new_size *= 2; - } - list->md = static_cast<grpc_mdelem*>( - gpr_realloc(list->md, sizeof(grpc_mdelem) * new_size)); -} - -void grpc_credentials_mdelem_array_add(grpc_credentials_mdelem_array* list, - grpc_mdelem md) { - mdelem_list_ensure_capacity(list, 1); - list->md[list->size++] = GRPC_MDELEM_REF(md); -} - -void grpc_credentials_mdelem_array_append(grpc_credentials_mdelem_array* dst, - grpc_credentials_mdelem_array* src) { - mdelem_list_ensure_capacity(dst, src->size); - for (size_t i = 0; i < src->size; ++i) { - dst->md[dst->size++] = GRPC_MDELEM_REF(src->md[i]); - } -} - -void grpc_credentials_mdelem_array_destroy( - grpc_credentials_mdelem_array* list) { - for (size_t i = 0; i < list->size; ++i) { - GRPC_MDELEM_UNREF(list->md[i]); - } - gpr_free(list->md); -} diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc index e2b901b40b..67e7cb128f 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc @@ -169,9 +169,8 @@ void AwsExternalAccountCredentials::RetrieveRegion() { grpc_http_response_destroy(&ctx_->response); ctx_->response = {}; GRPC_CLOSURE_INIT(&ctx_->closure, OnRetrieveRegion, this, nullptr); - grpc_httpcli_get(ctx_->httpcli_context, ctx_->pollent, - ResourceQuota::Default(), &request, ctx_->deadline, - &ctx_->closure, &ctx_->response); + grpc_httpcli_get(ctx_->pollent, ResourceQuota::Default(), &request, + ctx_->deadline, &ctx_->closure, &ctx_->response); grpc_http_request_destroy(&request.http); } @@ -217,9 +216,8 @@ void AwsExternalAccountCredentials::RetrieveRoleName() { ctx_->response = {}; GRPC_CLOSURE_INIT(&ctx_->closure, OnRetrieveRoleName, this, nullptr); // TODO(ctiller): use the caller's resource quota. - grpc_httpcli_get(ctx_->httpcli_context, ctx_->pollent, - ResourceQuota::Default(), &request, ctx_->deadline, - &ctx_->closure, &ctx_->response); + grpc_httpcli_get(ctx_->pollent, ResourceQuota::Default(), &request, + ctx_->deadline, &ctx_->closure, &ctx_->response); grpc_http_request_destroy(&request.http); } @@ -277,9 +275,8 @@ void AwsExternalAccountCredentials::RetrieveSigningKeys() { ctx_->response = {}; GRPC_CLOSURE_INIT(&ctx_->closure, OnRetrieveSigningKeys, this, nullptr); // TODO(ctiller): use the caller's resource quota. - grpc_httpcli_get(ctx_->httpcli_context, ctx_->pollent, - ResourceQuota::Default(), &request, ctx_->deadline, - &ctx_->closure, &ctx_->response); + grpc_httpcli_get(ctx_->pollent, ResourceQuota::Default(), &request, + ctx_->deadline, &ctx_->closure, &ctx_->response); grpc_http_request_destroy(&request.http); } diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.cc index ddf3079ad1..aa2dd50a12 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.cc @@ -237,10 +237,10 @@ TString ExternalAccountCredentials::debug_string() { // down. void ExternalAccountCredentials::fetch_oauth2( grpc_credentials_metadata_request* metadata_req, - grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent, - grpc_iomgr_cb_func response_cb, grpc_millis deadline) { + grpc_polling_entity* pollent, grpc_iomgr_cb_func response_cb, + grpc_millis deadline) { GPR_ASSERT(ctx_ == nullptr); - ctx_ = new HTTPRequestContext(httpcli_context, pollent, deadline); + ctx_ = new HTTPRequestContext(pollent, deadline); metadata_req_ = metadata_req; response_cb_ = response_cb; auto cb = [this](TString token, grpc_error_handle error) { @@ -326,9 +326,8 @@ void ExternalAccountCredentials::ExchangeToken( grpc_http_response_destroy(&ctx_->response); ctx_->response = {}; GRPC_CLOSURE_INIT(&ctx_->closure, OnExchangeToken, this, nullptr); - grpc_httpcli_post(ctx_->httpcli_context, ctx_->pollent, - ResourceQuota::Default(), &request, body.c_str(), - body.size(), ctx_->deadline, &ctx_->closure, + grpc_httpcli_post(ctx_->pollent, ResourceQuota::Default(), &request, + body.c_str(), body.size(), ctx_->deadline, &ctx_->closure, &ctx_->response); grpc_http_request_destroy(&request.http); } @@ -412,9 +411,8 @@ void ExternalAccountCredentials::ImpersenateServiceAccount() { ctx_->response = {}; GRPC_CLOSURE_INIT(&ctx_->closure, OnImpersenateServiceAccount, this, nullptr); // TODO(ctiller): Use the callers resource quota. - grpc_httpcli_post(ctx_->httpcli_context, ctx_->pollent, - ResourceQuota::Default(), &request, body.c_str(), - body.size(), ctx_->deadline, &ctx_->closure, + grpc_httpcli_post(ctx_->pollent, ResourceQuota::Default(), &request, + body.c_str(), body.size(), ctx_->deadline, &ctx_->closure, &ctx_->response); grpc_http_request_destroy(&request.http); } diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.h index 37945bf452..74c8bf0c27 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.h @@ -61,16 +61,12 @@ class ExternalAccountCredentials // This is a helper struct to pass information between multiple callback based // asynchronous calls. struct HTTPRequestContext { - HTTPRequestContext(grpc_httpcli_context* httpcli_context, - grpc_polling_entity* pollent, grpc_millis deadline) - : httpcli_context(httpcli_context), - pollent(pollent), - deadline(deadline) {} + HTTPRequestContext(grpc_polling_entity* pollent, grpc_millis deadline) + : pollent(pollent), deadline(deadline) {} ~HTTPRequestContext() { grpc_http_response_destroy(&response); } // Contextual parameters passed from // grpc_oauth2_token_fetcher_credentials::fetch_oauth2(). - grpc_httpcli_context* httpcli_context; grpc_polling_entity* pollent; grpc_millis deadline; @@ -92,7 +88,6 @@ class ExternalAccountCredentials // This method implements the common token fetch logic and it will be called // when grpc_oauth2_token_fetcher_credentials request a new access token. void fetch_oauth2(grpc_credentials_metadata_request* req, - grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent, grpc_iomgr_cb_func cb, grpc_millis deadline) override; diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/external/url_external_account_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/external/url_external_account_credentials.cc index 259484a4a5..7036148b40 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/external/url_external_account_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/external/url_external_account_credentials.cc @@ -142,9 +142,8 @@ void UrlExternalAccountCredentials::RetrieveSubjectToken( grpc_http_response_destroy(&ctx_->response); ctx_->response = {}; GRPC_CLOSURE_INIT(&ctx_->closure, OnRetrieveSubjectToken, this, nullptr); - grpc_httpcli_get(ctx_->httpcli_context, ctx_->pollent, - ResourceQuota::Default(), &request, ctx_->deadline, - &ctx_->closure, &ctx_->response); + grpc_httpcli_get(ctx_->pollent, ResourceQuota::Default(), &request, + ctx_->deadline, &ctx_->closure, &ctx_->response); grpc_http_request_destroy(&request.http); } diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.cc index 57a897f068..c3c6102455 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.cc @@ -91,9 +91,9 @@ 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_handle* /*error*/) { - grpc_credentials_mdelem_array_add(md_array, md_); + grpc_core::CredentialsMetadataArray* md_array, + grpc_closure* on_request_metadata, grpc_error_handle* /*error*/) { + md_array->emplace_back(key_.Ref(), value_.Ref()); if (is_async_) { grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_request_metadata, GRPC_ERROR_NONE); @@ -103,7 +103,8 @@ 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_handle error) { + grpc_core::CredentialsMetadataArray* /*md_array*/, + grpc_error_handle error) { GRPC_ERROR_UNREF(error); } diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.h index 806d339249..fcb1373ed9 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.h @@ -63,24 +63,25 @@ class grpc_md_only_test_credentials : public grpc_call_credentials { bool is_async) : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2, GRPC_SECURITY_NONE), - md_(grpc_mdelem_from_slices(grpc_slice_from_copied_string(md_key), - grpc_slice_from_copied_string(md_value))), + key_(grpc_core::Slice::FromCopiedString(md_key)), + value_(grpc_core::Slice::FromCopiedString(md_value)), is_async_(is_async) {} - ~grpc_md_only_test_credentials() override { GRPC_MDELEM_UNREF(md_); } bool get_request_metadata(grpc_polling_entity* pollent, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata, grpc_error_handle* error) override; - void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error_handle error) override; + void cancel_get_request_metadata( + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) override; TString debug_string() override { return "MD only Test Credentials"; }; private: - grpc_mdelem md_; + grpc_core::Slice key_; + grpc_core::Slice value_; bool is_async_; }; diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc index c5201fe07c..0e4ee0a228 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc @@ -172,7 +172,6 @@ static void destroy_pollset(void* p, grpc_error_handle /*e*/) { static int is_metadata_server_reachable() { metadata_server_detector detector; grpc_httpcli_request request; - grpc_httpcli_context context; grpc_closure destroy_closure; /* The http call is local. If it takes more than one sec, it is for sure not on compute engine. */ @@ -186,10 +185,9 @@ static int is_metadata_server_reachable() { memset(&request, 0, sizeof(grpc_httpcli_request)); request.host = const_cast<char*>(GRPC_COMPUTE_ENGINE_DETECTION_HOST); request.http.path = const_cast<char*>("/"); - grpc_httpcli_context_init(&context); grpc_httpcli_get( - &context, &detector.pollent, grpc_core::ResourceQuota::Default(), - &request, grpc_core::ExecCtx::Get()->Now() + max_detection_delay, + &detector.pollent, grpc_core::ResourceQuota::Default(), &request, + grpc_core::ExecCtx::Get()->Now() + max_detection_delay, GRPC_CLOSURE_CREATE(on_metadata_server_detection_http_response, &detector, grpc_schedule_on_exec_ctx), &detector.response); @@ -208,7 +206,6 @@ static int is_metadata_server_reachable() { } } gpr_mu_unlock(g_polling_mu); - grpc_httpcli_context_destroy(&context); GRPC_CLOSURE_INIT(&destroy_closure, destroy_pollset, grpc_polling_entity_pollset(&detector.pollent), grpc_schedule_on_exec_ctx); diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.cc index 96a9db8bae..b73ad869d7 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.cc @@ -30,40 +30,37 @@ #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/surface/api_trace.h" -grpc_google_iam_credentials::~grpc_google_iam_credentials() { - grpc_credentials_mdelem_array_destroy(&md_array_); -} - bool grpc_google_iam_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* /*on_request_metadata*/, grpc_error_handle* /*error*/) { - grpc_credentials_mdelem_array_append(md_array, &md_array_); + if (token_.has_value()) { + md_array->emplace_back(grpc_core::Slice::FromStaticString( + GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY), + token_->Ref()); + } + md_array->emplace_back(grpc_core::Slice::FromStaticString( + GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY), + authority_selector_.Ref()); return true; } void grpc_google_iam_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* /*md_array*/, grpc_error_handle error) { + grpc_core::CredentialsMetadataArray* /*md_array*/, + grpc_error_handle error) { GRPC_ERROR_UNREF(error); } grpc_google_iam_credentials::grpc_google_iam_credentials( const char* token, const char* authority_selector) : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_IAM), + token_(token == nullptr ? y_absl::optional<grpc_core::Slice>() + : grpc_core::Slice::FromCopiedString(token)), + authority_selector_( + grpc_core::Slice::FromCopiedString(authority_selector)), debug_string_(y_absl::StrFormat( "GoogleIAMCredentials{Token:%s,AuthoritySelector:%s}", - token != nullptr ? "present" : "absent", authority_selector)) { - grpc_mdelem md = grpc_mdelem_from_slices( - grpc_slice_from_static_string(GRPC_IAM_AUTHORIZATION_TOKEN_METADATA_KEY), - grpc_slice_from_copied_string(token)); - grpc_credentials_mdelem_array_add(&md_array_, md); - GRPC_MDELEM_UNREF(md); - md = grpc_mdelem_from_slices( - grpc_slice_from_static_string(GRPC_IAM_AUTHORITY_SELECTOR_METADATA_KEY), - grpc_slice_from_copied_string(authority_selector)); - grpc_credentials_mdelem_array_add(&md_array_, md); - GRPC_MDELEM_UNREF(md); -} + token != nullptr ? "present" : "absent", authority_selector)) {} grpc_call_credentials* grpc_google_iam_credentials_create( const char* token, const char* authority_selector, void* reserved) { diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.h index 8d766f424f..3f63446d2d 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.h @@ -29,20 +29,21 @@ class grpc_google_iam_credentials : public grpc_call_credentials { public: grpc_google_iam_credentials(const char* token, const char* authority_selector); - ~grpc_google_iam_credentials() override; bool get_request_metadata(grpc_polling_entity* pollent, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata, grpc_error_handle* error) override; - void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error_handle error) override; + void cancel_get_request_metadata( + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) override; TString debug_string() override { return debug_string_; } private: - grpc_credentials_mdelem_array md_array_; + const y_absl::optional<grpc_core::Slice> token_; + const grpc_core::Slice authority_selector_; const TString debug_string_; }; diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/json_token.cc b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/json_token.cc index 01e804d0ac..4773cb3a5b 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/json_token.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/json_token.cc @@ -22,6 +22,10 @@ #include <string.h> +#include <openssl/bio.h> +#include <openssl/evp.h> +#include <openssl/pem.h> + #include <grpc/grpc_security.h> #include <grpc/support/alloc.h> #include <grpc/support/log.h> @@ -33,12 +37,6 @@ #include "src/core/lib/security/util/json_util.h" #include "src/core/lib/slice/b64.h" -extern "C" { -#include <openssl/bio.h> -#include <openssl/evp.h> -#include <openssl/pem.h> -} - using grpc_core::Json; /* --- Constants. --- */ diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc index 2633dc8472..cb9a7f2d97 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc @@ -41,23 +41,15 @@ using grpc_core::Json; -void grpc_service_account_jwt_access_credentials::reset_cache() { - GRPC_MDELEM_UNREF(cached_.jwt_md); - cached_.jwt_md = GRPC_MDNULL; - cached_.service_url.clear(); - cached_.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME); -} - grpc_service_account_jwt_access_credentials:: ~grpc_service_account_jwt_access_credentials() { grpc_auth_json_key_destruct(&key_); - reset_cache(); gpr_mu_destroy(&cache_mu_); } bool grpc_service_account_jwt_access_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, 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); @@ -71,42 +63,38 @@ bool grpc_service_account_jwt_access_credentials::get_request_metadata( return true; } /* See if we can return a cached jwt. */ - grpc_mdelem jwt_md = GRPC_MDNULL; + y_absl::optional<grpc_core::Slice> jwt_value; { gpr_mu_lock(&cache_mu_); - if (!cached_.service_url.empty() && cached_.service_url == *uri && - !GRPC_MDISNULL(cached_.jwt_md) && + if (cached_.has_value() && cached_->service_url == *uri && (gpr_time_cmp( - gpr_time_sub(cached_.jwt_expiration, gpr_now(GPR_CLOCK_REALTIME)), + gpr_time_sub(cached_->jwt_expiration, gpr_now(GPR_CLOCK_REALTIME)), refresh_threshold) > 0)) { - jwt_md = GRPC_MDELEM_REF(cached_.jwt_md); + jwt_value = cached_->jwt_value.Ref(); } gpr_mu_unlock(&cache_mu_); } - if (GRPC_MDISNULL(jwt_md)) { + if (!jwt_value.has_value()) { char* jwt = nullptr; /* Generate a new jwt. */ gpr_mu_lock(&cache_mu_); - reset_cache(); + cached_.reset(); jwt = grpc_jwt_encode_and_sign(&key_, uri->c_str(), jwt_lifetime_, nullptr); if (jwt != nullptr) { TString md_value = y_absl::StrCat("Bearer ", jwt); gpr_free(jwt); - cached_.jwt_expiration = - gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), jwt_lifetime_); - cached_.service_url = std::move(*uri); - cached_.jwt_md = grpc_mdelem_from_slices( - grpc_slice_from_static_string(GRPC_AUTHORIZATION_METADATA_KEY), - grpc_slice_from_cpp_string(std::move(md_value))); - jwt_md = GRPC_MDELEM_REF(cached_.jwt_md); + jwt_value = grpc_core::Slice::FromCopiedString(md_value); + cached_ = {jwt_value->Ref(), std::move(*uri), + gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), jwt_lifetime_)}; } gpr_mu_unlock(&cache_mu_); } - if (!GRPC_MDISNULL(jwt_md)) { - grpc_credentials_mdelem_array_add(md_array, jwt_md); - GRPC_MDELEM_UNREF(jwt_md); + if (jwt_value.has_value()) { + md_array->emplace_back( + grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY), + std::move(*jwt_value)); } else { *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Could not generate JWT."); } @@ -114,7 +102,8 @@ 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_handle error) { + grpc_core::CredentialsMetadataArray* /*md_array*/, + grpc_error_handle error) { GRPC_ERROR_UNREF(error); } @@ -131,7 +120,6 @@ grpc_service_account_jwt_access_credentials:: } jwt_lifetime_ = token_lifetime; gpr_mu_init(&cache_mu_); - reset_cache(); } grpc_core::RefCountedPtr<grpc_call_credentials> diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.h index aff57aeee9..ea2c48abeb 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.h @@ -40,12 +40,13 @@ class grpc_service_account_jwt_access_credentials bool get_request_metadata(grpc_polling_entity* pollent, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata, grpc_error_handle* error) override; - void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error_handle error) override; + void cancel_get_request_metadata( + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) override; const gpr_timespec& jwt_lifetime() const { return jwt_lifetime_; } const grpc_auth_json_key& key() const { return key_; } @@ -58,16 +59,15 @@ class grpc_service_account_jwt_access_credentials }; private: - void reset_cache(); - // Have a simple cache for now with just 1 entry. We could have a map based on // the service_url for a more sophisticated one. gpr_mu cache_mu_; - struct { - grpc_mdelem jwt_md = GRPC_MDNULL; + struct Cache { + grpc_core::Slice jwt_value; TString service_url; gpr_timespec jwt_expiration; - } cached_; + }; + y_absl::optional<Cache> cached_; grpc_auth_json_key key_; gpr_timespec jwt_lifetime_; diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc index 2f96acf0ed..d1df6e649e 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc @@ -23,17 +23,15 @@ #include <limits.h> #include <string.h> +#include <openssl/bn.h> +#include <openssl/pem.h> +#include <openssl/rsa.h> + #include <grpc/support/alloc.h> #include <grpc/support/log.h> #include <grpc/support/string_util.h> #include <grpc/support/sync.h> -extern "C" { -#include <openssl/bn.h> -#include <openssl/pem.h> -#include <openssl/rsa.h> -} - #include "src/core/lib/gpr/string.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/http/httpcli.h" @@ -397,7 +395,6 @@ struct grpc_jwt_verifier { email_key_mapping* mappings; size_t num_mappings; /* Should be very few, linear search ok. */ size_t allocated_mappings; - grpc_httpcli_context http_ctx; }; static Json json_from_http(const grpc_httpcli_response* response) { @@ -700,8 +697,7 @@ static void on_openid_config_retrieved(void* user_data, channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ grpc_httpcli_get( - &ctx->verifier->http_ctx, &ctx->pollent, - grpc_core::ResourceQuota::Default(), &req, + &ctx->pollent, grpc_core::ResourceQuota::Default(), &req, grpc_core::ExecCtx::Get()->Now() + grpc_jwt_verifier_max_delay, GRPC_CLOSURE_CREATE(on_keys_retrieved, ctx, grpc_schedule_on_exec_ctx), &ctx->responses[HTTP_RESPONSE_KEYS]); @@ -824,8 +820,7 @@ static void retrieve_key_and_verify(verifier_cb_ctx* ctx) { channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ grpc_httpcli_get( - &ctx->verifier->http_ctx, &ctx->pollent, - grpc_core::ResourceQuota::Default(), &req, + &ctx->pollent, grpc_core::ResourceQuota::Default(), &req, grpc_core::ExecCtx::Get()->Now() + grpc_jwt_verifier_max_delay, http_cb, &ctx->responses[rsp_idx]); gpr_free(req.host); @@ -886,7 +881,6 @@ grpc_jwt_verifier* grpc_jwt_verifier_create( const grpc_jwt_verifier_email_domain_key_url_mapping* mappings, size_t num_mappings) { grpc_jwt_verifier* v = grpc_core::Zalloc<grpc_jwt_verifier>(); - grpc_httpcli_context_init(&v->http_ctx); /* We know at least of one mapping. */ v->allocated_mappings = 1 + num_mappings; @@ -908,7 +902,6 @@ grpc_jwt_verifier* grpc_jwt_verifier_create( void grpc_jwt_verifier_destroy(grpc_jwt_verifier* v) { size_t i; if (v == nullptr) return; - grpc_httpcli_context_destroy(&v->http_ctx); if (v->mappings != nullptr) { for (i = 0; i < v->num_mappings; i++) { gpr_free(v->mappings[i].email_domain); diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc index 4338f5a081..9c7681982a 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc @@ -127,15 +127,14 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token* refresh_token) { grpc_oauth2_token_fetcher_credentials:: ~grpc_oauth2_token_fetcher_credentials() { - GRPC_MDELEM_UNREF(access_token_md_); gpr_mu_destroy(&mu_); grpc_pollset_set_destroy(grpc_polling_entity_pollset_set(&pollent_)); - grpc_httpcli_context_destroy(&httpcli_context_); } grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( - const grpc_http_response* response, grpc_mdelem* token_md, + const grpc_http_response* response, + y_absl::optional<grpc_core::Slice>* token_value, grpc_millis* token_lifetime) { char* null_terminated_body = nullptr; grpc_credentials_status status = GRPC_CREDENTIALS_OK; @@ -204,19 +203,13 @@ grpc_oauth2_token_fetcher_credentials_parse_server_response( } expires_in = it->second.string_value().c_str(); *token_lifetime = strtol(expires_in, nullptr, 10) * GPR_MS_PER_SEC; - if (!GRPC_MDISNULL(*token_md)) GRPC_MDELEM_UNREF(*token_md); - *token_md = grpc_mdelem_from_slices( - grpc_core::ExternallyManagedSlice(GRPC_AUTHORIZATION_METADATA_KEY), - grpc_slice_from_cpp_string( - y_absl::StrCat(token_type, " ", access_token))); + *token_value = grpc_core::Slice::FromCopiedString( + y_absl::StrCat(token_type, " ", access_token)); status = GRPC_CREDENTIALS_OK; } end: - if (status != GRPC_CREDENTIALS_OK && !GRPC_MDISNULL(*token_md)) { - GRPC_MDELEM_UNREF(*token_md); - *token_md = GRPC_MDNULL; - } + if (status != GRPC_CREDENTIALS_OK) *token_value = y_absl::nullopt; gpr_free(null_terminated_body); return status; } @@ -233,17 +226,21 @@ 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_handle error) { - grpc_mdelem access_token_md = GRPC_MDNULL; + y_absl::optional<grpc_core::Slice> access_token_value; grpc_millis token_lifetime = 0; grpc_credentials_status status = error == GRPC_ERROR_NONE ? grpc_oauth2_token_fetcher_credentials_parse_server_response( - &r->response, &access_token_md, &token_lifetime) + &r->response, &access_token_value, &token_lifetime) : GRPC_CREDENTIALS_ERROR; // Update cache and grab list of pending requests. gpr_mu_lock(&mu_); token_fetch_pending_ = false; - access_token_md_ = GRPC_MDELEM_REF(access_token_md); + if (access_token_value.has_value()) { + access_token_value_ = access_token_value->Ref(); + } else { + access_token_value_ = y_absl::nullopt; + } token_expiration_ = status == GRPC_CREDENTIALS_OK ? gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), @@ -256,8 +253,9 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response( while (pending_request != nullptr) { 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); + pending_request->md_array->emplace_back( + grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY), + access_token_value->Ref()); } else { new_error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING( "Error occurred when fetching oauth2 token.", &error, 1); @@ -270,31 +268,31 @@ void grpc_oauth2_token_fetcher_credentials::on_http_response( pending_request = pending_request->next; gpr_free(prev); } - GRPC_MDELEM_UNREF(access_token_md); Unref(); grpc_credentials_metadata_request_destroy(r); } 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_handle* /*error*/) { + grpc_core::CredentialsMetadataArray* md_array, + grpc_closure* on_request_metadata, 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; - grpc_mdelem cached_access_token_md = GRPC_MDNULL; + y_absl::optional<grpc_core::Slice> cached_access_token_value; gpr_mu_lock(&mu_); - if (!GRPC_MDISNULL(access_token_md_) && + if (access_token_value_.has_value() && gpr_time_cmp( gpr_time_sub(token_expiration_, gpr_now(GPR_CLOCK_MONOTONIC)), gpr_time_from_seconds(GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS, GPR_TIMESPAN)) > 0) { - cached_access_token_md = GRPC_MDELEM_REF(access_token_md_); + cached_access_token_value = access_token_value_->Ref(); } - if (!GRPC_MDISNULL(cached_access_token_md)) { + if (cached_access_token_value.has_value()) { gpr_mu_unlock(&mu_); - grpc_credentials_mdelem_array_add(md_array, cached_access_token_md); - GRPC_MDELEM_UNREF(cached_access_token_md); + md_array->emplace_back( + grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY), + std::move(*cached_access_token_value)); return true; } // Couldn't get the token from the cache. @@ -318,15 +316,14 @@ bool grpc_oauth2_token_fetcher_credentials::get_request_metadata( if (start_fetch) { Ref().release(); fetch_oauth2(grpc_credentials_metadata_request_create(this->Ref()), - &httpcli_context_, &pollent_, - on_oauth2_token_fetcher_http_response, + &pollent_, on_oauth2_token_fetcher_http_response, grpc_core::ExecCtx::Get()->Now() + refresh_threshold); } return false; } void grpc_oauth2_token_fetcher_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* md_array, grpc_error_handle error) { + grpc_core::CredentialsMetadataArray* md_array, grpc_error_handle error) { gpr_mu_lock(&mu_); grpc_oauth2_pending_get_request_metadata* prev = nullptr; grpc_oauth2_pending_get_request_metadata* pending_request = pending_requests_; @@ -358,7 +355,6 @@ grpc_oauth2_token_fetcher_credentials::grpc_oauth2_token_fetcher_credentials() pollent_(grpc_polling_entity_create_from_pollset_set( grpc_pollset_set_create())) { gpr_mu_init(&mu_); - grpc_httpcli_context_init(&httpcli_context_); } TString grpc_oauth2_token_fetcher_credentials::debug_string() { @@ -379,7 +375,6 @@ class grpc_compute_engine_token_fetcher_credentials protected: void fetch_oauth2(grpc_credentials_metadata_request* metadata_req, - grpc_httpcli_context* http_context, grpc_polling_entity* pollent, grpc_iomgr_cb_func response_cb, grpc_millis deadline) override { @@ -395,8 +390,8 @@ class grpc_compute_engine_token_fetcher_credentials /* TODO(ctiller): Carry the memory quota in ctx and share it with the host channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ - grpc_httpcli_get(http_context, pollent, grpc_core::ResourceQuota::Default(), - &request, deadline, + grpc_httpcli_get(pollent, grpc_core::ResourceQuota::Default(), &request, + deadline, GRPC_CLOSURE_INIT(&http_get_cb_closure_, response_cb, metadata_req, grpc_schedule_on_exec_ctx), &metadata_req->response); @@ -435,8 +430,8 @@ grpc_google_refresh_token_credentials:: void grpc_google_refresh_token_credentials::fetch_oauth2( grpc_credentials_metadata_request* metadata_req, - grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent, - grpc_iomgr_cb_func response_cb, grpc_millis deadline) { + grpc_polling_entity* pollent, grpc_iomgr_cb_func response_cb, + grpc_millis deadline) { grpc_http_header header = { const_cast<char*>("Content-Type"), const_cast<char*>("application/x-www-form-urlencoded")}; @@ -453,9 +448,8 @@ void grpc_google_refresh_token_credentials::fetch_oauth2( /* TODO(ctiller): Carry the memory quota in ctx and share it with the host channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ - grpc_httpcli_post(httpcli_context, pollent, - grpc_core::ResourceQuota::Default(), &request, body.c_str(), - body.size(), deadline, + grpc_httpcli_post(pollent, grpc_core::ResourceQuota::Default(), &request, + body.c_str(), body.size(), deadline, GRPC_CLOSURE_INIT(&http_post_cb_closure_, response_cb, metadata_req, grpc_schedule_on_exec_ctx), &metadata_req->response); @@ -556,7 +550,6 @@ class StsTokenFetcherCredentials private: void fetch_oauth2(grpc_credentials_metadata_request* metadata_req, - grpc_httpcli_context* http_context, grpc_polling_entity* pollent, grpc_iomgr_cb_func response_cb, grpc_millis deadline) override { @@ -584,8 +577,8 @@ class StsTokenFetcherCredentials channel. This would allow us to cancel an authentication query when under extreme memory pressure. */ grpc_httpcli_post( - http_context, pollent, ResourceQuota::Default(), &request, body, - body_length, deadline, + pollent, ResourceQuota::Default(), &request, body, body_length, + deadline, GRPC_CLOSURE_INIT(&http_post_cb_closure_, response_cb, metadata_req, grpc_schedule_on_exec_ctx), &metadata_req->response); @@ -705,36 +698,30 @@ grpc_call_credentials* grpc_sts_credentials_create( // Oauth2 Access Token credentials. // -grpc_access_token_credentials::~grpc_access_token_credentials() { - GRPC_MDELEM_UNREF(access_token_md_); -} - bool grpc_access_token_credentials::get_request_metadata( grpc_polling_entity* /*pollent*/, grpc_auth_metadata_context /*context*/, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* /*on_request_metadata*/, grpc_error_handle* /*error*/) { - grpc_credentials_mdelem_array_add(md_array, access_token_md_); + md_array->emplace_back( + grpc_core::Slice::FromStaticString(GRPC_AUTHORIZATION_METADATA_KEY), + access_token_value_.Ref()); return true; } void grpc_access_token_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* /*md_array*/, grpc_error_handle error) { + grpc_core::CredentialsMetadataArray* /*md_array*/, + grpc_error_handle error) { GRPC_ERROR_UNREF(error); } grpc_access_token_credentials::grpc_access_token_credentials( const char* access_token) - : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2) { - grpc_core::ExecCtx exec_ctx; - access_token_md_ = grpc_mdelem_from_slices( - grpc_core::ExternallyManagedSlice(GRPC_AUTHORIZATION_METADATA_KEY), - grpc_slice_from_cpp_string(y_absl::StrCat("Bearer ", access_token))); -} + : grpc_call_credentials(GRPC_CALL_CREDENTIALS_TYPE_OAUTH2), + access_token_value_(grpc_core::Slice::FromCopiedString( + y_absl::StrCat("Bearer ", access_token))) {} TString grpc_access_token_credentials::debug_string() { - bool access_token_present = !GRPC_MDISNULL(access_token_md_); - return y_absl::StrFormat("AccessTokenCredentials{Token:%s}", - access_token_present ? "present" : "absent"); + return y_absl::StrFormat("AccessTokenCredentials{Token:present}"); } grpc_call_credentials* grpc_access_token_credentials_create( diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h index c01aa057d4..61df68bc0a 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h @@ -64,7 +64,7 @@ void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token* refresh_token); // from an http service. struct grpc_oauth2_pending_get_request_metadata { - grpc_credentials_mdelem_array* md_array; + grpc_core::CredentialsMetadataArray* md_array; grpc_closure* on_request_metadata; grpc_polling_entity* pollent; struct grpc_oauth2_pending_get_request_metadata* next; @@ -77,12 +77,13 @@ class grpc_oauth2_token_fetcher_credentials : public grpc_call_credentials { bool get_request_metadata(grpc_polling_entity* pollent, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata, grpc_error_handle* error) override; - void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error_handle error) override; + void cancel_get_request_metadata( + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) override; void on_http_response(grpc_credentials_metadata_request* r, grpc_error_handle error); @@ -90,17 +91,15 @@ class grpc_oauth2_token_fetcher_credentials : public grpc_call_credentials { protected: virtual void fetch_oauth2(grpc_credentials_metadata_request* req, - grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent, grpc_iomgr_cb_func cb, grpc_millis deadline) = 0; private: gpr_mu mu_; - grpc_mdelem access_token_md_ = GRPC_MDNULL; + y_absl::optional<grpc_core::Slice> access_token_value_; gpr_timespec token_expiration_; bool token_fetch_pending_ = false; grpc_oauth2_pending_get_request_metadata* pending_requests_ = nullptr; - grpc_httpcli_context httpcli_context_; grpc_polling_entity pollent_; }; @@ -120,7 +119,6 @@ class grpc_google_refresh_token_credentials final protected: void fetch_oauth2(grpc_credentials_metadata_request* req, - grpc_httpcli_context* httpcli_context, grpc_polling_entity* pollent, grpc_iomgr_cb_func cb, grpc_millis deadline) override; @@ -133,21 +131,21 @@ class grpc_google_refresh_token_credentials final class grpc_access_token_credentials final : public grpc_call_credentials { public: explicit grpc_access_token_credentials(const char* access_token); - ~grpc_access_token_credentials() override; bool get_request_metadata(grpc_polling_entity* pollent, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata, grpc_error_handle* error) override; - void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error_handle error) override; + void cancel_get_request_metadata( + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) override; TString debug_string() override; private: - grpc_mdelem access_token_md_; + const grpc_core::Slice access_token_value_; }; // Private constructor for refresh token credentials from an already parsed @@ -159,8 +157,8 @@ grpc_refresh_token_credentials_create_from_auth_refresh_token( // Exposed for testing only. grpc_credentials_status grpc_oauth2_token_fetcher_credentials_parse_server_response( - const struct grpc_http_response* response, grpc_mdelem* token_md, - grpc_millis* token_lifetime); + const struct grpc_http_response* response, + y_absl::optional<grpc_core::Slice>* token_value, grpc_millis* token_lifetime); namespace grpc_core { // Exposed for testing only. This function validates the options, ensuring that diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc index 56fc42394c..81c015627f 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc @@ -110,10 +110,9 @@ static grpc_error_handle process_plugin_result( error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Illegal metadata"); } else { for (size_t i = 0; i < num_md; ++i) { - grpc_mdelem mdelem = - grpc_mdelem_create(md[i].key, md[i].value, nullptr); - grpc_credentials_mdelem_array_add(r->md_array, mdelem); - GRPC_MDELEM_UNREF(mdelem); + r->md_array->emplace_back( + grpc_core::Slice(grpc_slice_ref_internal(md[i].key)), + grpc_core::Slice(grpc_slice_ref_internal(md[i].value))); } } } @@ -155,8 +154,8 @@ 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_handle* error) { + grpc_core::CredentialsMetadataArray* md_array, + grpc_closure* on_request_metadata, grpc_error_handle* error) { bool retval = true; // Synchronous return. if (plugin_.get_metadata != nullptr) { // Create pending_request object. @@ -229,7 +228,7 @@ bool grpc_plugin_credentials::get_request_metadata( } void grpc_plugin_credentials::cancel_get_request_metadata( - grpc_credentials_mdelem_array* md_array, grpc_error_handle error) { + grpc_core::CredentialsMetadataArray* md_array, grpc_error_handle error) { gpr_mu_lock(&mu_); for (pending_request* pending_request = pending_requests_; pending_request != nullptr; pending_request = pending_request->next) { diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.h index b56a94d601..2d0c3a458f 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.h @@ -33,7 +33,7 @@ struct grpc_plugin_credentials final : public grpc_call_credentials { struct pending_request { bool cancelled; struct grpc_plugin_credentials* creds; - grpc_credentials_mdelem_array* md_array; + grpc_core::CredentialsMetadataArray* md_array; grpc_closure* on_request_metadata; struct pending_request* prev; struct pending_request* next; @@ -45,12 +45,13 @@ struct grpc_plugin_credentials final : public grpc_call_credentials { bool get_request_metadata(grpc_polling_entity* pollent, grpc_auth_metadata_context context, - grpc_credentials_mdelem_array* md_array, + grpc_core::CredentialsMetadataArray* md_array, grpc_closure* on_request_metadata, grpc_error_handle* error) override; - void cancel_get_request_metadata(grpc_credentials_mdelem_array* md_array, - grpc_error_handle error) override; + void cancel_get_request_metadata( + grpc_core::CredentialsMetadataArray* md_array, + grpc_error_handle error) override; // Checks if the request has been cancelled. // If not, removes it from the pending list, so that it cannot be diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc b/contrib/libs/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc index 093f1ad0bf..1767871fc2 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc @@ -27,6 +27,7 @@ #include <grpc/support/string_util.h> #include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/security/security_connector/ssl_utils.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/tsi/ssl_transport_security.h" @@ -34,16 +35,6 @@ // SSL Channel Credentials. // -void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair* kp, - size_t num_key_cert_pairs) { - if (kp == nullptr) return; - for (size_t i = 0; i < num_key_cert_pairs; i++) { - gpr_free(const_cast<char*>(kp[i].private_key)); - gpr_free(const_cast<char*>(kp[i].cert_chain)); - } - gpr_free(kp); -} - grpc_ssl_credentials::grpc_ssl_credentials( const char* pem_root_certs, grpc_ssl_pem_key_cert_pair* pem_key_cert_pair, const grpc_ssl_verify_peer_options* verify_options) diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc index 8042cf2668..0617fd8ca1 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +++ b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc @@ -91,6 +91,12 @@ void grpc_tls_credentials_options_set_certificate_verifier( options->set_certificate_verifier(verifier->Ref()); } +void grpc_tls_credentials_options_set_crl_directory( + grpc_tls_credentials_options* options, const char* crl_directory) { + GPR_ASSERT(options != nullptr); + options->set_crl_directory(crl_directory); +} + void grpc_tls_credentials_options_set_check_call_host( grpc_tls_credentials_options* options, int check_call_host) { GPR_ASSERT(options != nullptr); diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h index 63b7bcef5b..25567e9ced 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h @@ -60,6 +60,7 @@ struct grpc_tls_credentials_options const TString& root_cert_name() { return root_cert_name_; } bool watch_identity_pair() { return watch_identity_pair_; } const TString& identity_cert_name() { return identity_cert_name_; } + const TString& crl_directory() { return crl_directory_; } // Setters for member fields. void set_cert_request_type( @@ -112,6 +113,11 @@ struct grpc_tls_credentials_options identity_cert_name_ = std::move(identity_cert_name); } + // gRPC will enforce CRLs on all handshakes from all hashed CRL files inside + // of the crl_directory. If not set, an empty string will be used, which will + // not enable CRL checking. Only supported for OpenSSL version > 1.1. + void set_crl_directory(TString path) { crl_directory_ = std::move(path); } + private: grpc_ssl_client_certificate_request_type cert_request_type_ = GRPC_SSL_DONT_REQUEST_CLIENT_CERTIFICATE; @@ -125,6 +131,7 @@ struct grpc_tls_credentials_options TString root_cert_name_; bool watch_identity_pair_ = false; TString identity_cert_name_; + TString crl_directory_; }; #endif // GRPC_CORE_LIB_SECURITY_CREDENTIALS_TLS_GRPC_TLS_CREDENTIALS_OPTIONS_H diff --git a/contrib/libs/grpc/src/core/lib/security/credentials/xds/xds_credentials.h b/contrib/libs/grpc/src/core/lib/security/credentials/xds/xds_credentials.h index ee2e71c583..a7525e6930 100644 --- a/contrib/libs/grpc/src/core/lib/security/credentials/xds/xds_credentials.h +++ b/contrib/libs/grpc/src/core/lib/security/credentials/xds/xds_credentials.h @@ -23,7 +23,7 @@ #include <grpc/grpc_security.h> -#include "src/core/ext/xds/xds_api.h" +#include "src/core/lib/matchers/matchers.h" #include "src/core/lib/security/credentials/credentials.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc b/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc index 67ce84ac80..12c843ee9c 100644 --- a/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc +++ b/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc @@ -25,15 +25,11 @@ #include <grpc/support/log.h> #include <grpc/support/string_util.h> -#include "src/core/ext/transport/chttp2/alpn/alpn.h" #include "src/core/lib/channel/channel_args.h" #include "src/core/lib/channel/handshaker.h" #include "src/core/lib/gpr/string.h" -#include "src/core/lib/gprpp/host_port.h" -#include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" -#include "src/core/lib/security/security_connector/load_system_roots.h" #include "src/core/lib/security/security_connector/security_connector.h" #include "src/core/lib/security/transport/security_handshaker.h" diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.h b/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.h index 6d5ba7fb75..73a23a41cf 100644 --- a/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.h +++ b/contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.h @@ -30,11 +30,15 @@ #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/tcp_server.h" -#include "src/core/tsi/ssl_transport_security.h" #include "src/core/tsi/transport_security_interface.h" extern grpc_core::DebugOnlyTraceFlag grpc_trace_security_connector_refcount; +/* --- URL schemes. --- */ + +#define GRPC_SSL_URL_SCHEME "https" +#define GRPC_FAKE_SECURITY_URL_SCHEME "http+fake_security" + typedef enum { GRPC_SECURITY_OK = 0, GRPC_SECURITY_ERROR } grpc_security_status; /* --- security_connector object. --- diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc index 4e2ded5cac..d7e5ba282e 100644 --- a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc +++ b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc @@ -94,30 +94,6 @@ const char* grpc_get_ssl_cipher_suites(void) { return cipher_suites; } -grpc_security_level grpc_tsi_security_level_string_to_enum( - const char* security_level) { - if (strcmp(security_level, "TSI_INTEGRITY_ONLY") == 0) { - return GRPC_INTEGRITY_ONLY; - } else if (strcmp(security_level, "TSI_PRIVACY_AND_INTEGRITY") == 0) { - return GRPC_PRIVACY_AND_INTEGRITY; - } - return GRPC_SECURITY_NONE; -} - -const char* grpc_security_level_to_string(grpc_security_level security_level) { - if (security_level == GRPC_PRIVACY_AND_INTEGRITY) { - return "GRPC_PRIVACY_AND_INTEGRITY"; - } else if (security_level == GRPC_INTEGRITY_ONLY) { - return "GRPC_INTEGRITY_ONLY"; - } - return "GRPC_SECURITY_NONE"; -} - -bool grpc_check_security_level(grpc_security_level channel_level, - grpc_security_level call_cred_level) { - return static_cast<int>(channel_level) >= static_cast<int>(call_cred_level); -} - tsi_client_certificate_request_type grpc_get_tsi_client_certificate_request_type( grpc_ssl_client_certificate_request_type grpc_request_type) { @@ -181,6 +157,16 @@ grpc_error_handle grpc_ssl_check_peer_name(y_absl::string_view peer_name, return GRPC_ERROR_NONE; } +void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair* kp, + size_t num_key_cert_pairs) { + if (kp == nullptr) return; + for (size_t i = 0; i < num_key_cert_pairs; i++) { + gpr_free(const_cast<char*>(kp[i].private_key)); + gpr_free(const_cast<char*>(kp[i].cert_chain)); + } + gpr_free(kp); +} + bool grpc_ssl_check_call_host(y_absl::string_view host, y_absl::string_view target_name, y_absl::string_view overridden_target_name, @@ -425,6 +411,7 @@ grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init( tsi_ssl_pem_key_cert_pair* pem_key_cert_pair, const char* pem_root_certs, bool skip_server_certificate_verification, tsi_tls_version min_tls_version, tsi_tls_version max_tls_version, tsi_ssl_session_cache* ssl_session_cache, + const char* crl_directory, tsi_ssl_client_handshaker_factory** handshaker_factory) { const char* root_certs; const tsi_ssl_root_certs_store* root_store; @@ -461,6 +448,7 @@ grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init( skip_server_certificate_verification; options.min_tls_version = min_tls_version; options.max_tls_version = max_tls_version; + options.crl_directory = crl_directory; const tsi_result result = tsi_create_ssl_client_handshaker_factory_with_options(&options, handshaker_factory); @@ -478,6 +466,7 @@ grpc_security_status grpc_ssl_tsi_server_handshaker_factory_init( const char* pem_root_certs, grpc_ssl_client_certificate_request_type client_certificate_request, tsi_tls_version min_tls_version, tsi_tls_version max_tls_version, + const char* crl_directory, tsi_ssl_server_handshaker_factory** handshaker_factory) { size_t num_alpn_protocols = 0; const char** alpn_protocol_strings = @@ -493,6 +482,7 @@ grpc_security_status grpc_ssl_tsi_server_handshaker_factory_init( options.num_alpn_protocols = static_cast<uint16_t>(num_alpn_protocols); options.min_tls_version = min_tls_version; options.max_tls_version = max_tls_version; + options.crl_directory = crl_directory; const tsi_result result = tsi_create_ssl_server_handshaker_factory_with_options(&options, handshaker_factory); diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.h b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.h index 7e122d94d6..d2cd26a9e0 100644 --- a/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.h +++ b/contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.h @@ -40,9 +40,6 @@ /* --- Util --- */ -/* --- URL schemes. --- */ -#define GRPC_SSL_URL_SCHEME "https" - /* Check ALPN information returned from SSL handshakes. */ grpc_error_handle grpc_ssl_check_alpn(const tsi_peer* peer); @@ -69,20 +66,9 @@ tsi_client_certificate_request_type grpc_get_tsi_client_certificate_request_type( grpc_ssl_client_certificate_request_type grpc_request_type); -/* Map tsi_security_level string to grpc_security_level enum. */ -grpc_security_level grpc_tsi_security_level_string_to_enum( - const char* security_level); - /* Map grpc_tls_version to tsi_tls_version. */ tsi_tls_version grpc_get_tsi_tls_version(grpc_tls_version tls_version); -/* Map grpc_security_level enum to a string. */ -const char* grpc_security_level_to_string(grpc_security_level security_level); - -/* Check security level of channel and call credential.*/ -bool grpc_check_security_level(grpc_security_level channel_level, - grpc_security_level call_cred_level); - /* Return an array of strings containing alpn protocols. */ const char** grpc_fill_alpn_protocol_strings(size_t* num_alpn_protocols); @@ -91,6 +77,7 @@ grpc_security_status grpc_ssl_tsi_client_handshaker_factory_init( tsi_ssl_pem_key_cert_pair* key_cert_pair, const char* pem_root_certs, bool skip_server_certificate_verification, tsi_tls_version min_tls_version, tsi_tls_version max_tls_version, tsi_ssl_session_cache* ssl_session_cache, + const char* crl_directory, tsi_ssl_client_handshaker_factory** handshaker_factory); grpc_security_status grpc_ssl_tsi_server_handshaker_factory_init( @@ -98,8 +85,12 @@ grpc_security_status grpc_ssl_tsi_server_handshaker_factory_init( const char* pem_root_certs, grpc_ssl_client_certificate_request_type client_certificate_request, tsi_tls_version min_tls_version, tsi_tls_version max_tls_version, + const char* crl_directory, tsi_ssl_server_handshaker_factory** handshaker_factory); +/* Free the memory occupied by key cert pairs. */ +void grpc_tsi_ssl_pem_key_cert_pairs_destroy(tsi_ssl_pem_key_cert_pair* kp, + size_t num_key_cert_pairs); /* Exposed for testing only. */ grpc_core::RefCountedPtr<grpc_auth_context> grpc_ssl_peer_to_auth_context( const tsi_peer* peer, const char* transport_security_type); diff --git a/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc b/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc index dfeafbae60..d015a60c79 100644 --- a/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc +++ b/contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc @@ -34,7 +34,6 @@ #include <grpc/support/string_util.h> #include "src/core/lib/gprpp/host_port.h" -#include "src/core/lib/security/credentials/ssl/ssl_credentials.h" #include "src/core/lib/security/credentials/tls/tls_credentials.h" #include "src/core/lib/security/security_connector/ssl_utils.h" #include "src/core/lib/security/transport/security_handshaker.h" @@ -538,7 +537,7 @@ TlsChannelSecurityConnector::UpdateHandshakerFactoryLocked() { skip_server_certificate_verification, grpc_get_tsi_tls_version(options_->min_tls_version()), grpc_get_tsi_tls_version(options_->max_tls_version()), ssl_session_cache_, - &client_handshaker_factory_); + options_->crl_directory().c_str(), &client_handshaker_factory_); /* Free memory. */ if (pem_key_cert_pair != nullptr) { grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pair, 1); @@ -806,7 +805,7 @@ TlsServerSecurityConnector::UpdateHandshakerFactoryLocked() { options_->cert_request_type(), grpc_get_tsi_tls_version(options_->min_tls_version()), grpc_get_tsi_tls_version(options_->max_tls_version()), - &server_handshaker_factory_); + options_->crl_directory().c_str(), &server_handshaker_factory_); /* Free memory. */ grpc_tsi_ssl_pem_key_cert_pairs_destroy(pem_key_cert_pairs, num_key_cert_pairs); diff --git a/contrib/libs/grpc/src/core/lib/security/transport/auth_filters.h b/contrib/libs/grpc/src/core/lib/security/transport/auth_filters.h index fc9e59cf5f..9608c1633a 100644 --- a/contrib/libs/grpc/src/core/lib/security/transport/auth_filters.h +++ b/contrib/libs/grpc/src/core/lib/security/transport/auth_filters.h @@ -33,4 +33,11 @@ void grpc_auth_metadata_context_build( const grpc_slice& call_method, grpc_auth_context* auth_context, grpc_auth_metadata_context* auth_md_context); +// Exposed for testing purposes only. +// Check if the channel's security level is higher or equal to +// that of call credentials to make a decision whether the transfer +// of call credentials should be allowed or not. +bool grpc_check_security_level(grpc_security_level channel_level, + grpc_security_level call_cred_level); + #endif /* GRPC_CORE_LIB_SECURITY_TRANSPORT_AUTH_FILTERS_H */ diff --git a/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc b/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc index e48f106f22..54884f1efe 100644 --- a/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc +++ b/contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc @@ -30,16 +30,15 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/gpr/string.h" +#include "src/core/lib/iomgr/error.h" #include "src/core/lib/profiling/timers.h" #include "src/core/lib/security/context/security_context.h" #include "src/core/lib/security/credentials/credentials.h" #include "src/core/lib/security/security_connector/security_connector.h" -#include "src/core/lib/security/security_connector/ssl_utils.h" #include "src/core/lib/security/transport/auth_filters.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/surface/call.h" -#include "src/core/lib/transport/static_metadata.h" #define MAX_CREDENTIALS_METADATA_COUNT 4 @@ -65,6 +64,9 @@ struct channel_data { struct call_data { call_data(grpc_call_element* elem, const grpc_call_element_args& args) : owning_call(args.call_stack), call_combiner(args.call_combiner) { + host.Init(); + method.Init(); + md_array.Init(); channel_data* chand = static_cast<channel_data*>(elem->channel_data); GPR_ASSERT(args.context != nullptr); if (args.context[GRPC_CONTEXT_SECURITY].value == nullptr) { @@ -87,25 +89,24 @@ struct call_data { // fields will be accessed after calling dtor, and msan correctly complains // that the memory is not initialized. void destroy() { - grpc_credentials_mdelem_array_destroy(&md_array); + md_array.Destroy(); creds.reset(); - grpc_slice_unref_internal(host); - grpc_slice_unref_internal(method); grpc_auth_metadata_context_reset(&auth_md_context); + host.Destroy(); + method.Destroy(); } grpc_call_stack* owning_call; grpc_core::CallCombiner* call_combiner; grpc_core::RefCountedPtr<grpc_call_credentials> creds; - grpc_slice host = grpc_empty_slice(); - grpc_slice method = grpc_empty_slice(); + grpc_core::ManualConstructor<grpc_core::Slice> host; + grpc_core::ManualConstructor<grpc_core::Slice> method; /* pollset{_set} bound to this call; if we need to make external network requests, they should be done under a pollset added to this pollset_set so that work can progress when this call wants work to progress */ grpc_polling_entity* pollent = nullptr; - grpc_credentials_mdelem_array md_array; - grpc_linked_mdelem md_links[MAX_CREDENTIALS_METADATA_COUNT] = {}; + grpc_core::ManualConstructor<grpc_core::CredentialsMetadataArray> md_array; grpc_auth_metadata_context auth_md_context = grpc_auth_metadata_context(); // Zero-initialize the C struct. grpc_closure async_result_closure; @@ -163,17 +164,20 @@ static void on_credentials_metadata(void* arg, grpc_error_handle input_error) { grpc_auth_metadata_context_reset(&calld->auth_md_context); grpc_error_handle error = GRPC_ERROR_REF(input_error); if (error == GRPC_ERROR_NONE) { - GPR_ASSERT(calld->md_array.size <= MAX_CREDENTIALS_METADATA_COUNT); + GPR_ASSERT(calld->md_array->size() <= MAX_CREDENTIALS_METADATA_COUNT); GPR_ASSERT(batch->send_initial_metadata); grpc_metadata_batch* mdb = batch->payload->send_initial_metadata.send_initial_metadata; - for (size_t i = 0; i < calld->md_array.size; ++i) { - add_error(&error, grpc_metadata_batch_add_tail( - mdb, &calld->md_links[i], - GRPC_MDELEM_REF(calld->md_array.md[i]))); + for (const auto& md : *calld->md_array) { + mdb->Append( + md.first.as_string_view(), md.second.Ref(), + [&](y_absl::string_view error_message, const grpc_core::Slice& value) { + add_error(&error, GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( + "on_credentials_metadata: ", error_message, + ": ", md.first.as_string_view(), ": ", + value.as_string_view()))); + }); } - } - if (error == GRPC_ERROR_NONE) { grpc_call_next_op(elem, batch); } else { error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, @@ -228,12 +232,27 @@ static void cancel_get_request_metadata(void* arg, grpc_error_handle error) { grpc_call_element* elem = static_cast<grpc_call_element*>(arg); call_data* calld = static_cast<call_data*>(elem->call_data); if (error != GRPC_ERROR_NONE) { - calld->creds->cancel_get_request_metadata(&calld->md_array, + calld->creds->cancel_get_request_metadata(&*calld->md_array, GRPC_ERROR_REF(error)); } GRPC_CALL_STACK_UNREF(calld->owning_call, "cancel_get_request_metadata"); } +static grpc_security_level convert_security_level_string_to_enum( + const char* security_level) { + if (strcmp(security_level, "TSI_INTEGRITY_ONLY") == 0) { + return GRPC_INTEGRITY_ONLY; + } else if (strcmp(security_level, "TSI_PRIVACY_AND_INTEGRITY") == 0) { + return GRPC_PRIVACY_AND_INTEGRITY; + } + return GRPC_SECURITY_NONE; +} + +bool grpc_check_security_level(grpc_security_level channel_level, + grpc_security_level call_cred_level) { + return static_cast<int>(channel_level) >= static_cast<int>(call_cred_level); +} + static void send_security_metadata(grpc_call_element* elem, grpc_transport_stream_op_batch* batch) { call_data* calld = static_cast<call_data*>(elem->call_data); @@ -289,7 +308,7 @@ static void send_security_metadata(grpc_call_element* elem, grpc_security_level call_cred_security_level = calld->creds->min_security_level(); int is_security_level_ok = grpc_check_security_level( - grpc_tsi_security_level_string_to_enum(prop->value), + convert_security_level_string_to_enum(prop->value), call_cred_security_level); if (!is_security_level_ok) { grpc_transport_stream_op_batch_finish_with_failure( @@ -304,8 +323,9 @@ static void send_security_metadata(grpc_call_element* elem, } grpc_auth_metadata_context_build( - chand->security_connector->url_scheme(), calld->host, calld->method, - chand->auth_context.get(), &calld->auth_md_context); + chand->security_connector->url_scheme(), calld->host->c_slice(), + calld->method->c_slice(), chand->auth_context.get(), + &calld->auth_md_context); GPR_ASSERT(calld->pollent != nullptr); GRPC_CALL_STACK_REF(calld->owning_call, "get_request_metadata"); @@ -313,7 +333,7 @@ static void send_security_metadata(grpc_call_element* elem, batch, grpc_schedule_on_exec_ctx); grpc_error_handle error = GRPC_ERROR_NONE; if (calld->creds->get_request_metadata( - calld->pollent, calld->auth_md_context, &calld->md_array, + calld->pollent, calld->auth_md_context, &*calld->md_array, &calld->async_result_closure, &error)) { // Synchronous return; invoke on_credentials_metadata() directly. on_credentials_metadata(batch, error); @@ -340,11 +360,11 @@ static void on_host_checked(void* arg, grpc_error_handle error) { } else { grpc_transport_stream_op_batch_finish_with_failure( batch, - grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "Invalid host ", grpc_core::StringViewFromSlice(calld->host), - " set in :authority metadata.")), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAUTHENTICATED), + grpc_error_set_int(GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( + "Invalid host ", calld->host->as_string_view(), + " set in :authority metadata.")), + GRPC_ERROR_INT_GRPC_STATUS, + GRPC_STATUS_UNAUTHENTICATED), calld->call_combiner); } GRPC_CALL_STACK_UNREF(calld->owning_call, "check_call_host"); @@ -372,18 +392,18 @@ static void client_auth_start_transport_stream_op_batch( if (batch->send_initial_metadata) { grpc_metadata_batch* metadata = batch->payload->send_initial_metadata.send_initial_metadata; - if (metadata->legacy_index()->named.path != nullptr) { - calld->method = grpc_slice_ref_internal( - GRPC_MDVALUE(metadata->legacy_index()->named.path->md)); + if (metadata->get_pointer(grpc_core::HttpPathMetadata()) != nullptr) { + *calld->method = + metadata->get_pointer(grpc_core::HttpPathMetadata())->Ref(); } - if (metadata->legacy_index()->named.authority != nullptr) { - calld->host = grpc_slice_ref_internal( - GRPC_MDVALUE(metadata->legacy_index()->named.authority->md)); + if (metadata->get_pointer(grpc_core::HttpAuthorityMetadata()) != nullptr) { + *calld->host = + metadata->get_pointer(grpc_core::HttpAuthorityMetadata())->Ref(); batch->handler_private.extra_arg = elem; GRPC_CALL_STACK_REF(calld->owning_call, "check_call_host"); GRPC_CLOSURE_INIT(&calld->async_result_closure, on_host_checked, batch, grpc_schedule_on_exec_ctx); - y_absl::string_view call_host(grpc_core::StringViewFromSlice(calld->host)); + y_absl::string_view call_host = calld->host->as_string_view(); grpc_error_handle error = GRPC_ERROR_NONE; if (chand->security_connector->check_call_host( call_host, chand->auth_context.get(), diff --git a/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc b/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc index feae3f7d13..2f0a375a3c 100644 --- a/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc +++ b/contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc @@ -86,49 +86,55 @@ struct call_data { grpc_error_handle recv_trailing_metadata_error; bool seen_recv_trailing_metadata_ready = false; grpc_metadata_array md; - const grpc_metadata* consumed_md; - size_t num_consumed_md; grpc_closure cancel_closure; gpr_atm state = STATE_INIT; // async_state }; +class ArrayEncoder { + public: + explicit ArrayEncoder(grpc_metadata_array* result) : result_(result) {} + + void Encode(const grpc_core::Slice& key, const grpc_core::Slice& value) { + Append(key.Ref(), value.Ref()); + } + + template <typename Which> + void Encode(Which, const typename Which::ValueType& value) { + Append(grpc_core::Slice( + grpc_core::StaticSlice::FromStaticString(Which::key())), + grpc_core::Slice(Which::Encode(value))); + } + + void Encode(grpc_core::HttpMethodMetadata, + const typename grpc_core::HttpMethodMetadata::ValueType&) {} + + private: + void Append(grpc_core::Slice key, grpc_core::Slice value) { + if (result_->count == result_->capacity) { + result_->capacity = + std::max(result_->capacity + 8, result_->capacity * 2); + result_->metadata = static_cast<grpc_metadata*>(gpr_realloc( + result_->metadata, result_->capacity * sizeof(grpc_metadata))); + } + auto* usr_md = &result_->metadata[result_->count++]; + usr_md->key = key.TakeCSlice(); + usr_md->value = value.TakeCSlice(); + } + + grpc_metadata_array* result_; +}; + } // namespace static grpc_metadata_array metadata_batch_to_md_array( const grpc_metadata_batch* batch) { grpc_metadata_array result; grpc_metadata_array_init(&result); - batch->ForEach([&](grpc_mdelem md) { - grpc_metadata* usr_md = nullptr; - grpc_slice key = GRPC_MDKEY(md); - grpc_slice value = GRPC_MDVALUE(md); - if (result.count == result.capacity) { - result.capacity = std::max(result.capacity + 8, result.capacity * 2); - result.metadata = static_cast<grpc_metadata*>(gpr_realloc( - result.metadata, result.capacity * sizeof(grpc_metadata))); - } - usr_md = &result.metadata[result.count++]; - usr_md->key = grpc_slice_ref_internal(key); - usr_md->value = grpc_slice_ref_internal(value); - }); + ArrayEncoder encoder(&result); + batch->Encode(&encoder); return result; } -static grpc_filtered_mdelem remove_consumed_md(void* user_data, - grpc_mdelem md) { - grpc_call_element* elem = static_cast<grpc_call_element*>(user_data); - call_data* calld = static_cast<call_data*>(elem->call_data); - size_t i; - for (i = 0; i < calld->num_consumed_md; i++) { - const grpc_metadata* consumed_md = &calld->consumed_md[i]; - if (grpc_slice_eq(GRPC_MDKEY(md), consumed_md->key) && - grpc_slice_eq(GRPC_MDVALUE(md), consumed_md->value)) { - return GRPC_FILTERED_REMOVE(); - } - } - return GRPC_FILTERED_MDELEM(md); -} - static void on_md_processing_done_inner(grpc_call_element* elem, const grpc_metadata* consumed_md, size_t num_consumed_md, @@ -144,11 +150,10 @@ static void on_md_processing_done_inner(grpc_call_element* elem, "Ignoring..."); } if (error == GRPC_ERROR_NONE) { - calld->consumed_md = consumed_md; - calld->num_consumed_md = num_consumed_md; - error = grpc_metadata_batch_filter( - batch->payload->recv_initial_metadata.recv_initial_metadata, - remove_consumed_md, elem, "Response metadata filtering error"); + for (size_t i = 0; i < num_consumed_md; i++) { + batch->payload->recv_initial_metadata.recv_initial_metadata->Remove( + grpc_core::StringViewFromSlice(consumed_md[i].key)); + } } calld->recv_initial_metadata_error = GRPC_ERROR_REF(error); grpc_closure* closure = calld->original_recv_initial_metadata_ready; diff --git a/contrib/libs/grpc/src/core/ext/service_config/service_config.cc b/contrib/libs/grpc/src/core/lib/service_config/service_config.cc index 4489221f8f..5c26d07e1f 100644 --- a/contrib/libs/grpc/src/core/ext/service_config/service_config.cc +++ b/contrib/libs/grpc/src/core/lib/service_config/service_config.cc @@ -16,7 +16,7 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/service_config/service_config.h" +#include "src/core/lib/service_config/service_config.h" #include <util/generic/string.h> @@ -24,8 +24,8 @@ #include <grpc/support/log.h> -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/json/json.h" +#include "src/core/lib/service_config/service_config_parser.h" #include "src/core/lib/slice/slice_internal.h" namespace grpc_core { diff --git a/contrib/libs/grpc/src/core/ext/service_config/service_config.h b/contrib/libs/grpc/src/core/lib/service_config/service_config.h index 27abc72e99..97e7fa3efa 100644 --- a/contrib/libs/grpc/src/core/ext/service_config/service_config.h +++ b/contrib/libs/grpc/src/core/lib/service_config/service_config.h @@ -14,8 +14,8 @@ // limitations under the License. // -#ifndef GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_H -#define GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_H +#ifndef GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_H +#define GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_H #include <grpc/support/port_platform.h> @@ -26,11 +26,11 @@ #include <grpc/impl/codegen/grpc_types.h> #include <grpc/support/string_util.h> -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/error.h" #include "src/core/lib/json/json.h" +#include "src/core/lib/service_config/service_config_parser.h" #include "src/core/lib/slice/slice_internal.h" // The main purpose of the code here is to parse the service config in @@ -124,4 +124,4 @@ class ServiceConfig : public RefCounted<ServiceConfig> { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_H */ +#endif /* GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_H */ diff --git a/contrib/libs/grpc/src/core/ext/service_config/service_config_call_data.h b/contrib/libs/grpc/src/core/lib/service_config/service_config_call_data.h index 8ccaeab621..52b141792e 100644 --- a/contrib/libs/grpc/src/core/ext/service_config/service_config_call_data.h +++ b/contrib/libs/grpc/src/core/lib/service_config/service_config_call_data.h @@ -14,8 +14,8 @@ // limitations under the License. // -#ifndef GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H -#define GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H +#ifndef GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H +#define GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H #include <grpc/support/port_platform.h> @@ -23,10 +23,10 @@ #include "y_absl/strings/string_view.h" -#include "src/core/ext/service_config/service_config.h" -#include "src/core/ext/service_config/service_config_parser.h" #include "src/core/lib/channel/context.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" +#include "src/core/lib/service_config/service_config.h" +#include "src/core/lib/service_config/service_config_parser.h" namespace grpc_core { @@ -69,4 +69,4 @@ class ServiceConfigCallData { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H */ +#endif /* GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_CALL_DATA_H */ diff --git a/contrib/libs/grpc/src/core/ext/service_config/service_config_parser.cc b/contrib/libs/grpc/src/core/lib/service_config/service_config_parser.cc index 04cc7dcbe1..f6f50217c6 100644 --- a/contrib/libs/grpc/src/core/ext/service_config/service_config_parser.cc +++ b/contrib/libs/grpc/src/core/lib/service_config/service_config_parser.cc @@ -16,7 +16,7 @@ #include <grpc/support/port_platform.h> -#include "src/core/ext/service_config/service_config_parser.h" +#include "src/core/lib/service_config/service_config_parser.h" #include <grpc/support/log.h> diff --git a/contrib/libs/grpc/src/core/ext/service_config/service_config_parser.h b/contrib/libs/grpc/src/core/lib/service_config/service_config_parser.h index aa9c31967c..2d93b4e86c 100644 --- a/contrib/libs/grpc/src/core/ext/service_config/service_config_parser.h +++ b/contrib/libs/grpc/src/core/lib/service_config/service_config_parser.h @@ -14,8 +14,8 @@ // limitations under the License. // -#ifndef GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H -#define GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H +#ifndef GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H +#define GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H #include <grpc/support/port_platform.h> @@ -94,4 +94,4 @@ class ServiceConfigParser { } // namespace grpc_core -#endif /* GRPC_CORE_EXT_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H */ +#endif /* GRPC_CORE_LIB_SERVICE_CONFIG_SERVICE_CONFIG_PARSER_H */ diff --git a/contrib/libs/grpc/src/core/lib/slice/slice.cc b/contrib/libs/grpc/src/core/lib/slice/slice.cc index f22a41af83..a5fcf85d4b 100644 --- a/contrib/libs/grpc/src/core/lib/slice/slice.cc +++ b/contrib/libs/grpc/src/core/lib/slice/slice.cc @@ -215,7 +215,9 @@ grpc_slice grpc_slice_from_copied_buffer(const char* source, size_t length) { slice = grpc_core::UnmanagedMemorySlice( length, grpc_core::UnmanagedMemorySlice::ForceHeapAllocation()); } - memcpy(GRPC_SLICE_START_PTR(slice), source, length); + if (length > 0) { + memcpy(GRPC_SLICE_START_PTR(slice), source, length); + } return slice; } diff --git a/contrib/libs/grpc/src/core/lib/slice/slice.h b/contrib/libs/grpc/src/core/lib/slice/slice.h index 83bb725440..7d35ea5119 100644 --- a/contrib/libs/grpc/src/core/lib/slice/slice.h +++ b/contrib/libs/grpc/src/core/lib/slice/slice.h @@ -17,10 +17,13 @@ #include <grpc/support/port_platform.h> +#include <cstdint> + #include "y_absl/strings/string_view.h" #include <grpc/slice.h> +#include "src/core/lib/gpr/string.h" #include "src/core/lib/slice/slice_internal.h" // Herein lies grpc_core::Slice and its team of thin wrappers around grpc_slice. @@ -110,6 +113,8 @@ class BaseSlice { uint8_t* mutable_data() { return GRPC_SLICE_START_PTR(slice_); } + grpc_slice* c_slice_ptr() { return &slice_; } + private: grpc_slice slice_; }; @@ -159,6 +164,9 @@ struct CopyConstructors { static Out FromCopiedString(const char* s) { return Out(grpc_slice_from_copied_string(s)); } + static Out FromCopiedString(y_absl::string_view s) { + return FromCopiedBuffer(s.data(), s.size()); + } static Out FromCopiedString(TString s) { return Out(grpc_slice_from_cpp_string(std::move(s))); } @@ -171,30 +179,39 @@ struct CopyConstructors { return FromCopiedBuffer(reinterpret_cast<const char*>(buffer.data()), buffer.size()); } + + static Out FromInt64(int64_t i) { + char buffer[GPR_LTOA_MIN_BUFSIZE]; + gpr_ltoa(i, buffer); + return FromCopiedString(buffer); + } +}; + +template <typename Out> +struct StaticConstructors { + static Out FromStaticString(const char* s) { + return Out(grpc_slice_from_static_string(s)); + } + + static Out FromStaticString(y_absl::string_view s) { + return Out(ExternallyManagedSlice(s.data(), s.size())); + } }; } // namespace slice_detail -class StaticSlice : public slice_detail::BaseSlice { +class StaticSlice : public slice_detail::BaseSlice, + public slice_detail::StaticConstructors<StaticSlice> { public: StaticSlice() = default; explicit StaticSlice(const grpc_slice& slice) : slice_detail::BaseSlice(slice) { - GPR_DEBUG_ASSERT( - slice.refcount->GetType() == grpc_slice_refcount::Type::STATIC || - slice.refcount->GetType() == grpc_slice_refcount::Type::NOP); + GPR_DEBUG_ASSERT(slice.refcount->GetType() == + grpc_slice_refcount::Type::NOP); } explicit StaticSlice(const StaticMetadataSlice& slice) : slice_detail::BaseSlice(slice) {} - static StaticSlice FromStaticString(const char* s) { - return StaticSlice(grpc_slice_from_static_string(s)); - } - - static StaticSlice FromStaticString(y_absl::string_view s) { - return StaticSlice(ExternallyManagedSlice(s.data(), s.size())); - } - StaticSlice(const StaticSlice& other) : slice_detail::BaseSlice(other.c_slice()) {} StaticSlice& operator=(const StaticSlice& other) { @@ -242,13 +259,15 @@ class MutableSlice : public slice_detail::BaseSlice, // Iterator access to the underlying bytes uint8_t* begin() { return mutable_data(); } uint8_t* end() { return mutable_data() + size(); } + uint8_t* data() { return mutable_data(); } // Array access uint8_t& operator[](size_t i) { return mutable_data()[i]; } }; class Slice : public slice_detail::BaseSlice, - public slice_detail::CopyConstructors<Slice> { + public slice_detail::CopyConstructors<Slice>, + public slice_detail::StaticConstructors<Slice> { public: Slice() = default; ~Slice() { grpc_slice_unref_internal(c_slice()); } @@ -321,6 +340,17 @@ class Slice : public slice_detail::BaseSlice, return Slice(grpc_slice_sub_no_ref(TakeCSlice(), pos, pos + n)); } + // Return a sub slice of this one. Adds a reference to the underlying slice. + Slice RefSubSlice(size_t pos, size_t n) const { + return Slice(grpc_slice_sub(c_slice(), pos, pos + n)); + } + + // Split this slice, returning a new slice containing (split:end] and + // leaving this slice with [begin:split). + Slice Split(size_t split) { + return Slice(grpc_slice_split_tail(c_slice_ptr(), split)); + } + Slice Ref() const { return Slice(grpc_slice_ref_internal(c_slice())); } Slice Copy() const { return Slice(grpc_slice_copy(c_slice())); } diff --git a/contrib/libs/grpc/src/core/lib/slice/slice_intern.cc b/contrib/libs/grpc/src/core/lib/slice/slice_intern.cc index 0bed91a9e2..2ab13d1458 100644 --- a/contrib/libs/grpc/src/core/lib/slice/slice_intern.cc +++ b/contrib/libs/grpc/src/core/lib/slice/slice_intern.cc @@ -31,7 +31,6 @@ #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_utils.h" -#include "src/core/lib/transport/static_metadata.h" #define LOG2_SHARD_COUNT 5 #define SHARD_COUNT (1 << LOG2_SHARD_COUNT) @@ -51,15 +50,6 @@ typedef struct slice_shard { static slice_shard* g_shards; -struct static_metadata_hash_ent { - uint32_t hash; - uint32_t idx; -}; -static static_metadata_hash_ent - static_metadata_hash[4 * GRPC_STATIC_MDSTR_COUNT]; -static uint32_t max_static_metadata_hash_probe; -uint32_t grpc_static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT]; - namespace grpc_core { /* hash seed: decided at initialization time */ @@ -116,37 +106,8 @@ uint32_t grpc_slice_default_hash_impl(grpc_slice s) { grpc_core::g_hash_seed); } -uint32_t grpc_static_slice_hash(grpc_slice s) { - return grpc_static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX(s)]; -} - -int grpc_static_slice_eq(grpc_slice a, grpc_slice b) { - return GRPC_STATIC_METADATA_INDEX(a) == GRPC_STATIC_METADATA_INDEX(b); -} - uint32_t grpc_slice_hash(grpc_slice s) { return grpc_slice_hash_internal(s); } -grpc_slice grpc_slice_maybe_static_intern(grpc_slice slice, - bool* returned_slice_is_different) { - if (GRPC_IS_STATIC_METADATA_STRING(slice)) { - return slice; - } - - uint32_t hash = grpc_slice_hash_internal(slice); - for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) { - static_metadata_hash_ent ent = - static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)]; - if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT && - grpc_slice_eq_static_interned( - slice, grpc_core::g_static_metadata_slice_table[ent.idx])) { - *returned_slice_is_different = true; - return grpc_core::g_static_metadata_slice_table[ent.idx]; - } - } - - return slice; -} - grpc_slice grpc_slice_intern(grpc_slice slice) { /* TODO(arjunroy): At present, this is capable of returning either a static or an interned slice. This yields weirdness like the constructor for @@ -155,25 +116,6 @@ grpc_slice grpc_slice_intern(grpc_slice slice) { return grpc_core::ManagedMemorySlice(&slice); } -// Attempt to see if the provided slice or string matches a static slice. -// SliceArgs is either a const grpc_slice& or const pair<const char*, size_t>&. -// In either case, hash is the pre-computed hash value. -// -// Returns: a matching static slice, or null. -template <typename SliceArgs> -static const grpc_core::StaticMetadataSlice* MatchStaticSlice( - uint32_t hash, const SliceArgs& args) { - for (uint32_t i = 0; i <= max_static_metadata_hash_probe; i++) { - static_metadata_hash_ent ent = - static_metadata_hash[(hash + i) % GPR_ARRAY_SIZE(static_metadata_hash)]; - if (ent.hash == hash && ent.idx < GRPC_STATIC_MDSTR_COUNT && - grpc_core::g_static_metadata_slice_table[ent.idx] == args) { - return &grpc_core::g_static_metadata_slice_table[ent.idx]; - } - } - return nullptr; -} - // Helper methods to enable us to select appropriately overloaded slice methods // whether we're dealing with a slice, or a buffer with length, when interning // strings. Helpers for FindOrCreateInternedSlice(). @@ -271,30 +213,15 @@ grpc_core::ManagedMemorySlice::ManagedMemorySlice(const char* string) grpc_core::ManagedMemorySlice::ManagedMemorySlice(const char* buf, size_t len) { GPR_TIMER_SCOPE("grpc_slice_intern", 0); const uint32_t hash = gpr_murmur_hash3(buf, len, g_hash_seed); - const StaticMetadataSlice* static_slice = - MatchStaticSlice(hash, std::pair<const char*, size_t>(buf, len)); - if (static_slice) { - *this = *static_slice; - } else { - *this = grpc_core::InternedSlice(FindOrCreateInternedSlice( - hash, std::pair<const char*, size_t>(buf, len))); - } + *this = grpc_core::InternedSlice(FindOrCreateInternedSlice( + hash, std::pair<const char*, size_t>(buf, len))); } grpc_core::ManagedMemorySlice::ManagedMemorySlice(const grpc_slice* slice_ptr) { GPR_TIMER_SCOPE("grpc_slice_intern", 0); const grpc_slice& slice = *slice_ptr; - if (GRPC_IS_STATIC_METADATA_STRING(slice)) { - *this = static_cast<const grpc_core::StaticMetadataSlice&>(slice); - return; - } const uint32_t hash = grpc_slice_hash_internal(slice); - const StaticMetadataSlice* static_slice = MatchStaticSlice(hash, slice); - if (static_slice) { - *this = *static_slice; - } else { - *this = grpc_core::InternedSlice(FindOrCreateInternedSlice(hash, slice)); - } + *this = grpc_core::InternedSlice(FindOrCreateInternedSlice(hash, slice)); } void grpc_test_only_set_slice_hash_seed(uint32_t seed) { @@ -315,31 +242,6 @@ void grpc_slice_intern_init(void) { shard->strs = static_cast<InternedSliceRefcount**>( gpr_zalloc(sizeof(*shard->strs) * shard->capacity)); } - for (size_t i = 0; i < GPR_ARRAY_SIZE(static_metadata_hash); i++) { - static_metadata_hash[i].hash = 0; - static_metadata_hash[i].idx = GRPC_STATIC_MDSTR_COUNT; - } - max_static_metadata_hash_probe = 0; - for (size_t i = 0; i < GRPC_STATIC_MDSTR_COUNT; i++) { - grpc_static_metadata_hash_values[i] = grpc_slice_default_hash_internal( - grpc_core::g_static_metadata_slice_table[i]); - for (size_t j = 0; j < GPR_ARRAY_SIZE(static_metadata_hash); j++) { - size_t slot = (grpc_static_metadata_hash_values[i] + j) % - GPR_ARRAY_SIZE(static_metadata_hash); - if (static_metadata_hash[slot].idx == GRPC_STATIC_MDSTR_COUNT) { - static_metadata_hash[slot].hash = grpc_static_metadata_hash_values[i]; - static_metadata_hash[slot].idx = static_cast<uint32_t>(i); - if (j > max_static_metadata_hash_probe) { - max_static_metadata_hash_probe = static_cast<uint32_t>(j); - } - break; - } - } - } - // Handle KV hash for all static mdelems. - for (size_t i = 0; i < GRPC_STATIC_MDELEM_COUNT; ++i) { - grpc_core::g_static_mdelem_table[i].HashInit(); - } } void grpc_slice_intern_shutdown(void) { diff --git a/contrib/libs/grpc/src/core/lib/slice/slice_internal.h b/contrib/libs/grpc/src/core/lib/slice/slice_internal.h index d603d04efe..f913fde87d 100644 --- a/contrib/libs/grpc/src/core/lib/slice/slice_internal.h +++ b/contrib/libs/grpc/src/core/lib/slice/slice_internal.h @@ -56,8 +56,7 @@ void grpc_slice_buffer_sub_first(grpc_slice_buffer* sb, size_t begin, bool grpc_slice_is_interned(const grpc_slice& slice); inline bool grpc_slice_is_interned(const grpc_slice& slice) { return (slice.refcount && - (slice.refcount->GetType() == grpc_slice_refcount::Type::INTERNED || - slice.refcount->GetType() == grpc_slice_refcount::Type::STATIC)); + (slice.refcount->GetType() == grpc_slice_refcount::Type::INTERNED)); } inline bool grpc_slice_static_interned_equal(const grpc_slice& a, diff --git a/contrib/libs/grpc/src/core/lib/slice/slice_refcount.h b/contrib/libs/grpc/src/core/lib/slice/slice_refcount.h index 28f38f6638..a2f5f918ca 100644 --- a/contrib/libs/grpc/src/core/lib/slice/slice_refcount.h +++ b/contrib/libs/grpc/src/core/lib/slice/slice_refcount.h @@ -17,17 +17,16 @@ #include <grpc/support/port_platform.h> +#include <string.h> + #include <grpc/support/alloc.h> +#include "src/core/lib/gpr/murmur_hash.h" #include "src/core/lib/slice/slice_refcount_base.h" -#include "src/core/lib/slice/static_slice.h" - -// Interned slices have specific fast-path operations for hashing. To inline -// these operations, we need to forward declare them here. -extern uint32_t grpc_static_metadata_hash_values[GRPC_STATIC_MDSTR_COUNT]; namespace grpc_core { +extern uint32_t g_hash_seed; extern grpc_slice_refcount kNoopRefcount; // TODO(ctiller): when this is removed, remove the std::atomic* in @@ -73,11 +72,6 @@ inline int grpc_slice_refcount::Eq(const grpc_slice& a, const grpc_slice& b) { GPR_DEBUG_ASSERT(a.refcount != nullptr); GPR_DEBUG_ASSERT(a.refcount == this); switch (ref_type_) { - case Type::STATIC: - GPR_DEBUG_ASSERT( - (GRPC_STATIC_METADATA_INDEX(a) == GRPC_STATIC_METADATA_INDEX(b)) == - (a.refcount == b.refcount)); - Y_ABSL_FALLTHROUGH_INTENDED; case Type::INTERNED: return a.refcount == b.refcount; case Type::NOP: @@ -94,9 +88,6 @@ inline uint32_t grpc_slice_refcount::Hash(const grpc_slice& slice) { GPR_DEBUG_ASSERT(slice.refcount != nullptr); GPR_DEBUG_ASSERT(slice.refcount == this); switch (ref_type_) { - case Type::STATIC: - return ::grpc_static_metadata_hash_values[GRPC_STATIC_METADATA_INDEX( - slice)]; case Type::INTERNED: return reinterpret_cast<grpc_core::InternedSliceRefcount*>(slice.refcount) ->hash; diff --git a/contrib/libs/grpc/src/core/lib/slice/slice_refcount_base.h b/contrib/libs/grpc/src/core/lib/slice/slice_refcount_base.h index 9c1e34056b..5d81fcd8fc 100644 --- a/contrib/libs/grpc/src/core/lib/slice/slice_refcount_base.h +++ b/contrib/libs/grpc/src/core/lib/slice/slice_refcount_base.h @@ -85,7 +85,6 @@ struct grpc_slice_refcount { public: enum class Type { - STATIC, // Refcount for a static metadata slice. INTERNED, // Refcount for an interned slice. NOP, // No-Op REGULAR // Refcount for non-static-metadata, non-interned slices. @@ -163,19 +162,4 @@ struct grpc_slice_refcount { void* destroy_fn_arg_ = nullptr; }; -namespace grpc_core { - -struct StaticSliceRefcount { - static grpc_slice_refcount kStaticSubRefcount; - - explicit StaticSliceRefcount(uint32_t index) - : base(&kStaticSubRefcount, grpc_slice_refcount::Type::STATIC), - index(index) {} - - grpc_slice_refcount base; - const uint32_t index; -}; - -} // namespace grpc_core - #endif // GRPC_CORE_LIB_SLICE_SLICE_REFCOUNT_BASE_H diff --git a/contrib/libs/grpc/src/core/lib/slice/static_slice.cc b/contrib/libs/grpc/src/core/lib/slice/static_slice.cc deleted file mode 100644 index 9f59753608..0000000000 --- a/contrib/libs/grpc/src/core/lib/slice/static_slice.cc +++ /dev/null @@ -1,377 +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. - */ - -/* - * WARNING: Auto-generated code. - * - * To make changes to this file, change - * tools/codegen/core/gen_static_metadata.py, and then re-run it. - * - * See metadata.h for an explanation of the interface here, and metadata.cc for - * an explanation of what's going on. - */ - -#include <grpc/support/port_platform.h> - -#include "src/core/lib/slice/static_slice.h" - -namespace grpc_core { -const uint8_t g_static_metadata_bytes[] = { - 58, 112, 97, 116, 104, 58, 109, 101, 116, 104, 111, 100, 58, 115, 116, - 97, 116, 117, 115, 58, 97, 117, 116, 104, 111, 114, 105, 116, 121, 58, - 115, 99, 104, 101, 109, 101, 103, 114, 112, 99, 45, 115, 116, 97, 116, - 117, 115, 103, 114, 112, 99, 45, 101, 110, 99, 111, 100, 105, 110, 103, - 103, 114, 112, 99, 45, 97, 99, 99, 101, 112, 116, 45, 101, 110, 99, - 111, 100, 105, 110, 103, 99, 111, 110, 116, 101, 110, 116, 45, 116, 121, - 112, 101, 99, 111, 110, 116, 101, 110, 116, 45, 101, 110, 99, 111, 100, - 105, 110, 103, 97, 99, 99, 101, 112, 116, 45, 101, 110, 99, 111, 100, - 105, 110, 103, 103, 114, 112, 99, 45, 105, 110, 116, 101, 114, 110, 97, - 108, 45, 101, 110, 99, 111, 100, 105, 110, 103, 45, 114, 101, 113, 117, - 101, 115, 116, 103, 114, 112, 99, 45, 112, 114, 101, 118, 105, 111, 117, - 115, 45, 114, 112, 99, 45, 97, 116, 116, 101, 109, 112, 116, 115, 103, - 114, 112, 99, 45, 114, 101, 116, 114, 121, 45, 112, 117, 115, 104, 98, - 97, 99, 107, 45, 109, 115, 103, 114, 112, 99, 45, 116, 105, 109, 101, - 111, 117, 116, 49, 50, 51, 52, 47, 103, 114, 112, 99, 46, 108, 98, - 46, 118, 49, 46, 76, 111, 97, 100, 66, 97, 108, 97, 110, 99, 101, - 114, 47, 66, 97, 108, 97, 110, 99, 101, 76, 111, 97, 100, 47, 101, - 110, 118, 111, 121, 46, 115, 101, 114, 118, 105, 99, 101, 46, 108, 111, - 97, 100, 95, 115, 116, 97, 116, 115, 46, 118, 50, 46, 76, 111, 97, - 100, 82, 101, 112, 111, 114, 116, 105, 110, 103, 83, 101, 114, 118, 105, - 99, 101, 47, 83, 116, 114, 101, 97, 109, 76, 111, 97, 100, 83, 116, - 97, 116, 115, 47, 101, 110, 118, 111, 121, 46, 115, 101, 114, 118, 105, - 99, 101, 46, 108, 111, 97, 100, 95, 115, 116, 97, 116, 115, 46, 118, - 51, 46, 76, 111, 97, 100, 82, 101, 112, 111, 114, 116, 105, 110, 103, - 83, 101, 114, 118, 105, 99, 101, 47, 83, 116, 114, 101, 97, 109, 76, - 111, 97, 100, 83, 116, 97, 116, 115, 47, 103, 114, 112, 99, 46, 104, - 101, 97, 108, 116, 104, 46, 118, 49, 46, 72, 101, 97, 108, 116, 104, - 47, 87, 97, 116, 99, 104, 47, 101, 110, 118, 111, 121, 46, 115, 101, - 114, 118, 105, 99, 101, 46, 100, 105, 115, 99, 111, 118, 101, 114, 121, - 46, 118, 50, 46, 65, 103, 103, 114, 101, 103, 97, 116, 101, 100, 68, - 105, 115, 99, 111, 118, 101, 114, 121, 83, 101, 114, 118, 105, 99, 101, - 47, 83, 116, 114, 101, 97, 109, 65, 103, 103, 114, 101, 103, 97, 116, - 101, 100, 82, 101, 115, 111, 117, 114, 99, 101, 115, 47, 101, 110, 118, - 111, 121, 46, 115, 101, 114, 118, 105, 99, 101, 46, 100, 105, 115, 99, - 111, 118, 101, 114, 121, 46, 118, 51, 46, 65, 103, 103, 114, 101, 103, - 97, 116, 101, 100, 68, 105, 115, 99, 111, 118, 101, 114, 121, 83, 101, - 114, 118, 105, 99, 101, 47, 83, 116, 114, 101, 97, 109, 65, 103, 103, - 114, 101, 103, 97, 116, 101, 100, 82, 101, 115, 111, 117, 114, 99, 101, - 115, 100, 101, 102, 108, 97, 116, 101, 103, 122, 105, 112, 115, 116, 114, - 101, 97, 109, 47, 103, 122, 105, 112, 116, 101, 116, 114, 97, 105, 108, - 101, 114, 115, 71, 69, 84, 80, 79, 83, 84, 47, 47, 105, 110, 100, - 101, 120, 46, 104, 116, 109, 108, 104, 116, 116, 112, 104, 116, 116, 112, - 115, 50, 48, 48, 50, 48, 52, 50, 48, 54, 51, 48, 52, 52, 48, - 48, 52, 48, 52, 53, 48, 48, 97, 99, 99, 101, 112, 116, 45, 99, - 104, 97, 114, 115, 101, 116, 103, 122, 105, 112, 44, 32, 100, 101, 102, - 108, 97, 116, 101, 97, 99, 99, 101, 112, 116, 45, 108, 97, 110, 103, - 117, 97, 103, 101, 97, 99, 99, 101, 112, 116, 45, 114, 97, 110, 103, - 101, 115, 97, 99, 99, 101, 112, 116, 97, 99, 99, 101, 115, 115, 45, - 99, 111, 110, 116, 114, 111, 108, 45, 97, 108, 108, 111, 119, 45, 111, - 114, 105, 103, 105, 110, 97, 103, 101, 97, 108, 108, 111, 119, 97, 117, - 116, 104, 111, 114, 105, 122, 97, 116, 105, 111, 110, 99, 97, 99, 104, - 101, 45, 99, 111, 110, 116, 114, 111, 108, 99, 111, 110, 116, 101, 110, - 116, 45, 100, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 99, 111, - 110, 116, 101, 110, 116, 45, 108, 97, 110, 103, 117, 97, 103, 101, 99, - 111, 110, 116, 101, 110, 116, 45, 108, 101, 110, 103, 116, 104, 99, 111, - 110, 116, 101, 110, 116, 45, 108, 111, 99, 97, 116, 105, 111, 110, 99, - 111, 110, 116, 101, 110, 116, 45, 114, 97, 110, 103, 101, 99, 111, 111, - 107, 105, 101, 100, 97, 116, 101, 101, 116, 97, 103, 101, 120, 112, 101, - 99, 116, 101, 120, 112, 105, 114, 101, 115, 102, 114, 111, 109, 104, 111, - 115, 116, 105, 102, 45, 109, 97, 116, 99, 104, 105, 102, 45, 109, 111, - 100, 105, 102, 105, 101, 100, 45, 115, 105, 110, 99, 101, 105, 102, 45, - 110, 111, 110, 101, 45, 109, 97, 116, 99, 104, 105, 102, 45, 114, 97, - 110, 103, 101, 105, 102, 45, 117, 110, 109, 111, 100, 105, 102, 105, 101, - 100, 45, 115, 105, 110, 99, 101, 108, 97, 115, 116, 45, 109, 111, 100, - 105, 102, 105, 101, 100, 108, 105, 110, 107, 108, 111, 99, 97, 116, 105, - 111, 110, 109, 97, 120, 45, 102, 111, 114, 119, 97, 114, 100, 115, 112, - 114, 111, 120, 121, 45, 97, 117, 116, 104, 101, 110, 116, 105, 99, 97, - 116, 101, 112, 114, 111, 120, 121, 45, 97, 117, 116, 104, 111, 114, 105, - 122, 97, 116, 105, 111, 110, 114, 97, 110, 103, 101, 114, 101, 102, 101, - 114, 101, 114, 114, 101, 102, 114, 101, 115, 104, 114, 101, 116, 114, 121, - 45, 97, 102, 116, 101, 114, 115, 101, 114, 118, 101, 114, 115, 101, 116, - 45, 99, 111, 111, 107, 105, 101, 115, 116, 114, 105, 99, 116, 45, 116, - 114, 97, 110, 115, 112, 111, 114, 116, 45, 115, 101, 99, 117, 114, 105, - 116, 121, 116, 114, 97, 110, 115, 102, 101, 114, 45, 101, 110, 99, 111, - 100, 105, 110, 103, 117, 115, 101, 114, 45, 97, 103, 101, 110, 116, 118, - 97, 114, 121, 118, 105, 97, 119, 119, 119, 45, 97, 117, 116, 104, 101, - 110, 116, 105, 99, 97, 116, 101, 48, 105, 100, 101, 110, 116, 105, 116, - 121, 97, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 47, 103, 114, - 112, 99, 103, 114, 112, 99, 80, 85, 84, 108, 98, 45, 99, 111, 115, - 116, 45, 98, 105, 110, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, - 101, 102, 108, 97, 116, 101, 105, 100, 101, 110, 116, 105, 116, 121, 44, - 103, 122, 105, 112, 100, 101, 102, 108, 97, 116, 101, 44, 103, 122, 105, - 112, 105, 100, 101, 110, 116, 105, 116, 121, 44, 100, 101, 102, 108, 97, - 116, 101, 44, 103, 122, 105, 112}; - -grpc_slice_refcount StaticSliceRefcount::kStaticSubRefcount; - -StaticSliceRefcount g_static_metadata_slice_refcounts[GRPC_STATIC_MDSTR_COUNT] = - { - - StaticSliceRefcount(0), StaticSliceRefcount(1), - StaticSliceRefcount(2), StaticSliceRefcount(3), - StaticSliceRefcount(4), StaticSliceRefcount(5), - StaticSliceRefcount(6), StaticSliceRefcount(7), - StaticSliceRefcount(8), StaticSliceRefcount(9), - StaticSliceRefcount(10), StaticSliceRefcount(11), - StaticSliceRefcount(12), StaticSliceRefcount(13), - StaticSliceRefcount(14), StaticSliceRefcount(15), - StaticSliceRefcount(16), StaticSliceRefcount(17), - StaticSliceRefcount(18), StaticSliceRefcount(19), - StaticSliceRefcount(20), StaticSliceRefcount(21), - StaticSliceRefcount(22), StaticSliceRefcount(23), - StaticSliceRefcount(24), StaticSliceRefcount(25), - StaticSliceRefcount(26), StaticSliceRefcount(27), - StaticSliceRefcount(28), StaticSliceRefcount(29), - StaticSliceRefcount(30), StaticSliceRefcount(31), - StaticSliceRefcount(32), StaticSliceRefcount(33), - StaticSliceRefcount(34), StaticSliceRefcount(35), - StaticSliceRefcount(36), StaticSliceRefcount(37), - StaticSliceRefcount(38), StaticSliceRefcount(39), - StaticSliceRefcount(40), StaticSliceRefcount(41), - StaticSliceRefcount(42), StaticSliceRefcount(43), - StaticSliceRefcount(44), StaticSliceRefcount(45), - StaticSliceRefcount(46), StaticSliceRefcount(47), - StaticSliceRefcount(48), StaticSliceRefcount(49), - StaticSliceRefcount(50), StaticSliceRefcount(51), - StaticSliceRefcount(52), StaticSliceRefcount(53), - StaticSliceRefcount(54), StaticSliceRefcount(55), - StaticSliceRefcount(56), StaticSliceRefcount(57), - StaticSliceRefcount(58), StaticSliceRefcount(59), - StaticSliceRefcount(60), StaticSliceRefcount(61), - StaticSliceRefcount(62), StaticSliceRefcount(63), - StaticSliceRefcount(64), StaticSliceRefcount(65), - StaticSliceRefcount(66), StaticSliceRefcount(67), - StaticSliceRefcount(68), StaticSliceRefcount(69), - StaticSliceRefcount(70), StaticSliceRefcount(71), - StaticSliceRefcount(72), StaticSliceRefcount(73), - StaticSliceRefcount(74), StaticSliceRefcount(75), - StaticSliceRefcount(76), StaticSliceRefcount(77), - StaticSliceRefcount(78), StaticSliceRefcount(79), - StaticSliceRefcount(80), StaticSliceRefcount(81), - StaticSliceRefcount(82), StaticSliceRefcount(83), - StaticSliceRefcount(84), StaticSliceRefcount(85), - StaticSliceRefcount(86), StaticSliceRefcount(87), - StaticSliceRefcount(88), StaticSliceRefcount(89), - StaticSliceRefcount(90), StaticSliceRefcount(91), - StaticSliceRefcount(92), StaticSliceRefcount(93), - StaticSliceRefcount(94), StaticSliceRefcount(95), - StaticSliceRefcount(96), StaticSliceRefcount(97), - StaticSliceRefcount(98), -}; - -const StaticMetadataSlice - g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT] = { - - StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 5, - g_static_metadata_bytes + 0), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, - g_static_metadata_bytes + 5), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 10, - g_static_metadata_bytes + 19), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7, - g_static_metadata_bytes + 29), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 11, - g_static_metadata_bytes + 36), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 13, - g_static_metadata_bytes + 47), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 12, - g_static_metadata_bytes + 80), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 16, - g_static_metadata_bytes + 92), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 15, - g_static_metadata_bytes + 108), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[11].base, 30, - g_static_metadata_bytes + 123), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[12].base, 26, - g_static_metadata_bytes + 153), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[13].base, 22, - g_static_metadata_bytes + 179), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[14].base, 12, - g_static_metadata_bytes + 201), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[15].base, 1, - g_static_metadata_bytes + 213), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[16].base, 1, - g_static_metadata_bytes + 214), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[17].base, 1, - g_static_metadata_bytes + 215), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[18].base, 1, - g_static_metadata_bytes + 216), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[20].base, 36, - g_static_metadata_bytes + 217), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[21].base, 65, - g_static_metadata_bytes + 253), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[22].base, 65, - g_static_metadata_bytes + 318), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[23].base, 28, - g_static_metadata_bytes + 383), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[24].base, 80, - g_static_metadata_bytes + 411), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[25].base, 80, - g_static_metadata_bytes + 491), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[26].base, 7, - g_static_metadata_bytes + 571), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 4, - g_static_metadata_bytes + 578), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[28].base, 11, - g_static_metadata_bytes + 582), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[29].base, 2, - g_static_metadata_bytes + 593), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[30].base, 8, - g_static_metadata_bytes + 595), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[31].base, 3, - g_static_metadata_bytes + 603), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[32].base, 4, - g_static_metadata_bytes + 606), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[33].base, 1, - g_static_metadata_bytes + 610), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[34].base, 11, - g_static_metadata_bytes + 611), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[35].base, 4, - g_static_metadata_bytes + 622), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[36].base, 5, - g_static_metadata_bytes + 626), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[37].base, 3, - g_static_metadata_bytes + 631), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[38].base, 3, - g_static_metadata_bytes + 634), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[39].base, 3, - g_static_metadata_bytes + 637), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[40].base, 3, - g_static_metadata_bytes + 640), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[41].base, 3, - g_static_metadata_bytes + 643), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[42].base, 3, - g_static_metadata_bytes + 646), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[43].base, 3, - g_static_metadata_bytes + 649), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[44].base, 14, - g_static_metadata_bytes + 652), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[45].base, 13, - g_static_metadata_bytes + 666), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[46].base, 15, - g_static_metadata_bytes + 679), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[47].base, 13, - g_static_metadata_bytes + 694), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[48].base, 6, - g_static_metadata_bytes + 707), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[49].base, 27, - g_static_metadata_bytes + 713), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[50].base, 3, - g_static_metadata_bytes + 740), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[51].base, 5, - g_static_metadata_bytes + 743), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[52].base, 13, - g_static_metadata_bytes + 748), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[53].base, 13, - g_static_metadata_bytes + 761), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[54].base, 19, - g_static_metadata_bytes + 774), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[55].base, 16, - g_static_metadata_bytes + 793), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[56].base, 14, - g_static_metadata_bytes + 809), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[57].base, 16, - g_static_metadata_bytes + 823), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[58].base, 13, - g_static_metadata_bytes + 839), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[59].base, 6, - g_static_metadata_bytes + 852), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[60].base, 4, - g_static_metadata_bytes + 858), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[61].base, 4, - g_static_metadata_bytes + 862), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[62].base, 6, - g_static_metadata_bytes + 866), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[63].base, 7, - g_static_metadata_bytes + 872), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[64].base, 4, - g_static_metadata_bytes + 879), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[65].base, 4, - g_static_metadata_bytes + 883), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[66].base, 8, - g_static_metadata_bytes + 887), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[67].base, 17, - g_static_metadata_bytes + 895), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[68].base, 13, - g_static_metadata_bytes + 912), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[69].base, 8, - g_static_metadata_bytes + 925), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[70].base, 19, - g_static_metadata_bytes + 933), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[71].base, 13, - g_static_metadata_bytes + 952), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[72].base, 4, - g_static_metadata_bytes + 965), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[73].base, 8, - g_static_metadata_bytes + 969), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[74].base, 12, - g_static_metadata_bytes + 977), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[75].base, 18, - g_static_metadata_bytes + 989), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[76].base, 19, - g_static_metadata_bytes + 1007), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[77].base, 5, - g_static_metadata_bytes + 1026), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[78].base, 7, - g_static_metadata_bytes + 1031), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[79].base, 7, - g_static_metadata_bytes + 1038), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[80].base, 11, - g_static_metadata_bytes + 1045), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[81].base, 6, - g_static_metadata_bytes + 1056), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 10, - g_static_metadata_bytes + 1062), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[83].base, 25, - g_static_metadata_bytes + 1072), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[84].base, 17, - g_static_metadata_bytes + 1097), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[85].base, 10, - g_static_metadata_bytes + 1114), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[86].base, 4, - g_static_metadata_bytes + 1124), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[87].base, 3, - g_static_metadata_bytes + 1128), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[88].base, 16, - g_static_metadata_bytes + 1131), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[89].base, 1, - g_static_metadata_bytes + 1147), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[90].base, 8, - g_static_metadata_bytes + 1148), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[91].base, 16, - g_static_metadata_bytes + 1156), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[92].base, 4, - g_static_metadata_bytes + 1172), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[93].base, 3, - g_static_metadata_bytes + 1176), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[94].base, 11, - g_static_metadata_bytes + 1179), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[95].base, 16, - g_static_metadata_bytes + 1190), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[96].base, 13, - g_static_metadata_bytes + 1206), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[97].base, 12, - g_static_metadata_bytes + 1219), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[98].base, 21, - g_static_metadata_bytes + 1231), -}; -} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/slice/static_slice.h b/contrib/libs/grpc/src/core/lib/slice/static_slice.h deleted file mode 100644 index 267b7aba96..0000000000 --- a/contrib/libs/grpc/src/core/lib/slice/static_slice.h +++ /dev/null @@ -1,300 +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. - */ - -/* - * WARNING: Auto-generated code. - * - * To make changes to this file, change - * tools/codegen/core/gen_static_metadata.py, and then re-run it. - * - * See metadata.h for an explanation of the interface here, and metadata.cc for - * an explanation of what's going on. - */ - -#ifndef GRPC_CORE_LIB_SLICE_STATIC_SLICE_H -#define GRPC_CORE_LIB_SLICE_STATIC_SLICE_H - -#include <grpc/support/port_platform.h> - -#include <cstdint> -#include <type_traits> - -#include "src/core/lib/slice/slice_refcount_base.h" -#include "src/core/lib/slice/slice_utils.h" - -static_assert( - std::is_trivially_destructible<grpc_core::StaticMetadataSlice>::value, - "StaticMetadataSlice must be trivially destructible."); -#define GRPC_STATIC_MDSTR_COUNT 99 -/* ":path" */ -#define GRPC_MDSTR_PATH (::grpc_core::g_static_metadata_slice_table[0]) -/* ":method" */ -#define GRPC_MDSTR_METHOD (::grpc_core::g_static_metadata_slice_table[1]) -/* ":status" */ -#define GRPC_MDSTR_STATUS (::grpc_core::g_static_metadata_slice_table[2]) -/* ":authority" */ -#define GRPC_MDSTR_AUTHORITY (::grpc_core::g_static_metadata_slice_table[3]) -/* ":scheme" */ -#define GRPC_MDSTR_SCHEME (::grpc_core::g_static_metadata_slice_table[4]) -/* "grpc-status" */ -#define GRPC_MDSTR_GRPC_STATUS (::grpc_core::g_static_metadata_slice_table[5]) -/* "grpc-encoding" */ -#define GRPC_MDSTR_GRPC_ENCODING (::grpc_core::g_static_metadata_slice_table[6]) -/* "grpc-accept-encoding" */ -#define GRPC_MDSTR_GRPC_ACCEPT_ENCODING \ - (::grpc_core::g_static_metadata_slice_table[7]) -/* "content-type" */ -#define GRPC_MDSTR_CONTENT_TYPE (::grpc_core::g_static_metadata_slice_table[8]) -/* "content-encoding" */ -#define GRPC_MDSTR_CONTENT_ENCODING \ - (::grpc_core::g_static_metadata_slice_table[9]) -/* "accept-encoding" */ -#define GRPC_MDSTR_ACCEPT_ENCODING \ - (::grpc_core::g_static_metadata_slice_table[10]) -/* "grpc-internal-encoding-request" */ -#define GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST \ - (::grpc_core::g_static_metadata_slice_table[11]) -/* "grpc-previous-rpc-attempts" */ -#define GRPC_MDSTR_GRPC_PREVIOUS_RPC_ATTEMPTS \ - (::grpc_core::g_static_metadata_slice_table[12]) -/* "grpc-retry-pushback-ms" */ -#define GRPC_MDSTR_GRPC_RETRY_PUSHBACK_MS \ - (::grpc_core::g_static_metadata_slice_table[13]) -/* "grpc-timeout" */ -#define GRPC_MDSTR_GRPC_TIMEOUT (::grpc_core::g_static_metadata_slice_table[14]) -/* "1" */ -#define GRPC_MDSTR_1 (::grpc_core::g_static_metadata_slice_table[15]) -/* "2" */ -#define GRPC_MDSTR_2 (::grpc_core::g_static_metadata_slice_table[16]) -/* "3" */ -#define GRPC_MDSTR_3 (::grpc_core::g_static_metadata_slice_table[17]) -/* "4" */ -#define GRPC_MDSTR_4 (::grpc_core::g_static_metadata_slice_table[18]) -/* "" */ -#define GRPC_MDSTR_EMPTY (::grpc_core::g_static_metadata_slice_table[19]) -/* "/grpc.lb.v1.LoadBalancer/BalanceLoad" */ -#define GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD \ - (::grpc_core::g_static_metadata_slice_table[20]) -/* "/envoy.service.load_stats.v2.LoadReportingService/StreamLoadStats" */ -#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V2_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \ - (::grpc_core::g_static_metadata_slice_table[21]) -/* "/envoy.service.load_stats.v3.LoadReportingService/StreamLoadStats" */ -#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_LOAD_STATS_DOT_V3_DOT_LOADREPORTINGSERVICE_SLASH_STREAMLOADSTATS \ - (::grpc_core::g_static_metadata_slice_table[22]) -/* "/grpc.health.v1.Health/Watch" */ -#define GRPC_MDSTR_SLASH_GRPC_DOT_HEALTH_DOT_V1_DOT_HEALTH_SLASH_WATCH \ - (::grpc_core::g_static_metadata_slice_table[23]) -/* "/envoy.service.discovery.v2.AggregatedDiscoveryService/StreamAggregatedResources" - */ -#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V2_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \ - (::grpc_core::g_static_metadata_slice_table[24]) -/* "/envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources" - */ -#define GRPC_MDSTR_SLASH_ENVOY_DOT_SERVICE_DOT_DISCOVERY_DOT_V3_DOT_AGGREGATEDDISCOVERYSERVICE_SLASH_STREAMAGGREGATEDRESOURCES \ - (::grpc_core::g_static_metadata_slice_table[25]) -/* "deflate" */ -#define GRPC_MDSTR_DEFLATE (::grpc_core::g_static_metadata_slice_table[26]) -/* "gzip" */ -#define GRPC_MDSTR_GZIP (::grpc_core::g_static_metadata_slice_table[27]) -/* "stream/gzip" */ -#define GRPC_MDSTR_STREAM_SLASH_GZIP \ - (::grpc_core::g_static_metadata_slice_table[28]) -/* "te" */ -#define GRPC_MDSTR_TE (::grpc_core::g_static_metadata_slice_table[29]) -/* "trailers" */ -#define GRPC_MDSTR_TRAILERS (::grpc_core::g_static_metadata_slice_table[30]) -/* "GET" */ -#define GRPC_MDSTR_GET (::grpc_core::g_static_metadata_slice_table[31]) -/* "POST" */ -#define GRPC_MDSTR_POST (::grpc_core::g_static_metadata_slice_table[32]) -/* "/" */ -#define GRPC_MDSTR_SLASH (::grpc_core::g_static_metadata_slice_table[33]) -/* "/index.html" */ -#define GRPC_MDSTR_SLASH_INDEX_DOT_HTML \ - (::grpc_core::g_static_metadata_slice_table[34]) -/* "http" */ -#define GRPC_MDSTR_HTTP (::grpc_core::g_static_metadata_slice_table[35]) -/* "https" */ -#define GRPC_MDSTR_HTTPS (::grpc_core::g_static_metadata_slice_table[36]) -/* "200" */ -#define GRPC_MDSTR_200 (::grpc_core::g_static_metadata_slice_table[37]) -/* "204" */ -#define GRPC_MDSTR_204 (::grpc_core::g_static_metadata_slice_table[38]) -/* "206" */ -#define GRPC_MDSTR_206 (::grpc_core::g_static_metadata_slice_table[39]) -/* "304" */ -#define GRPC_MDSTR_304 (::grpc_core::g_static_metadata_slice_table[40]) -/* "400" */ -#define GRPC_MDSTR_400 (::grpc_core::g_static_metadata_slice_table[41]) -/* "404" */ -#define GRPC_MDSTR_404 (::grpc_core::g_static_metadata_slice_table[42]) -/* "500" */ -#define GRPC_MDSTR_500 (::grpc_core::g_static_metadata_slice_table[43]) -/* "accept-charset" */ -#define GRPC_MDSTR_ACCEPT_CHARSET \ - (::grpc_core::g_static_metadata_slice_table[44]) -/* "gzip, deflate" */ -#define GRPC_MDSTR_GZIP_COMMA_DEFLATE \ - (::grpc_core::g_static_metadata_slice_table[45]) -/* "accept-language" */ -#define GRPC_MDSTR_ACCEPT_LANGUAGE \ - (::grpc_core::g_static_metadata_slice_table[46]) -/* "accept-ranges" */ -#define GRPC_MDSTR_ACCEPT_RANGES \ - (::grpc_core::g_static_metadata_slice_table[47]) -/* "accept" */ -#define GRPC_MDSTR_ACCEPT (::grpc_core::g_static_metadata_slice_table[48]) -/* "access-control-allow-origin" */ -#define GRPC_MDSTR_ACCESS_CONTROL_ALLOW_ORIGIN \ - (::grpc_core::g_static_metadata_slice_table[49]) -/* "age" */ -#define GRPC_MDSTR_AGE (::grpc_core::g_static_metadata_slice_table[50]) -/* "allow" */ -#define GRPC_MDSTR_ALLOW (::grpc_core::g_static_metadata_slice_table[51]) -/* "authorization" */ -#define GRPC_MDSTR_AUTHORIZATION \ - (::grpc_core::g_static_metadata_slice_table[52]) -/* "cache-control" */ -#define GRPC_MDSTR_CACHE_CONTROL \ - (::grpc_core::g_static_metadata_slice_table[53]) -/* "content-disposition" */ -#define GRPC_MDSTR_CONTENT_DISPOSITION \ - (::grpc_core::g_static_metadata_slice_table[54]) -/* "content-language" */ -#define GRPC_MDSTR_CONTENT_LANGUAGE \ - (::grpc_core::g_static_metadata_slice_table[55]) -/* "content-length" */ -#define GRPC_MDSTR_CONTENT_LENGTH \ - (::grpc_core::g_static_metadata_slice_table[56]) -/* "content-location" */ -#define GRPC_MDSTR_CONTENT_LOCATION \ - (::grpc_core::g_static_metadata_slice_table[57]) -/* "content-range" */ -#define GRPC_MDSTR_CONTENT_RANGE \ - (::grpc_core::g_static_metadata_slice_table[58]) -/* "cookie" */ -#define GRPC_MDSTR_COOKIE (::grpc_core::g_static_metadata_slice_table[59]) -/* "date" */ -#define GRPC_MDSTR_DATE (::grpc_core::g_static_metadata_slice_table[60]) -/* "etag" */ -#define GRPC_MDSTR_ETAG (::grpc_core::g_static_metadata_slice_table[61]) -/* "expect" */ -#define GRPC_MDSTR_EXPECT (::grpc_core::g_static_metadata_slice_table[62]) -/* "expires" */ -#define GRPC_MDSTR_EXPIRES (::grpc_core::g_static_metadata_slice_table[63]) -/* "from" */ -#define GRPC_MDSTR_FROM (::grpc_core::g_static_metadata_slice_table[64]) -/* "host" */ -#define GRPC_MDSTR_HOST (::grpc_core::g_static_metadata_slice_table[65]) -/* "if-match" */ -#define GRPC_MDSTR_IF_MATCH (::grpc_core::g_static_metadata_slice_table[66]) -/* "if-modified-since" */ -#define GRPC_MDSTR_IF_MODIFIED_SINCE \ - (::grpc_core::g_static_metadata_slice_table[67]) -/* "if-none-match" */ -#define GRPC_MDSTR_IF_NONE_MATCH \ - (::grpc_core::g_static_metadata_slice_table[68]) -/* "if-range" */ -#define GRPC_MDSTR_IF_RANGE (::grpc_core::g_static_metadata_slice_table[69]) -/* "if-unmodified-since" */ -#define GRPC_MDSTR_IF_UNMODIFIED_SINCE \ - (::grpc_core::g_static_metadata_slice_table[70]) -/* "last-modified" */ -#define GRPC_MDSTR_LAST_MODIFIED \ - (::grpc_core::g_static_metadata_slice_table[71]) -/* "link" */ -#define GRPC_MDSTR_LINK (::grpc_core::g_static_metadata_slice_table[72]) -/* "location" */ -#define GRPC_MDSTR_LOCATION (::grpc_core::g_static_metadata_slice_table[73]) -/* "max-forwards" */ -#define GRPC_MDSTR_MAX_FORWARDS (::grpc_core::g_static_metadata_slice_table[74]) -/* "proxy-authenticate" */ -#define GRPC_MDSTR_PROXY_AUTHENTICATE \ - (::grpc_core::g_static_metadata_slice_table[75]) -/* "proxy-authorization" */ -#define GRPC_MDSTR_PROXY_AUTHORIZATION \ - (::grpc_core::g_static_metadata_slice_table[76]) -/* "range" */ -#define GRPC_MDSTR_RANGE (::grpc_core::g_static_metadata_slice_table[77]) -/* "referer" */ -#define GRPC_MDSTR_REFERER (::grpc_core::g_static_metadata_slice_table[78]) -/* "refresh" */ -#define GRPC_MDSTR_REFRESH (::grpc_core::g_static_metadata_slice_table[79]) -/* "retry-after" */ -#define GRPC_MDSTR_RETRY_AFTER (::grpc_core::g_static_metadata_slice_table[80]) -/* "server" */ -#define GRPC_MDSTR_SERVER (::grpc_core::g_static_metadata_slice_table[81]) -/* "set-cookie" */ -#define GRPC_MDSTR_SET_COOKIE (::grpc_core::g_static_metadata_slice_table[82]) -/* "strict-transport-security" */ -#define GRPC_MDSTR_STRICT_TRANSPORT_SECURITY \ - (::grpc_core::g_static_metadata_slice_table[83]) -/* "transfer-encoding" */ -#define GRPC_MDSTR_TRANSFER_ENCODING \ - (::grpc_core::g_static_metadata_slice_table[84]) -/* "user-agent" */ -#define GRPC_MDSTR_USER_AGENT (::grpc_core::g_static_metadata_slice_table[85]) -/* "vary" */ -#define GRPC_MDSTR_VARY (::grpc_core::g_static_metadata_slice_table[86]) -/* "via" */ -#define GRPC_MDSTR_VIA (::grpc_core::g_static_metadata_slice_table[87]) -/* "www-authenticate" */ -#define GRPC_MDSTR_WWW_AUTHENTICATE \ - (::grpc_core::g_static_metadata_slice_table[88]) -/* "0" */ -#define GRPC_MDSTR_0 (::grpc_core::g_static_metadata_slice_table[89]) -/* "identity" */ -#define GRPC_MDSTR_IDENTITY (::grpc_core::g_static_metadata_slice_table[90]) -/* "application/grpc" */ -#define GRPC_MDSTR_APPLICATION_SLASH_GRPC \ - (::grpc_core::g_static_metadata_slice_table[91]) -/* "grpc" */ -#define GRPC_MDSTR_GRPC (::grpc_core::g_static_metadata_slice_table[92]) -/* "PUT" */ -#define GRPC_MDSTR_PUT (::grpc_core::g_static_metadata_slice_table[93]) -/* "lb-cost-bin" */ -#define GRPC_MDSTR_LB_COST_BIN (::grpc_core::g_static_metadata_slice_table[94]) -/* "identity,deflate" */ -#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE \ - (::grpc_core::g_static_metadata_slice_table[95]) -/* "identity,gzip" */ -#define GRPC_MDSTR_IDENTITY_COMMA_GZIP \ - (::grpc_core::g_static_metadata_slice_table[96]) -/* "deflate,gzip" */ -#define GRPC_MDSTR_DEFLATE_COMMA_GZIP \ - (::grpc_core::g_static_metadata_slice_table[97]) -/* "identity,deflate,gzip" */ -#define GRPC_MDSTR_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ - (::grpc_core::g_static_metadata_slice_table[98]) - -namespace grpc_core { -extern StaticSliceRefcount - g_static_metadata_slice_refcounts[GRPC_STATIC_MDSTR_COUNT]; -extern const StaticMetadataSlice - g_static_metadata_slice_table[GRPC_STATIC_MDSTR_COUNT]; -extern const uint8_t g_static_metadata_bytes[]; -} // namespace grpc_core - -#define GRPC_IS_STATIC_METADATA_STRING(slice) \ - ((slice).refcount != NULL && \ - (slice).refcount->GetType() == grpc_slice_refcount::Type::STATIC) - -#define GRPC_STATIC_METADATA_INDEX(static_slice) \ - (reinterpret_cast<::grpc_core::StaticSliceRefcount*>( \ - (static_slice).refcount) \ - ->index) - -#endif /* GRPC_CORE_LIB_SLICE_STATIC_SLICE_H */ diff --git a/contrib/libs/grpc/src/core/lib/surface/call.cc b/contrib/libs/grpc/src/core/lib/surface/call.cc index a2293df77c..8af61c239b 100644 --- a/contrib/libs/grpc/src/core/lib/surface/call.cc +++ b/contrib/libs/grpc/src/core/lib/surface/call.cc @@ -39,17 +39,17 @@ #include <grpc/support/string_util.h> #include "src/core/lib/channel/channel_stack.h" -#include "src/core/lib/compression/algorithm_metadata.h" +#include "src/core/lib/compression/compression_internal.h" #include "src/core/lib/debug/stats.h" #include "src/core/lib/gpr/alloc.h" #include "src/core/lib/gpr/string.h" #include "src/core/lib/gpr/time_precise.h" #include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/arena.h" #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/gprpp/ref_counted.h" #include "src/core/lib/iomgr/timer.h" #include "src/core/lib/profiling/timers.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/slice/slice_split.h" #include "src/core/lib/slice/slice_string_helpers.h" #include "src/core/lib/slice/slice_utils.h" @@ -60,9 +60,6 @@ #include "src/core/lib/surface/server.h" #include "src/core/lib/surface/validate_metadata.h" #include "src/core/lib/transport/error_utils.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/static_metadata.h" -#include "src/core/lib/transport/status_metadata.h" #include "src/core/lib/transport/transport.h" #include <util/system/yassert.h> @@ -78,11 +75,6 @@ - status/close recv (depending on client/server) */ #define MAX_CONCURRENT_BATCHES 6 -#define MAX_SEND_EXTRA_METADATA_COUNT 3 - -// Used to create arena for the first call. -#define ESTIMATED_MDELEM_COUNT 16 - struct batch_control { batch_control() = default; @@ -198,8 +190,6 @@ struct grpc_call { Element 0 is initial metadata, element 1 is trailing metadata. */ grpc_metadata_array* buffered_metadata[2] = {}; - grpc_metadata compression_md; - // A char* indicating the peer name. gpr_atm peer_string = 0; @@ -208,24 +198,18 @@ struct grpc_call { grpc_call_final_info final_info; /* Compression algorithm for *incoming* data */ - grpc_message_compression_algorithm incoming_message_compression_algorithm = - GRPC_MESSAGE_COMPRESS_NONE; - /* Stream compression algorithm for *incoming* data */ - grpc_stream_compression_algorithm incoming_stream_compression_algorithm = - GRPC_STREAM_COMPRESS_NONE; + grpc_compression_algorithm incoming_compression_algorithm = + GRPC_COMPRESS_NONE; /* Supported encodings (compression algorithms), a bitset. * Always support no compression. */ - uint32_t encodings_accepted_by_peer = 1 << GRPC_MESSAGE_COMPRESS_NONE; + grpc_core::CompressionAlgorithmSet encodings_accepted_by_peer{ + GRPC_COMPRESS_NONE}; /* Supported stream encodings (stream compression algorithms), a bitset */ uint32_t stream_encodings_accepted_by_peer = 0; /* Contexts for various subsystems (security, tracing, ...). */ grpc_call_context_element context[GRPC_CONTEXT_COUNT] = {}; - /* for the client, extra metadata is initial metadata; for the - server, it's trailing metadata */ - grpc_linked_mdelem send_extra_metadata[MAX_SEND_EXTRA_METADATA_COUNT]; - int send_extra_metadata_count; grpc_millis send_deadline; grpc_core::ManualConstructor<grpc_core::SliceBufferByteStream> sending_stream; @@ -341,11 +325,10 @@ static parent_call* get_parent_call(grpc_call* call) { } size_t grpc_call_get_initial_size_estimate() { - return sizeof(grpc_call) + sizeof(batch_control) * MAX_CONCURRENT_BATCHES + - sizeof(grpc_linked_mdelem) * ESTIMATED_MDELEM_COUNT; + return sizeof(grpc_call) + sizeof(batch_control) * MAX_CONCURRENT_BATCHES; } -grpc_error_handle grpc_call_create(const grpc_call_create_args* args, +grpc_error_handle grpc_call_create(grpc_call_create_args* args, grpc_call** out_call) { GPR_TIMER_SCOPE("grpc_call_create", 0); @@ -365,7 +348,8 @@ grpc_error_handle grpc_call_create(const grpc_call_create_args* args, call_and_stack_size + (args->parent ? sizeof(child_call) : 0); std::pair<grpc_core::Arena*, void*> arena_with_call = - grpc_core::Arena::CreateWithAlloc(initial_size, call_alloc_size); + grpc_core::Arena::CreateWithAlloc(initial_size, call_alloc_size, + &*args->channel->allocator); arena = arena_with_call.first; call = new (arena_with_call.second) grpc_call(arena, *args); *out_call = call; @@ -375,24 +359,17 @@ grpc_error_handle grpc_call_create(const grpc_call_create_args* args, call->final_op.client.status = nullptr; call->final_op.client.error_string = nullptr; GRPC_STATS_INC_CLIENT_CALLS_CREATED(); - GPR_ASSERT(args->add_initial_metadata_count < - MAX_SEND_EXTRA_METADATA_COUNT); - for (size_t i = 0; i < args->add_initial_metadata_count; i++) { - call->send_extra_metadata[i].md = args->add_initial_metadata[i]; - if (grpc_slice_eq_static_interned( - GRPC_MDKEY(args->add_initial_metadata[i]), GRPC_MDSTR_PATH)) { - path = grpc_slice_ref_internal( - GRPC_MDVALUE(args->add_initial_metadata[i])); - } + path = grpc_slice_ref_internal(args->path->c_slice()); + call->send_initial_metadata.Set(grpc_core::HttpPathMetadata(), + std::move(*args->path)); + if (args->authority.has_value()) { + call->send_initial_metadata.Set(grpc_core::HttpAuthorityMetadata(), + std::move(*args->authority)); } - call->send_extra_metadata_count = - static_cast<int>(args->add_initial_metadata_count); } else { GRPC_STATS_INC_SERVER_CALLS_CREATED(); call->final_op.server.cancelled = nullptr; call->final_op.server.core_server = args->server; - GPR_ASSERT(args->add_initial_metadata_count == 0); - call->send_extra_metadata_count = 0; } grpc_millis send_deadline = args->send_deadline; @@ -553,9 +530,6 @@ static void destroy_call(void* call, grpc_error_handle /*error*/) { if (pc != nullptr) { pc->~parent_call(); } - for (int i = 0; i < c->send_extra_metadata_count; i++) { - GRPC_MDELEM_UNREF(c->send_extra_metadata[i].md); - } if (c->cq) { GRPC_CQ_INTERNAL_UNREF(c->cq, "bind"); } @@ -781,31 +755,9 @@ static void set_final_status(grpc_call* call, grpc_error_handle error) { * COMPRESSION */ -static void set_incoming_message_compression_algorithm( - grpc_call* call, grpc_message_compression_algorithm algo) { - GPR_ASSERT(algo < GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT); - call->incoming_message_compression_algorithm = algo; -} - -static void set_incoming_stream_compression_algorithm( - grpc_call* call, grpc_stream_compression_algorithm algo) { - GPR_ASSERT(algo < GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT); - call->incoming_stream_compression_algorithm = algo; -} - grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm( grpc_call* call) { - grpc_compression_algorithm algorithm = GRPC_COMPRESS_NONE; - grpc_compression_algorithm_from_message_stream_compression_algorithm( - &algorithm, call->incoming_message_compression_algorithm, - call->incoming_stream_compression_algorithm); - return algorithm; -} - -static grpc_compression_algorithm compression_algorithm_for_level_locked( - grpc_call* call, grpc_compression_level level) { - return grpc_compression_algorithm_for_level(level, - call->encodings_accepted_by_peer); + return call->incoming_compression_algorithm; } uint32_t grpc_call_test_only_get_message_flags(grpc_call* call) { @@ -814,188 +766,91 @@ uint32_t grpc_call_test_only_get_message_flags(grpc_call* call) { return flags; } -static void destroy_encodings_accepted_by_peer(void* /*p*/) {} - -static void set_encodings_accepted_by_peer(grpc_call* /*call*/, - grpc_mdelem mdel, - uint32_t* encodings_accepted_by_peer, - bool stream_encoding) { - size_t i; - uint32_t algorithm; - grpc_slice_buffer accept_encoding_parts; - grpc_slice accept_encoding_slice; - void* accepted_user_data; - - accepted_user_data = - grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer); - if (accepted_user_data != nullptr) { - *encodings_accepted_by_peer = static_cast<uint32_t>( - reinterpret_cast<uintptr_t>(accepted_user_data) - 1); - return; - } - - *encodings_accepted_by_peer = 0; - - accept_encoding_slice = GRPC_MDVALUE(mdel); - grpc_slice_buffer_init(&accept_encoding_parts); - grpc_slice_split_without_space(accept_encoding_slice, ",", - &accept_encoding_parts); - - grpc_core::SetBit(encodings_accepted_by_peer, GRPC_COMPRESS_NONE); - for (i = 0; i < accept_encoding_parts.count; i++) { - int r; - grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i]; - if (!stream_encoding) { - r = grpc_message_compression_algorithm_parse( - accept_encoding_entry_slice, - reinterpret_cast<grpc_message_compression_algorithm*>(&algorithm)); - } else { - r = grpc_stream_compression_algorithm_parse( - accept_encoding_entry_slice, - reinterpret_cast<grpc_stream_compression_algorithm*>(&algorithm)); - } - if (r) { - grpc_core::SetBit(encodings_accepted_by_peer, algorithm); - } else { - char* accept_encoding_entry_str = - grpc_slice_to_c_string(accept_encoding_entry_slice); - gpr_log(GPR_DEBUG, - "Unknown entry in accept encoding metadata: '%s'. Ignoring.", - accept_encoding_entry_str); - gpr_free(accept_encoding_entry_str); - } - } - - grpc_slice_buffer_destroy_internal(&accept_encoding_parts); - - grpc_mdelem_set_user_data( - mdel, destroy_encodings_accepted_by_peer, - reinterpret_cast<void*>( - static_cast<uintptr_t>(*encodings_accepted_by_peer) + 1)); -} - uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call* call) { - uint32_t encodings_accepted_by_peer; - encodings_accepted_by_peer = call->encodings_accepted_by_peer; - return encodings_accepted_by_peer; -} - -grpc_stream_compression_algorithm -grpc_call_test_only_get_incoming_stream_encodings(grpc_call* call) { - return call->incoming_stream_compression_algorithm; -} - -static grpc_linked_mdelem* linked_from_md(grpc_metadata* md) { - return reinterpret_cast<grpc_linked_mdelem*>(&md->internal_data); -} - -static grpc_metadata* get_md_elem(grpc_metadata* metadata, - grpc_metadata* additional_metadata, int i, - int count) { - grpc_metadata* res = - i < count ? &metadata[i] : &additional_metadata[i - count]; - GPR_ASSERT(res); - return res; + return call->encodings_accepted_by_peer.ToLegacyBitmask(); } static int prepare_application_metadata(grpc_call* call, int count, grpc_metadata* metadata, - int is_trailing, - grpc_metadata* additional_metadata, - int additional_metadata_count) { - int total_count = count + additional_metadata_count; + int is_trailing) { int i; grpc_metadata_batch* batch = is_trailing ? &call->send_trailing_metadata : &call->send_initial_metadata; - 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); - GPR_ASSERT(sizeof(grpc_linked_mdelem) == sizeof(md->internal_data)); + for (i = 0; i < count; i++) { + grpc_metadata* md = &metadata[i]; if (!GRPC_LOG_IF_ERROR("validate_metadata", grpc_validate_header_key_is_legal(md->key))) { - break; + return 0; } else if (!grpc_is_binary_header_internal(md->key) && !GRPC_LOG_IF_ERROR( "validate_metadata", grpc_validate_header_nonbin_value_is_legal(md->value))) { - break; + return 0; } else if (GRPC_SLICE_LENGTH(md->value) >= UINT32_MAX) { // HTTP2 hpack encoding has a maximum limit. - break; - } - l->md = grpc_mdelem_from_grpc_metadata(const_cast<grpc_metadata*>(md)); - } - if (i != total_count) { - for (int j = 0; j < i; j++) { - grpc_metadata* md = get_md_elem(metadata, additional_metadata, j, count); - grpc_linked_mdelem* l = linked_from_md(md); - GRPC_MDELEM_UNREF(l->md); - } - return 0; - } - 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_handle error = batch->LinkTail(l); - if (error != GRPC_ERROR_NONE) { - GRPC_MDELEM_UNREF(l->md); + return 0; } - GRPC_LOG_IF_ERROR("prepare_application_metadata", error); + batch->Append( + grpc_core::StringViewFromSlice(md->key), + grpc_core::Slice(grpc_slice_ref_internal(md->value)), + [md](y_absl::string_view error, const grpc_core::Slice& value) { + gpr_log( + GPR_DEBUG, "Append error: %s", + y_absl::StrCat("key=", grpc_core::StringViewFromSlice(md->key), + " error=", error, " value=", value.as_string_view()) + .c_str()); + }); } return 1; } -static grpc_message_compression_algorithm decode_message_compression( - grpc_mdelem md) { - grpc_message_compression_algorithm algorithm = - grpc_message_compression_algorithm_from_slice(GRPC_MDVALUE(md)); - if (algorithm == GRPC_MESSAGE_COMPRESS_ALGORITHMS_COUNT) { - char* md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md)); - gpr_log(GPR_ERROR, - "Invalid incoming message compression algorithm: '%s'. " - "Interpreting incoming data as uncompressed.", - md_c_str); - gpr_free(md_c_str); - return GRPC_MESSAGE_COMPRESS_NONE; - } - return algorithm; -} - -static grpc_stream_compression_algorithm decode_stream_compression( - grpc_mdelem md) { - grpc_stream_compression_algorithm algorithm = - grpc_stream_compression_algorithm_from_slice(GRPC_MDVALUE(md)); - if (algorithm == GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) { - char* md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md)); - gpr_log(GPR_ERROR, - "Invalid incoming stream compression algorithm: '%s'. Interpreting " - "incoming data as uncompressed.", - md_c_str); - gpr_free(md_c_str); - return GRPC_STREAM_COMPRESS_NONE; - } - return algorithm; -} - namespace { class PublishToAppEncoder { public: explicit PublishToAppEncoder(grpc_metadata_array* dest) : dest_(dest) {} - void Encode(grpc_mdelem md) { Append(GRPC_MDKEY(md), GRPC_MDVALUE(md)); } - - void Encode(grpc_core::GrpcTimeoutMetadata, grpc_millis) {} - void Encode(grpc_core::TeMetadata, grpc_core::TeMetadata::ValueType) {} + void Encode(const grpc_core::Slice& key, const grpc_core::Slice& value) { + Append(key.c_slice(), value.c_slice()); + } + // Catch anything that is not explicitly handled, and do not publish it to the + // application. If new metadata is added to a batch that needs to be + // published, it should be called out here. template <typename Which> - void Encode(Which, const grpc_core::Slice& value) { - const auto key = Which::key(); - Append(grpc_core::ExternallyManagedSlice(key.data(), key.length()), - value.c_slice()); + void Encode(Which, const typename Which::ValueType&) {} + + void Encode(grpc_core::UserAgentMetadata, const grpc_core::Slice& slice) { + Append(grpc_core::UserAgentMetadata::key(), slice); + } + + void Encode(grpc_core::HostMetadata, const grpc_core::Slice& slice) { + Append(grpc_core::HostMetadata::key(), slice); + } + + void Encode(grpc_core::GrpcPreviousRpcAttemptsMetadata, uint32_t count) { + Append(grpc_core::GrpcPreviousRpcAttemptsMetadata::key(), count); + } + + void Encode(grpc_core::GrpcRetryPushbackMsMetadata, grpc_millis count) { + Append(grpc_core::GrpcRetryPushbackMsMetadata::key(), count); + } + + void Encode(grpc_core::LbTokenMetadata, const grpc_core::Slice& slice) { + Append(grpc_core::LbTokenMetadata::key(), slice); } private: + void Append(y_absl::string_view key, int64_t value) { + Append(grpc_core::StaticSlice::FromStaticString(key).c_slice(), + grpc_core::Slice::FromInt64(value).c_slice()); + } + + void Append(y_absl::string_view key, const grpc_core::Slice& value) { + Append(grpc_core::StaticSlice::FromStaticString(key).c_slice(), + value.c_slice()); + } + void Append(grpc_slice key, grpc_slice value) { auto* mdusr = &dest_->metadata[dest_->count++]; mdusr->key = key; @@ -1025,40 +880,11 @@ static void publish_app_metadata(grpc_call* call, grpc_metadata_batch* b, } static void recv_initial_filter(grpc_call* call, grpc_metadata_batch* b) { - if (b->legacy_index()->named.content_encoding != nullptr) { - GPR_TIMER_SCOPE("incoming_stream_compression_algorithm", 0); - set_incoming_stream_compression_algorithm( - call, decode_stream_compression( - b->legacy_index()->named.content_encoding->md)); - b->Remove(GRPC_BATCH_CONTENT_ENCODING); - } - if (b->legacy_index()->named.grpc_encoding != nullptr) { - GPR_TIMER_SCOPE("incoming_message_compression_algorithm", 0); - set_incoming_message_compression_algorithm( - call, - decode_message_compression(b->legacy_index()->named.grpc_encoding->md)); - b->Remove(GRPC_BATCH_GRPC_ENCODING); - } - uint32_t message_encodings_accepted_by_peer = 1u; - uint32_t stream_encodings_accepted_by_peer = 1u; - if (b->legacy_index()->named.grpc_accept_encoding != nullptr) { - GPR_TIMER_SCOPE("encodings_accepted_by_peer", 0); - set_encodings_accepted_by_peer( - call, b->legacy_index()->named.grpc_accept_encoding->md, - &message_encodings_accepted_by_peer, false); - b->Remove(GRPC_BATCH_GRPC_ACCEPT_ENCODING); - } - if (b->legacy_index()->named.accept_encoding != nullptr) { - GPR_TIMER_SCOPE("stream_encodings_accepted_by_peer", 0); - set_encodings_accepted_by_peer(call, - b->legacy_index()->named.accept_encoding->md, - &stream_encodings_accepted_by_peer, true); - b->Remove(GRPC_BATCH_ACCEPT_ENCODING); - } + call->incoming_compression_algorithm = + b->Take(grpc_core::GrpcEncodingMetadata()).value_or(GRPC_COMPRESS_NONE); call->encodings_accepted_by_peer = - grpc_compression_bitset_from_message_stream_compression_bitset( - message_encodings_accepted_by_peer, - stream_encodings_accepted_by_peer); + b->Take(grpc_core::GrpcAcceptEncodingMetadata()) + .value_or(grpc_core::CompressionAlgorithmSet{GRPC_COMPRESS_NONE}); publish_app_metadata(call, b, false); } @@ -1067,37 +893,39 @@ static void recv_trailing_filter(void* args, grpc_metadata_batch* b, grpc_call* call = static_cast<grpc_call*>(args); if (batch_error != GRPC_ERROR_NONE) { set_final_status(call, batch_error); - } else if (b->legacy_index()->named.grpc_status != nullptr) { - grpc_status_code status_code = grpc_get_status_code_from_metadata( - b->legacy_index()->named.grpc_status->md); - 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(GRPC_ERROR_CREATE_FROM_CPP_STRING(y_absl::StrCat( - "Error received from peer ", peer)), - GRPC_ERROR_INT_GRPC_STATUS, - static_cast<intptr_t>(status_code)); - gpr_free(peer); - } - auto grpc_message = b->Take(grpc_core::GrpcMessageMetadata()); - if (grpc_message.has_value()) { - error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, - grpc_message->as_string_view()); - } else if (error != GRPC_ERROR_NONE) { - error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, ""); - } - set_final_status(call, GRPC_ERROR_REF(error)); - b->Remove(GRPC_BATCH_GRPC_STATUS); - GRPC_ERROR_UNREF(error); - } else if (!call->is_client) { - set_final_status(call, GRPC_ERROR_NONE); } else { - gpr_log(GPR_DEBUG, - "Received trailing metadata with no error and no status"); - set_final_status( - call, grpc_error_set_int( - GRPC_ERROR_CREATE_FROM_STATIC_STRING("No status received"), - GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNKNOWN)); + y_absl::optional<grpc_status_code> grpc_status = + b->Take(grpc_core::GrpcStatusMetadata()); + if (grpc_status.has_value()) { + grpc_status_code status_code = *grpc_status; + 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( + GRPC_ERROR_CREATE_FROM_CPP_STRING( + y_absl::StrCat("Error received from peer ", peer)), + GRPC_ERROR_INT_GRPC_STATUS, static_cast<intptr_t>(status_code)); + gpr_free(peer); + } + auto grpc_message = b->Take(grpc_core::GrpcMessageMetadata()); + if (grpc_message.has_value()) { + error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, + grpc_message->as_string_view()); + } else if (error != GRPC_ERROR_NONE) { + error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, ""); + } + set_final_status(call, GRPC_ERROR_REF(error)); + GRPC_ERROR_UNREF(error); + } else if (!call->is_client) { + set_final_status(call, GRPC_ERROR_NONE); + } else { + gpr_log(GPR_DEBUG, + "Received trailing metadata with no error and no status"); + set_final_status( + call, grpc_error_set_int( + GRPC_ERROR_CREATE_FROM_STATIC_STRING("No status received"), + GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNKNOWN)); + } } publish_app_metadata(call, b, true); } @@ -1330,15 +1158,9 @@ static void process_data_after_md(batch_control* bctl) { } else { call->test_only_last_message_flags = call->receiving_stream->flags(); if ((call->receiving_stream->flags() & GRPC_WRITE_INTERNAL_COMPRESS) && - (call->incoming_message_compression_algorithm > - GRPC_MESSAGE_COMPRESS_NONE)) { - grpc_compression_algorithm algo; - GPR_ASSERT( - grpc_compression_algorithm_from_message_stream_compression_algorithm( - &algo, call->incoming_message_compression_algorithm, - (grpc_stream_compression_algorithm)0)); - *call->receiving_buffer = - grpc_raw_compressed_byte_buffer_create(nullptr, 0, algo); + (call->incoming_compression_algorithm != GRPC_COMPRESS_NONE)) { + *call->receiving_buffer = grpc_raw_compressed_byte_buffer_create( + nullptr, 0, call->incoming_compression_algorithm); } else { *call->receiving_buffer = grpc_raw_byte_buffer_create(nullptr, 0); } @@ -1379,35 +1201,6 @@ static void receiving_stream_ready_in_call_combiner(void* bctlp, receiving_stream_ready(bctlp, error); } -static void GPR_ATTRIBUTE_NOINLINE -handle_both_stream_and_msg_compression_set(grpc_call* call) { - TString error_msg = y_absl::StrFormat( - "Incoming stream has both stream compression (%d) and message " - "compression (%d).", - call->incoming_stream_compression_algorithm, - call->incoming_message_compression_algorithm); - gpr_log(GPR_ERROR, "%s", error_msg.c_str()); - cancel_with_status(call, GRPC_STATUS_INTERNAL, error_msg.c_str()); -} - -static void GPR_ATTRIBUTE_NOINLINE -handle_error_parsing_compression_algorithm(grpc_call* call) { - TString error_msg = y_absl::StrFormat( - "Error in incoming message compression (%d) or stream " - "compression (%d).", - call->incoming_stream_compression_algorithm, - call->incoming_message_compression_algorithm); - cancel_with_status(call, GRPC_STATUS_INTERNAL, error_msg.c_str()); -} - -static void GPR_ATTRIBUTE_NOINLINE handle_invalid_compression( - grpc_call* call, grpc_compression_algorithm compression_algorithm) { - TString error_msg = y_absl::StrFormat( - "Invalid compression algorithm value '%d'.", compression_algorithm); - gpr_log(GPR_ERROR, "%s", error_msg.c_str()); - cancel_with_status(call, GRPC_STATUS_UNIMPLEMENTED, error_msg.c_str()); -} - static void GPR_ATTRIBUTE_NOINLINE handle_compression_algorithm_disabled( grpc_call* call, grpc_compression_algorithm compression_algorithm) { const char* algo_name = nullptr; @@ -1423,44 +1216,30 @@ static void GPR_ATTRIBUTE_NOINLINE handle_compression_algorithm_not_accepted( const char* algo_name = nullptr; grpc_compression_algorithm_name(compression_algorithm, &algo_name); gpr_log(GPR_ERROR, - "Compression algorithm ('%s') not present in the bitset of " - "accepted encodings ('0x%x')", - algo_name, call->encodings_accepted_by_peer); + "Compression algorithm ('%s') not present in the " + "accepted encodings (%s)", + algo_name, call->encodings_accepted_by_peer.ToString().c_str()); } static void validate_filtered_metadata(batch_control* bctl) { - grpc_compression_algorithm compression_algorithm; grpc_call* call = bctl->call; - if (GPR_UNLIKELY(call->incoming_stream_compression_algorithm != - GRPC_STREAM_COMPRESS_NONE && - call->incoming_message_compression_algorithm != - GRPC_MESSAGE_COMPRESS_NONE)) { - handle_both_stream_and_msg_compression_set(call); - } else if ( - GPR_UNLIKELY( - grpc_compression_algorithm_from_message_stream_compression_algorithm( - &compression_algorithm, - call->incoming_message_compression_algorithm, - call->incoming_stream_compression_algorithm) == 0)) { - handle_error_parsing_compression_algorithm(call); - } else { - const grpc_compression_options compression_options = - grpc_channel_compression_options(call->channel); - if (GPR_UNLIKELY(compression_algorithm >= GRPC_COMPRESS_ALGORITHMS_COUNT)) { - handle_invalid_compression(call, compression_algorithm); - } else if (GPR_UNLIKELY( - grpc_compression_options_is_algorithm_enabled_internal( - &compression_options, compression_algorithm) == 0)) { - /* check if algorithm is supported by current channel config */ - handle_compression_algorithm_disabled(call, compression_algorithm); - } - /* GRPC_COMPRESS_NONE is always set. */ - GPR_DEBUG_ASSERT(call->encodings_accepted_by_peer != 0); - if (GPR_UNLIKELY(!grpc_core::GetBit(call->encodings_accepted_by_peer, - compression_algorithm))) { - if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) { - handle_compression_algorithm_not_accepted(call, compression_algorithm); - } + + const grpc_compression_options compression_options = + grpc_channel_compression_options(call->channel); + const grpc_compression_algorithm compression_algorithm = + call->incoming_compression_algorithm; + if (GPR_UNLIKELY(!grpc_core::CompressionAlgorithmSet::FromUint32( + compression_options.enabled_algorithms_bitset) + .IsSet(compression_algorithm))) { + /* check if algorithm is supported by current channel config */ + handle_compression_algorithm_disabled(call, compression_algorithm); + } + /* GRPC_COMPRESS_NONE is always set. */ + GPR_DEBUG_ASSERT(call->encodings_accepted_by_peer.IsSet(GRPC_COMPRESS_NONE)); + if (GPR_UNLIKELY( + !call->encodings_accepted_by_peer.IsSet(compression_algorithm))) { + if (GRPC_TRACE_FLAG_ENABLED(grpc_compression_trace)) { + handle_compression_algorithm_not_accepted(call, compression_algorithm); } } } @@ -1625,10 +1404,6 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, // GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, we shouldn't override that // with the compression algorithm mapped from compression level. /* process compression level */ - grpc_metadata& compression_md = call->compression_md; - compression_md.key = grpc_empty_slice(); - compression_md.value = grpc_empty_slice(); - size_t additional_metadata_count = 0; grpc_compression_level effective_compression_level = GRPC_COMPRESS_LEVEL_NONE; bool level_set = false; @@ -1647,36 +1422,23 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, // Currently, only server side supports compression level setting. if (level_set && !call->is_client) { const grpc_compression_algorithm calgo = - compression_algorithm_for_level_locked( - call, effective_compression_level); + call->encodings_accepted_by_peer.CompressionAlgorithmForLevel( + effective_compression_level); // The following metadata will be checked and removed by the message // compression filter. It will be used as the call's compression // algorithm. - compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST; - compression_md.value = grpc_compression_algorithm_slice(calgo); - additional_metadata_count++; + call->send_initial_metadata.Set( + grpc_core::GrpcInternalEncodingRequest(), calgo); } - if (op->data.send_initial_metadata.count + additional_metadata_count > - INT_MAX) { + if (op->data.send_initial_metadata.count > INT_MAX) { error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } stream_op->send_initial_metadata = true; call->sent_initial_metadata = true; - if (call->is_client) { - // TODO(ctiller): this will turn into explicit Set() calls once we - // migrate :path, :authority. - for (int i = 0; i < call->send_extra_metadata_count; i++) { - GRPC_LOG_IF_ERROR("prepare_client_metadata", - call->send_initial_metadata.LinkTail( - &call->send_extra_metadata[i])); - } - call->send_extra_metadata_count = 0; - } if (!prepare_application_metadata( call, static_cast<int>(op->data.send_initial_metadata.count), - op->data.send_initial_metadata.metadata, 0, &compression_md, - static_cast<int>(additional_metadata_count))) { + op->data.send_initial_metadata.metadata, 0)) { error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } @@ -1773,8 +1535,7 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call, static_cast<int>( op->data.send_status_from_server.trailing_metadata_count), - op->data.send_status_from_server.trailing_metadata, 1, nullptr, - 0)) { + op->data.send_status_from_server.trailing_metadata, 1)) { error = GRPC_CALL_ERROR_INVALID_METADATA; goto done_with_error; } @@ -1804,10 +1565,9 @@ static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops, call->status_error.set(status_error); GRPC_ERROR_UNREF(status_error); - GRPC_LOG_IF_ERROR( - "set call status", - call->send_trailing_metadata.Append(grpc_get_reffed_status_elem( - op->data.send_status_from_server.status))); + call->send_trailing_metadata.Set( + grpc_core::GrpcStatusMetadata(), + op->data.send_status_from_server.status); stream_op_payload->send_trailing_metadata.send_trailing_metadata = &call->send_trailing_metadata; @@ -2030,9 +1790,7 @@ uint8_t grpc_call_is_client(grpc_call* call) { return call->is_client; } grpc_compression_algorithm grpc_call_compression_for_level( grpc_call* call, grpc_compression_level level) { - grpc_compression_algorithm algo = - compression_algorithm_for_level_locked(call, level); - return algo; + return call->encodings_accepted_by_peer.CompressionAlgorithmForLevel(level); } bool grpc_call_is_trailers_only(const grpc_call* call) { diff --git a/contrib/libs/grpc/src/core/lib/surface/call.h b/contrib/libs/grpc/src/core/lib/surface/call.h index e16a6be520..d59f99a268 100644 --- a/contrib/libs/grpc/src/core/lib/surface/call.h +++ b/contrib/libs/grpc/src/core/lib/surface/call.h @@ -26,7 +26,7 @@ #include "src/core/lib/channel/channel_stack.h" #include "src/core/lib/channel/context.h" -#include "src/core/lib/gprpp/arena.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/server.h" @@ -46,8 +46,8 @@ typedef struct grpc_call_create_args { const void* server_transport_data; - grpc_mdelem* add_initial_metadata; - size_t add_initial_metadata_count; + y_absl::optional<grpc_core::Slice> path; + y_absl::optional<grpc_core::Slice> authority; grpc_millis send_deadline; } grpc_call_create_args; @@ -55,7 +55,7 @@ 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_handle grpc_call_create(const grpc_call_create_args* args, +grpc_error_handle grpc_call_create(grpc_call_create_args* args, grpc_call** call); void grpc_call_set_completion_queue(grpc_call* call, grpc_completion_queue* cq); diff --git a/contrib/libs/grpc/src/core/lib/surface/channel.cc b/contrib/libs/grpc/src/core/lib/surface/channel.cc index d764ce08df..98d8d46936 100644 --- a/contrib/libs/grpc/src/core/lib/surface/channel.cc +++ b/contrib/libs/grpc/src/core/lib/surface/channel.cc @@ -41,11 +41,12 @@ #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/iomgr/iomgr.h" +#include "src/core/lib/resource_quota/api.h" #include "src/core/lib/resource_quota/memory_quota.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/surface/api_trace.h" #include "src/core/lib/surface/call.h" -#include "src/core/lib/transport/static_metadata.h" +#include "src/core/lib/surface/channel_stack_type.h" /** Cache grpc-status: X mdelems for X = 0..NUM_CACHED_STATUS_ELEMS. * Avoids needing to take a metadata context lock for sending status @@ -59,7 +60,7 @@ 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_handle* error) { - char* target = gpr_strdup(grpc_channel_stack_builder_get_target(builder)); + TString target = grpc_channel_stack_builder_get_target(builder); grpc_channel_args* args = grpc_channel_args_copy( grpc_channel_stack_builder_get_channel_arguments(builder)); grpc_channel* channel; @@ -68,6 +69,7 @@ grpc_channel* grpc_channel_create_with_builder( } else { GRPC_STATS_INC_CLIENT_CHANNELS_CREATED(); } + TString name = grpc_channel_stack_builder_get_target(builder); grpc_error_handle builder_error = grpc_channel_stack_builder_finish( builder, sizeof(grpc_channel), 1, destroy_channel, nullptr, reinterpret_cast<void**>(&channel)); @@ -80,13 +82,15 @@ grpc_channel* grpc_channel_create_with_builder( } else { GRPC_ERROR_UNREF(builder_error); } - gpr_free(target); grpc_channel_args_destroy(args); return nullptr; } - channel->target = target; + channel->target.Init(std::move(target)); channel->is_client = grpc_channel_stack_type_is_client(channel_stack_type); channel->registration_table.Init(); + channel->allocator.Init(grpc_core::ResourceQuotaFromChannelArgs(args) + ->memory_quota() + ->CreateMemoryOwner(name)); gpr_atm_no_barrier_store( &channel->call_size_estimate, @@ -197,11 +201,10 @@ void CreateChannelzNode(grpc_channel_stack_builder* builder) { const bool is_internal_channel = grpc_channel_args_find_bool( args, GRPC_ARG_CHANNELZ_IS_INTERNAL_CHANNEL, false); // Create the channelz node. - const char* target = grpc_channel_stack_builder_get_target(builder); + TString target = grpc_channel_stack_builder_get_target(builder); grpc_core::RefCountedPtr<grpc_core::channelz::ChannelNode> channelz_node = grpc_core::MakeRefCounted<grpc_core::channelz::ChannelNode>( - target != nullptr ? target : "", channel_tracer_max_memory, - is_internal_channel); + target.c_str(), channel_tracer_max_memory, is_internal_channel); channelz_node->AddTraceEvent( grpc_core::channelz::ChannelTrace::Severity::Info, grpc_slice_from_static_string("Channel created")); @@ -241,7 +244,8 @@ grpc_channel* grpc_channel_create(const char* target, // grpc_shutdown() when the channel is actually destroyed, thus // ensuring that shutdown is deferred until that point. grpc_init(); - grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create(); + grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create( + grpc_channel_stack_type_string(channel_stack_type)); const grpc_core::UniquePtr<char> default_authority = get_default_authority(input_args); grpc_channel_args* args = @@ -313,7 +317,7 @@ void grpc_channel_update_call_size_estimate(grpc_channel* channel, char* grpc_channel_get_target(grpc_channel* channel) { GRPC_API_TRACE("grpc_channel_get_target(channel=%p)", 1, (channel)); - return gpr_strdup(channel->target); + return gpr_strdup(channel->target->c_str()); } void grpc_channel_get_info(grpc_channel* channel, @@ -340,19 +344,11 @@ void grpc_channel_reset_connect_backoff(grpc_channel* channel) { static grpc_call* grpc_channel_create_call_internal( grpc_channel* channel, grpc_call* parent_call, uint32_t propagation_mask, grpc_completion_queue* cq, grpc_pollset_set* pollset_set_alternative, - grpc_mdelem path_mdelem, grpc_mdelem authority_mdelem, + grpc_core::Slice path, y_absl::optional<grpc_core::Slice> authority, grpc_millis deadline) { - grpc_mdelem send_metadata[2]; - size_t num_metadata = 0; - GPR_ASSERT(channel->is_client); GPR_ASSERT(!(cq != nullptr && pollset_set_alternative != nullptr)); - send_metadata[num_metadata++] = path_mdelem; - if (!GRPC_MDISNULL(authority_mdelem)) { - send_metadata[num_metadata++] = authority_mdelem; - } - grpc_call_create_args args; args.channel = channel; args.server = nullptr; @@ -361,8 +357,8 @@ static grpc_call* grpc_channel_create_call_internal( args.cq = cq; args.pollset_set_alternative = pollset_set_alternative; args.server_transport_data = nullptr; - args.add_initial_metadata = send_metadata; - args.add_initial_metadata_count = num_metadata; + args.path = std::move(path); + args.authority = std::move(authority); args.send_deadline = deadline; grpc_call* call; @@ -381,9 +377,10 @@ grpc_call* grpc_channel_create_call(grpc_channel* channel, grpc_core::ExecCtx exec_ctx; grpc_call* call = grpc_channel_create_call_internal( channel, parent_call, propagation_mask, completion_queue, nullptr, - grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr), - host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr) - : GRPC_MDNULL, + grpc_core::Slice(grpc_slice_ref_internal(method)), + host != nullptr + ? y_absl::optional<grpc_core::Slice>(grpc_slice_ref_internal(*host)) + : y_absl::nullopt, grpc_timespec_to_millis_round_up(deadline)); return call; @@ -396,34 +393,31 @@ grpc_call* grpc_channel_create_pollset_set_call( GPR_ASSERT(!reserved); return grpc_channel_create_call_internal( channel, parent_call, propagation_mask, nullptr, pollset_set, - grpc_mdelem_create(GRPC_MDSTR_PATH, method, nullptr), - host != nullptr ? grpc_mdelem_create(GRPC_MDSTR_AUTHORITY, *host, nullptr) - : GRPC_MDNULL, + grpc_core::Slice(method), + host != nullptr + ? y_absl::optional<grpc_core::Slice>(grpc_slice_ref_internal(*host)) + : y_absl::nullopt, deadline); } namespace grpc_core { -RegisteredCall::RegisteredCall(const char* method_arg, const char* host_arg) - : path(method_arg != nullptr && method_arg[0] != 0 - ? grpc_mdelem_from_slices( - GRPC_MDSTR_PATH, grpc_slice_from_copied_string(method_arg)) - : GRPC_MDNULL), - authority( - host_arg != nullptr && host_arg[0] != 0 - ? grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY, - grpc_slice_from_copied_string(host_arg)) - : GRPC_MDNULL) {} +RegisteredCall::RegisteredCall(const char* method_arg, const char* host_arg) { + path = Slice::FromCopiedString(method_arg); + if (host_arg != nullptr && host_arg[0] != 0) { + authority = Slice::FromCopiedString(host_arg); + } +} RegisteredCall::RegisteredCall(const RegisteredCall& other) - : path(GRPC_MDELEM_REF(other.path)), - authority(GRPC_MDELEM_REF(other.authority)) {} - -RegisteredCall::~RegisteredCall() { - GRPC_MDELEM_UNREF(path); - GRPC_MDELEM_UNREF(authority); + : path(other.path.Ref()) { + if (other.authority.has_value()) { + authority = other.authority->Ref(); + } } +RegisteredCall::~RegisteredCall() {} + } // namespace grpc_core void* grpc_channel_register_call(grpc_channel* channel, const char* method, @@ -470,7 +464,10 @@ grpc_call* grpc_channel_create_registered_call( grpc_core::ExecCtx exec_ctx; grpc_call* call = grpc_channel_create_call_internal( channel, parent_call, propagation_mask, completion_queue, nullptr, - GRPC_MDELEM_REF(rc->path), GRPC_MDELEM_REF(rc->authority), + rc->path.Ref(), + rc->authority.has_value() + ? y_absl::optional<grpc_core::Slice>(rc->authority->Ref()) + : y_absl::nullopt, grpc_timespec_to_millis_round_up(deadline)); return call; @@ -486,7 +483,8 @@ static void destroy_channel(void* arg, grpc_error_handle /*error*/) { } grpc_channel_stack_destroy(CHANNEL_STACK_FROM_CHANNEL(channel)); channel->registration_table.Destroy(); - gpr_free(channel->target); + channel->allocator.Destroy(); + channel->target.Destroy(); gpr_free(channel); // See comment in grpc_channel_create() for why we do this. grpc_shutdown(); diff --git a/contrib/libs/grpc/src/core/lib/surface/channel.h b/contrib/libs/grpc/src/core/lib/surface/channel.h index dbf59f4afe..1ae471a787 100644 --- a/contrib/libs/grpc/src/core/lib/surface/channel.h +++ b/contrib/libs/grpc/src/core/lib/surface/channel.h @@ -29,7 +29,6 @@ #include "src/core/lib/gprpp/manual_constructor.h" #include "src/core/lib/resource_quota/memory_quota.h" #include "src/core/lib/surface/channel_stack_type.h" -#include "src/core/lib/transport/metadata.h" /// Creates a grpc_channel. grpc_channel* grpc_channel_create(const char* target, @@ -74,8 +73,8 @@ void grpc_channel_update_call_size_estimate(grpc_channel* channel, size_t size); namespace grpc_core { struct RegisteredCall { - grpc_mdelem path; - grpc_mdelem authority; + Slice path; + y_absl::optional<Slice> authority; explicit RegisteredCall(const char* method_arg, const char* host_arg); RegisteredCall(const RegisteredCall& other); @@ -110,8 +109,9 @@ struct grpc_channel { grpc_core::ManualConstructor<grpc_core::CallRegistrationTable> registration_table; grpc_core::RefCountedPtr<grpc_core::channelz::ChannelNode> channelz_node; + grpc_core::ManualConstructor<grpc_core::MemoryAllocator> allocator; - char* target; + grpc_core::ManualConstructor<TString> target; }; #define CHANNEL_STACK_FROM_CHANNEL(c) ((grpc_channel_stack*)((c) + 1)) diff --git a/contrib/libs/grpc/src/core/lib/surface/init.cc b/contrib/libs/grpc/src/core/lib/surface/init.cc index 7099a01b27..23c6c1192c 100644 --- a/contrib/libs/grpc/src/core/lib/surface/init.cc +++ b/contrib/libs/grpc/src/core/lib/surface/init.cc @@ -105,7 +105,6 @@ void grpc_init(void) { grpc_fork_handlers_auto_register(); grpc_stats_init(); grpc_slice_intern_init(); - grpc_mdctx_global_init(); grpc_core::channelz::ChannelzRegistry::Init(); grpc_security_pre_init(); grpc_core::ApplicationCallbackExecCtx::GlobalInit(); @@ -141,7 +140,6 @@ void grpc_shutdown_internal_locked(void) grpc_iomgr_shutdown(); gpr_timers_global_destroy(); grpc_tracer_shutdown(); - grpc_mdctx_global_shutdown(); grpc_slice_intern_shutdown(); grpc_core::channelz::ChannelzRegistry::Shutdown(); grpc_stats_shutdown(); diff --git a/contrib/libs/grpc/src/core/lib/surface/lame_client.cc b/contrib/libs/grpc/src/core/lib/surface/lame_client.cc index a9a564a128..88dd3c5dc5 100644 --- a/contrib/libs/grpc/src/core/lib/surface/lame_client.cc +++ b/contrib/libs/grpc/src/core/lib/surface/lame_client.cc @@ -35,7 +35,6 @@ #include "src/core/lib/surface/call.h" #include "src/core/lib/surface/channel.h" #include "src/core/lib/transport/connectivity_state.h" -#include "src/core/lib/transport/static_metadata.h" #define GRPC_ARG_LAME_FILTER_ERROR "grpc.lame_filter_error" diff --git a/contrib/libs/grpc/src/core/lib/surface/server.cc b/contrib/libs/grpc/src/core/lib/surface/server.cc index b10ddcd866..631d9b74e1 100644 --- a/contrib/libs/grpc/src/core/lib/surface/server.cc +++ b/contrib/libs/grpc/src/core/lib/surface/server.cc @@ -53,8 +53,6 @@ #include "src/core/lib/surface/channel.h" #include "src/core/lib/surface/completion_queue.h" #include "src/core/lib/surface/init.h" -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/static_metadata.h" namespace grpc_core { @@ -1035,8 +1033,7 @@ void Server::ChannelData::InitTransport(RefCountedPtr<Server> server, if (has_host) { host = ExternallyManagedSlice(rm->host.c_str()); } - uint32_t hash = - GRPC_MDSTR_KV_HASH(has_host ? host.Hash() : 0, method.Hash()); + uint32_t hash = MixHash32(has_host ? host.Hash() : 0, method.Hash()); uint32_t probes = 0; for (probes = 0; (*registered_methods_)[(hash + probes) % slots] .server_registered_method != nullptr; @@ -1080,8 +1077,8 @@ Server::ChannelRegisteredMethod* Server::ChannelData::GetRegisteredMethod( if (registered_methods_ == nullptr) return nullptr; /* TODO(ctiller): unify these two searches */ /* check for an exact match with host */ - uint32_t hash = GRPC_MDSTR_KV_HASH(grpc_slice_hash_internal(host), - grpc_slice_hash_internal(path)); + uint32_t hash = + MixHash32(grpc_slice_hash_internal(host), grpc_slice_hash_internal(path)); for (size_t i = 0; i <= registered_method_max_probes_; i++) { ChannelRegisteredMethod* rm = &(*registered_methods_)[(hash + i) % registered_methods_->size()]; @@ -1096,7 +1093,7 @@ Server::ChannelRegisteredMethod* Server::ChannelData::GetRegisteredMethod( return rm; } /* check for a wildcard method definition (no host set) */ - hash = GRPC_MDSTR_KV_HASH(0, grpc_slice_hash_internal(path)); + hash = MixHash32(0, grpc_slice_hash_internal(path)); for (size_t i = 0; i <= registered_method_max_probes_; i++) { ChannelRegisteredMethod* rm = &(*registered_methods_)[(hash + i) % registered_methods_->size()]; @@ -1124,8 +1121,6 @@ void Server::ChannelData::AcceptStream(void* arg, grpc_transport* /*transport*/, args.cq = nullptr; args.pollset_set_alternative = nullptr; args.server_transport_data = transport_server_data; - args.add_initial_metadata = nullptr; - args.add_initial_metadata_count = 0; args.send_deadline = GRPC_MILLIS_INF_FUTURE; grpc_call* call; grpc_error_handle error = grpc_call_create(&args, &call); @@ -1200,12 +1195,6 @@ Server::CallData::CallData(grpc_call_element* elem, Server::CallData::~CallData() { GPR_ASSERT(state_.load(std::memory_order_relaxed) != CallState::PENDING); GRPC_ERROR_UNREF(recv_initial_metadata_error_); - if (host_.has_value()) { - grpc_slice_unref_internal(*host_); - } - if (path_.has_value()) { - grpc_slice_unref_internal(*path_); - } grpc_metadata_array_destroy(&initial_metadata_); grpc_byte_buffer_destroy(payload_); } @@ -1258,8 +1247,9 @@ void Server::CallData::Publish(size_t cq_idx, RequestedCall* rc) { case RequestedCall::Type::BATCH_CALL: GPR_ASSERT(host_.has_value()); GPR_ASSERT(path_.has_value()); - rc->data.batch.details->host = grpc_slice_ref_internal(*host_); - rc->data.batch.details->method = grpc_slice_ref_internal(*path_); + rc->data.batch.details->host = grpc_slice_ref_internal(host_->c_slice()); + rc->data.batch.details->method = + grpc_slice_ref_internal(path_->c_slice()); rc->data.batch.details->deadline = grpc_millis_to_timespec(deadline_, GPR_CLOCK_MONOTONIC); rc->data.batch.details->flags = recv_initial_metadata_flags_; @@ -1320,7 +1310,7 @@ void Server::CallData::StartNewRpc(grpc_call_element* elem) { GRPC_SRM_PAYLOAD_NONE; if (path_.has_value() && host_.has_value()) { ChannelRegisteredMethod* rm = - chand->GetRegisteredMethod(*host_, *path_, + chand->GetRegisteredMethod(host_->c_slice(), path_->c_slice(), (recv_initial_metadata_flags_ & GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST)); if (rm != nullptr) { @@ -1352,6 +1342,8 @@ void Server::CallData::RecvInitialMetadataBatchComplete( grpc_call_element* elem = static_cast<grpc_call_element*>(arg); auto* calld = static_cast<Server::CallData*>(elem->call_data); if (error != GRPC_ERROR_NONE) { + gpr_log(GPR_DEBUG, "Failed call creation: %s", + grpc_error_std_string(error).c_str()); calld->FailCallCreation(); return; } @@ -1385,17 +1377,8 @@ void Server::CallData::RecvInitialMetadataReady(void* arg, grpc_call_element* elem = static_cast<grpc_call_element*>(arg); CallData* calld = static_cast<CallData*>(elem->call_data); if (error == GRPC_ERROR_NONE) { - GPR_DEBUG_ASSERT( - calld->recv_initial_metadata_->legacy_index()->named.path != nullptr); - GPR_DEBUG_ASSERT( - calld->recv_initial_metadata_->legacy_index()->named.authority != - nullptr); - calld->path_.emplace(grpc_slice_ref_internal(GRPC_MDVALUE( - calld->recv_initial_metadata_->legacy_index()->named.path->md))); - calld->host_.emplace(grpc_slice_ref_internal(GRPC_MDVALUE( - calld->recv_initial_metadata_->legacy_index()->named.authority->md))); - calld->recv_initial_metadata_->Remove(GRPC_BATCH_PATH); - calld->recv_initial_metadata_->Remove(GRPC_BATCH_AUTHORITY); + calld->path_ = calld->recv_initial_metadata_->Take(HttpPathMetadata()); + calld->host_ = calld->recv_initial_metadata_->Take(HttpAuthorityMetadata()); } else { (void)GRPC_ERROR_REF(error); } diff --git a/contrib/libs/grpc/src/core/lib/surface/server.h b/contrib/libs/grpc/src/core/lib/surface/server.h index f42df7d9a7..cbbd55f867 100644 --- a/contrib/libs/grpc/src/core/lib/surface/server.h +++ b/contrib/libs/grpc/src/core/lib/surface/server.h @@ -293,8 +293,8 @@ class Server : public InternallyRefCounted<Server>, std::atomic<CallState> state_{CallState::NOT_STARTED}; - y_absl::optional<grpc_slice> path_; - y_absl::optional<grpc_slice> host_; + y_absl::optional<Slice> path_; + y_absl::optional<Slice> host_; grpc_millis deadline_ = GRPC_MILLIS_INF_FUTURE; grpc_completion_queue* cq_new_ = nullptr; diff --git a/contrib/libs/grpc/src/core/lib/surface/version.cc b/contrib/libs/grpc/src/core/lib/surface/version.cc index 64f2829d9d..159a23956a 100644 --- a/contrib/libs/grpc/src/core/lib/surface/version.cc +++ b/contrib/libs/grpc/src/core/lib/surface/version.cc @@ -23,6 +23,6 @@ #include <grpc/grpc.h> -const char* grpc_version_string(void) { return "21.0.0"; } +const char* grpc_version_string(void) { return "22.0.0"; } -const char* grpc_g_stands_for(void) { return "green"; } +const char* grpc_g_stands_for(void) { return "great"; } diff --git a/contrib/libs/grpc/src/core/lib/transport/error_utils.h b/contrib/libs/grpc/src/core/lib/transport/error_utils.h index 8672541619..6689541cb9 100644 --- a/contrib/libs/grpc/src/core/lib/transport/error_utils.h +++ b/contrib/libs/grpc/src/core/lib/transport/error_utils.h @@ -27,6 +27,20 @@ #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/transport/http2_errors.h" +namespace grpc_core { + +enum class StreamNetworkState { + // Stream was never sent on the wire (e.g., because the transport became + // disconnected by the time the call got down to it). + kNotSentOnWire, + // Stream was sent on the wire but was not seen by the server application + // code (e.g., client sent data but then received a GOAWAY with a lower + // stream ID). + kNotSeenByServer, +}; + +} // namespace grpc_core + /// A utility function to get the status code and message to be returned /// to the application. If not set in the top-level message, looks /// through child errors until it finds the first one with these attributes. diff --git a/contrib/libs/grpc/src/core/lib/transport/metadata.cc b/contrib/libs/grpc/src/core/lib/transport/metadata.cc deleted file mode 100644 index 004e44af23..0000000000 --- a/contrib/libs/grpc/src/core/lib/transport/metadata.cc +++ /dev/null @@ -1,714 +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. - * - */ - -#include <grpc/support/port_platform.h> - -#include "src/core/lib/transport/metadata.h" - -#include <assert.h> -#include <inttypes.h> -#include <stddef.h> -#include <string.h> - -#include <grpc/compression.h> -#include <grpc/grpc.h> -#include <grpc/support/alloc.h> -#include <grpc/support/atm.h> -#include <grpc/support/log.h> -#include <grpc/support/string_util.h> -#include <grpc/support/time.h> - -#include "src/core/lib/gpr/murmur_hash.h" -#include "src/core/lib/gpr/string.h" -#include "src/core/lib/iomgr/iomgr_internal.h" -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/transport/static_metadata.h" - -using grpc_core::AllocatedMetadata; -using grpc_core::InternedMetadata; -using grpc_core::StaticMetadata; -using grpc_core::UserData; - -/* There are two kinds of mdelem and mdstr instances. - * Static instances are declared in static_metadata.{h,c} and - * are initialized by grpc_mdctx_global_init(). - * Dynamic instances are stored in hash tables on grpc_mdctx, and are backed - * by internal_string and internal_element structures. - * Internal helper functions here-in (is_mdstr_static, is_mdelem_static) are - * used to determine which kind of element a pointer refers to. - */ - -grpc_core::DebugOnlyTraceFlag grpc_trace_metadata(false, "metadata"); - -#ifndef NDEBUG -#define DEBUG_ARGS , const char *file, int line -#define FWD_DEBUG_ARGS file, line - -void grpc_mdelem_trace_ref(void* md, const grpc_slice& key, - const grpc_slice& value, intptr_t refcnt, - const char* file, int line) { - if (grpc_trace_metadata.enabled()) { - char* key_str = grpc_slice_to_c_string(key); - char* value_str = grpc_slice_to_c_string(value); - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "mdelem REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md, - refcnt, refcnt + 1, key_str, value_str); - gpr_free(key_str); - gpr_free(value_str); - } -} - -void grpc_mdelem_trace_unref(void* md, const grpc_slice& key, - const grpc_slice& value, intptr_t refcnt, - const char* file, int line) { - if (grpc_trace_metadata.enabled()) { - char* key_str = grpc_slice_to_c_string(key); - char* value_str = grpc_slice_to_c_string(value); - gpr_log(file, line, GPR_LOG_SEVERITY_DEBUG, - "mdelem UNREF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", md, - refcnt, refcnt - 1, key_str, value_str); - gpr_free(key_str); - gpr_free(value_str); - } -} - -#else // ifndef NDEBUG -#define DEBUG_ARGS -#define FWD_DEBUG_ARGS -#endif // ifndef NDEBUG - -#define INITIAL_SHARD_CAPACITY 8 -#define LOG2_SHARD_COUNT 4 -#define SHARD_COUNT ((size_t)(1 << LOG2_SHARD_COUNT)) - -#define TABLE_IDX(hash, capacity) (((hash) >> (LOG2_SHARD_COUNT)) % (capacity)) -#define SHARD_IDX(hash) ((hash) & ((1 << (LOG2_SHARD_COUNT)) - 1)) - -void StaticMetadata::HashInit() { - uint32_t k_hash = grpc_slice_hash_internal(kv_.key); - uint32_t v_hash = grpc_slice_hash_internal(kv_.value); - hash_ = GRPC_MDSTR_KV_HASH(k_hash, v_hash); -} - -AllocatedMetadata::AllocatedMetadata(const grpc_slice& key, - const grpc_slice& value) - : RefcountedMdBase(grpc_slice_ref_internal(key), - grpc_slice_ref_internal(value)) { -#ifndef NDEBUG - TraceAtStart("ALLOC_MD"); -#endif -} - -AllocatedMetadata::AllocatedMetadata(const grpc_slice& key, - const grpc_slice& value, const NoRefKey*) - : RefcountedMdBase(key, grpc_slice_ref_internal(value)) { -#ifndef NDEBUG - TraceAtStart("ALLOC_MD_NOREF_KEY"); -#endif -} - -AllocatedMetadata::AllocatedMetadata( - const grpc_core::ManagedMemorySlice& key, - const grpc_core::UnmanagedMemorySlice& value) - : RefcountedMdBase(key, value) { -#ifndef NDEBUG - TraceAtStart("ALLOC_MD_NOREF_KEY_VAL"); -#endif -} - -AllocatedMetadata::AllocatedMetadata( - const grpc_core::ExternallyManagedSlice& key, - const grpc_core::UnmanagedMemorySlice& value) - : RefcountedMdBase(key, value) { -#ifndef NDEBUG - TraceAtStart("ALLOC_MD_NOREF_KEY_VAL"); -#endif -} - -AllocatedMetadata::~AllocatedMetadata() { - grpc_slice_unref_internal(key()); - grpc_slice_unref_internal(value()); - void* user_data = user_data_.data.load(std::memory_order_relaxed); - if (user_data) { - destroy_user_data_func destroy_user_data = - user_data_.destroy_user_data.load(std::memory_order_relaxed); - destroy_user_data(user_data); - } -} - -#ifndef NDEBUG -void grpc_core::RefcountedMdBase::TraceAtStart(const char* tag) { - if (grpc_trace_metadata.enabled()) { - char* key_str = grpc_slice_to_c_string(key()); - char* value_str = grpc_slice_to_c_string(value()); - gpr_log(GPR_DEBUG, "mdelem %s:%p:%" PRIdPTR ": '%s' = '%s'", tag, this, - RefValue(), key_str, value_str); - gpr_free(key_str); - gpr_free(value_str); - } -} -#endif - -InternedMetadata::InternedMetadata(const grpc_slice& key, - const grpc_slice& value, uint32_t hash, - InternedMetadata* next) - : RefcountedMdBase(grpc_slice_ref_internal(key), - grpc_slice_ref_internal(value), hash), - link_(next) { -#ifndef NDEBUG - TraceAtStart("INTERNED_MD"); -#endif -} - -InternedMetadata::InternedMetadata(const grpc_slice& key, - const grpc_slice& value, uint32_t hash, - InternedMetadata* next, const NoRefKey*) - : RefcountedMdBase(key, grpc_slice_ref_internal(value), hash), link_(next) { -#ifndef NDEBUG - TraceAtStart("INTERNED_MD_NOREF_KEY"); -#endif -} - -InternedMetadata::~InternedMetadata() { - grpc_slice_unref_internal(key()); - grpc_slice_unref_internal(value()); - void* user_data = user_data_.data.load(std::memory_order_relaxed); - if (user_data) { - destroy_user_data_func destroy_user_data = - user_data_.destroy_user_data.load(std::memory_order_relaxed); - destroy_user_data(user_data); - } -} - -size_t InternedMetadata::CleanupLinkedMetadata( - InternedMetadata::BucketLink* head) { - size_t num_freed = 0; - InternedMetadata::BucketLink* prev_next = head; - InternedMetadata *md, *next; - - for (md = head->next; md; md = next) { - next = md->link_.next; - if (md->AllRefsDropped()) { - prev_next->next = next; - delete md; - num_freed++; - } else { - prev_next = &md->link_; - } - } - return num_freed; -} - -typedef struct mdtab_shard { - gpr_mu mu; - InternedMetadata::BucketLink* elems; - size_t count; - size_t capacity; - /** Estimate of the number of unreferenced mdelems in the hash table. - This will eventually converge to the exact number, but it's instantaneous - accuracy is not guaranteed */ - gpr_atm free_estimate; -} mdtab_shard; - -static mdtab_shard g_shards[SHARD_COUNT]; - -static void gc_mdtab(mdtab_shard* shard); - -void grpc_mdctx_global_init(void) { - /* initialize shards */ - for (size_t i = 0; i < SHARD_COUNT; i++) { - mdtab_shard* shard = &g_shards[i]; - gpr_mu_init(&shard->mu); - shard->count = 0; - gpr_atm_no_barrier_store(&shard->free_estimate, 0); - shard->capacity = INITIAL_SHARD_CAPACITY; - shard->elems = static_cast<InternedMetadata::BucketLink*>( - gpr_zalloc(sizeof(*shard->elems) * shard->capacity)); - } -} - -void grpc_mdctx_global_shutdown() { - for (size_t i = 0; i < SHARD_COUNT; i++) { - mdtab_shard* shard = &g_shards[i]; - gpr_mu_destroy(&shard->mu); - gc_mdtab(shard); - if (shard->count != 0) { - gpr_log(GPR_ERROR, "WARNING: %" PRIuPTR " metadata elements were leaked", - shard->count); - for (size_t i = 0; i < shard->capacity; i++) { - for (InternedMetadata* md = shard->elems[i].next; md; - md = md->bucket_next()) { - char* key_str = grpc_slice_to_c_string(md->key()); - char* value_str = grpc_slice_to_c_string(md->value()); - gpr_log(GPR_ERROR, "mdelem '%s' = '%s'", key_str, value_str); - gpr_free(key_str); - gpr_free(value_str); - } - } - if (grpc_iomgr_abort_on_leaks()) { - abort(); - } - } - // For ASAN builds, we don't want to crash here, because that will - // prevent ASAN from providing leak detection information, which is - // far more useful than this simple assertion. -#ifndef GRPC_ASAN_ENABLED - GPR_DEBUG_ASSERT(shard->count == 0); -#endif - gpr_free(shard->elems); - } -} - -#ifndef NDEBUG -static int is_mdelem_static(grpc_mdelem e) { - return reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(e)) >= - &grpc_core::g_static_mdelem_table[0] && - reinterpret_cast<grpc_core::StaticMetadata*>(GRPC_MDELEM_DATA(e)) < - &grpc_core::g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; -} -#endif - -void InternedMetadata::RefWithShardLocked(mdtab_shard* shard) { -#ifndef NDEBUG - if (grpc_trace_metadata.enabled()) { - char* key_str = grpc_slice_to_c_string(key()); - char* value_str = grpc_slice_to_c_string(value()); - intptr_t value = RefValue(); - gpr_log(__FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG, - "mdelem REF:%p:%" PRIdPTR "->%" PRIdPTR ": '%s' = '%s'", this, - value, value + 1, key_str, value_str); - gpr_free(key_str); - gpr_free(value_str); - } -#endif - if (FirstRef()) { - gpr_atm_no_barrier_fetch_add(&shard->free_estimate, -1); - } -} - -static void gc_mdtab(mdtab_shard* shard) { - GPR_TIMER_SCOPE("gc_mdtab", 0); - size_t num_freed = 0; - for (size_t i = 0; i < shard->capacity; ++i) { - intptr_t freed = InternedMetadata::CleanupLinkedMetadata(&shard->elems[i]); - num_freed += freed; - shard->count -= freed; - } - gpr_atm_no_barrier_fetch_add(&shard->free_estimate, - -static_cast<intptr_t>(num_freed)); -} - -static void grow_mdtab(mdtab_shard* shard) { - GPR_TIMER_SCOPE("grow_mdtab", 0); - - size_t capacity = shard->capacity * 2; - size_t i; - InternedMetadata::BucketLink* mdtab; - InternedMetadata *md, *next; - uint32_t hash; - - mdtab = static_cast<InternedMetadata::BucketLink*>( - gpr_zalloc(sizeof(InternedMetadata::BucketLink) * capacity)); - - for (i = 0; i < shard->capacity; i++) { - for (md = shard->elems[i].next; md; md = next) { - size_t idx; - hash = md->hash(); - next = md->bucket_next(); - idx = TABLE_IDX(hash, capacity); - md->set_bucket_next(mdtab[idx].next); - mdtab[idx].next = md; - } - } - gpr_free(shard->elems); - shard->elems = mdtab; - shard->capacity = capacity; -} - -static void rehash_mdtab(mdtab_shard* shard) { - if (gpr_atm_no_barrier_load(&shard->free_estimate) > - static_cast<gpr_atm>(shard->capacity / 4)) { - gc_mdtab(shard); - } else { - grow_mdtab(shard); - } -} - -template <bool key_definitely_static, bool value_definitely_static = false> -static grpc_mdelem md_create_maybe_static(const grpc_slice& key, - const grpc_slice& value); -template <bool key_definitely_static> -static grpc_mdelem md_create_must_intern(const grpc_slice& key, - const grpc_slice& value, - uint32_t hash); - -template <bool key_definitely_static, bool value_definitely_static = false> -static grpc_mdelem md_create( - const grpc_slice& key, const grpc_slice& value, - grpc_mdelem_data* compatible_external_backing_store) { - // Ensure slices are, in fact, static if we claimed they were. - GPR_DEBUG_ASSERT(!key_definitely_static || - GRPC_IS_STATIC_METADATA_STRING(key)); - GPR_DEBUG_ASSERT(!value_definitely_static || - GRPC_IS_STATIC_METADATA_STRING(value)); - const bool key_is_interned = - key_definitely_static || grpc_slice_is_interned(key); - const bool value_is_interned = - value_definitely_static || grpc_slice_is_interned(value); - // External storage if either slice is not interned and the caller already - // created a backing store. If no backing store, we allocate one. - if (!key_is_interned || !value_is_interned) { - if (compatible_external_backing_store != nullptr) { - // Caller provided backing store. - return GRPC_MAKE_MDELEM(compatible_external_backing_store, - GRPC_MDELEM_STORAGE_EXTERNAL); - } else { - // We allocate backing store. - return key_definitely_static - ? GRPC_MAKE_MDELEM( - new AllocatedMetadata( - key, value, - static_cast<const AllocatedMetadata::NoRefKey*>( - nullptr)), - GRPC_MDELEM_STORAGE_ALLOCATED) - : GRPC_MAKE_MDELEM(new AllocatedMetadata(key, value), - GRPC_MDELEM_STORAGE_ALLOCATED); - } - } - return md_create_maybe_static<key_definitely_static, value_definitely_static>( - key, value); -} - -template <bool key_definitely_static, bool value_definitely_static> -static grpc_mdelem md_create_maybe_static(const grpc_slice& key, - const grpc_slice& value) { - // Ensure slices are, in fact, static if we claimed they were. - GPR_DEBUG_ASSERT(!key_definitely_static || - GRPC_IS_STATIC_METADATA_STRING(key)); - GPR_DEBUG_ASSERT(!value_definitely_static || - GRPC_IS_STATIC_METADATA_STRING(value)); - GPR_DEBUG_ASSERT(key.refcount != nullptr); - GPR_DEBUG_ASSERT(value.refcount != nullptr); - - const bool key_is_static_mdstr = - key_definitely_static || - key.refcount->GetType() == grpc_slice_refcount::Type::STATIC; - const bool value_is_static_mdstr = - value_definitely_static || - value.refcount->GetType() == grpc_slice_refcount::Type::STATIC; - - const intptr_t kidx = GRPC_STATIC_METADATA_INDEX(key); - - // Not all static slice input yields a statically stored metadata element. - if (key_is_static_mdstr && value_is_static_mdstr) { - grpc_mdelem static_elem = grpc_static_mdelem_for_static_strings( - kidx, GRPC_STATIC_METADATA_INDEX(value)); - if (!GRPC_MDISNULL(static_elem)) { - return static_elem; - } - } - - uint32_t khash = key_definitely_static - ? grpc_static_metadata_hash_values[kidx] - : grpc_slice_hash_refcounted(key); - - uint32_t hash = GRPC_MDSTR_KV_HASH(khash, grpc_slice_hash_refcounted(value)); - return md_create_must_intern<key_definitely_static>(key, value, hash); -} - -template <bool key_definitely_static> -static grpc_mdelem md_create_must_intern(const grpc_slice& key, - const grpc_slice& value, - uint32_t hash) { - // Here, we know both key and value are both at least interned, and both - // possibly static. We know that anything inside the shared interned table is - // also at least interned (and maybe static). Note that equality for a static - // and interned slice implies that they are both the same exact slice. - // The same applies to a pair of interned slices, or a pair of static slices. - // Rather than run the full equality check, we can therefore just do a pointer - // comparison of the refcounts. - InternedMetadata* md; - mdtab_shard* shard = &g_shards[SHARD_IDX(hash)]; - size_t idx; - - GPR_TIMER_SCOPE("grpc_mdelem_from_metadata_strings", 0); - - gpr_mu_lock(&shard->mu); - - idx = TABLE_IDX(hash, shard->capacity); - /* search for an existing pair */ - for (md = shard->elems[idx].next; md; md = md->bucket_next()) { - if (grpc_slice_static_interned_equal(key, md->key()) && - grpc_slice_static_interned_equal(value, md->value())) { - md->RefWithShardLocked(shard); - gpr_mu_unlock(&shard->mu); - return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED); - } - } - - /* not found: create a new pair */ - md = key_definitely_static - ? new InternedMetadata( - key, value, hash, shard->elems[idx].next, - static_cast<const InternedMetadata::NoRefKey*>(nullptr)) - : new InternedMetadata(key, value, hash, shard->elems[idx].next); - shard->elems[idx].next = md; - shard->count++; - - if (shard->count > shard->capacity * 2) { - rehash_mdtab(shard); - } - - gpr_mu_unlock(&shard->mu); - - return GRPC_MAKE_MDELEM(md, GRPC_MDELEM_STORAGE_INTERNED); -} - -grpc_mdelem grpc_mdelem_create( - const grpc_slice& key, const grpc_slice& value, - grpc_mdelem_data* compatible_external_backing_store) { - return md_create<false>(key, value, compatible_external_backing_store); -} - -grpc_mdelem grpc_mdelem_create( - const grpc_core::StaticMetadataSlice& key, const grpc_slice& value, - grpc_mdelem_data* compatible_external_backing_store) { - return md_create<true>(key, value, compatible_external_backing_store); -} - -/* Create grpc_mdelem from provided slices. We specify via template parameter - whether we know that the input key is static or not. If it is, we short - circuit various comparisons and a no-op unref. */ -template <bool key_definitely_static> -static grpc_mdelem md_from_slices(const grpc_slice& key, - const grpc_slice& value) { - // Ensure key is, in fact, static if we claimed it was. - GPR_DEBUG_ASSERT(!key_definitely_static || - GRPC_IS_STATIC_METADATA_STRING(key)); - grpc_mdelem out = md_create<key_definitely_static>(key, value, nullptr); - if (!key_definitely_static) { - grpc_slice_unref_internal(key); - } - grpc_slice_unref_internal(value); - return out; -} - -grpc_mdelem grpc_mdelem_from_slices(const grpc_slice& key, - const grpc_slice& value) { - return md_from_slices</*key_definitely_static=*/false>(key, value); -} - -grpc_mdelem grpc_mdelem_from_slices(const grpc_core::StaticMetadataSlice& key, - const grpc_slice& value) { - return md_from_slices</*key_definitely_static=*/true>(key, value); -} - -grpc_mdelem grpc_mdelem_from_slices( - const grpc_core::StaticMetadataSlice& key, - const grpc_core::StaticMetadataSlice& value) { - grpc_mdelem out = md_create_maybe_static<true, true>(key, value); - return out; -} - -grpc_mdelem grpc_mdelem_from_slices( - const grpc_core::StaticMetadataSlice& key, - const grpc_core::ManagedMemorySlice& value) { - // TODO(arjunroy): We can save the unref if md_create_maybe_static ended up - // creating a new interned metadata. But otherwise - we need this here. - grpc_mdelem out = md_create_maybe_static<true>(key, value); - grpc_slice_unref_internal(value); - return out; -} - -grpc_mdelem grpc_mdelem_from_slices( - const grpc_core::ManagedMemorySlice& key, - const grpc_core::ManagedMemorySlice& value) { - grpc_mdelem out = md_create_maybe_static<false>(key, value); - // TODO(arjunroy): We can save the unref if md_create_maybe_static ended up - // creating a new interned metadata. But otherwise - we need this here. - grpc_slice_unref_internal(key); - grpc_slice_unref_internal(value); - return out; -} - -grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_metadata* metadata) { - bool key_changed = false; - grpc_slice key_slice = - grpc_slice_maybe_static_intern(metadata->key, &key_changed); - bool value_changed = false; - grpc_slice* unref_slice = nullptr; - grpc_slice value_slice = - grpc_slice_maybe_static_intern(metadata->value, &value_changed); - // If key or value changed, but the other didn't.... AND the other is a NOP - // refcount, then we need to convert it to a slice with a refcount else we run - // the risk of leaving a dangling reference to that metadata on the heap via - // this mdelem. - if (key_changed && !value_changed && value_slice.refcount != nullptr && - value_slice.refcount->GetType() == grpc_slice_refcount::Type::NOP) { - value_slice = grpc_slice_copy(value_slice); - unref_slice = &value_slice; - value_changed = true; - } else if (!key_changed && value_changed && key_slice.refcount != nullptr && - key_slice.refcount->GetType() == grpc_slice_refcount::Type::NOP) { - key_slice = grpc_slice_copy(key_slice); - unref_slice = &key_slice; - key_changed = true; - } - auto mdelem = - grpc_mdelem_create(key_slice, value_slice, - key_changed || value_changed - ? nullptr - : reinterpret_cast<grpc_mdelem_data*>(metadata)); - if (unref_slice != nullptr) grpc_slice_unref_internal(*unref_slice); - return mdelem; -} - -static void* get_user_data(UserData* user_data, void (*destroy_func)(void*)) { - if (user_data->destroy_user_data.load(std::memory_order_acquire) == - destroy_func) { - return user_data->data.load(std::memory_order_relaxed); - } else { - return nullptr; - } -} - -void* grpc_mdelem_get_user_data(grpc_mdelem md, void (*destroy_func)(void*)) { - switch (GRPC_MDELEM_STORAGE(md)) { - case GRPC_MDELEM_STORAGE_EXTERNAL: - return nullptr; - case GRPC_MDELEM_STORAGE_STATIC: - return reinterpret_cast<void*>( - grpc_static_mdelem_user_data - [reinterpret_cast<grpc_core::StaticMetadata*>( - GRPC_MDELEM_DATA(md)) - - grpc_core::g_static_mdelem_table]); - case GRPC_MDELEM_STORAGE_ALLOCATED: { - auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md)); - return get_user_data(am->user_data(), destroy_func); - } - case GRPC_MDELEM_STORAGE_INTERNED: { - auto* im = reinterpret_cast<InternedMetadata*> GRPC_MDELEM_DATA(md); - return get_user_data(im->user_data(), destroy_func); - } - } - GPR_UNREACHABLE_CODE(return nullptr); -} - -static void* set_user_data(UserData* ud, void (*destroy_func)(void*), - void* data) { - GPR_ASSERT((data == nullptr) == (destroy_func == nullptr)); - grpc_core::ReleasableMutexLock lock(&ud->mu_user_data); - if (ud->destroy_user_data.load(std::memory_order_relaxed)) { - /* user data can only be set once */ - lock.Release(); - if (destroy_func != nullptr) { - destroy_func(data); - } - return ud->data.load(std::memory_order_relaxed); - } - ud->data.store(data, std::memory_order_relaxed); - ud->destroy_user_data.store(destroy_func, std::memory_order_release); - return data; -} - -void* grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void*), - void* data) { - switch (GRPC_MDELEM_STORAGE(md)) { - case GRPC_MDELEM_STORAGE_EXTERNAL: - destroy_func(data); - return nullptr; - case GRPC_MDELEM_STORAGE_STATIC: - destroy_func(data); - return reinterpret_cast<void*>( - grpc_static_mdelem_user_data - [reinterpret_cast<grpc_core::StaticMetadata*>( - GRPC_MDELEM_DATA(md)) - - grpc_core::g_static_mdelem_table]); - case GRPC_MDELEM_STORAGE_ALLOCATED: { - auto* am = reinterpret_cast<AllocatedMetadata*>(GRPC_MDELEM_DATA(md)); - return set_user_data(am->user_data(), destroy_func, data); - } - case GRPC_MDELEM_STORAGE_INTERNED: { - auto* im = reinterpret_cast<InternedMetadata*> GRPC_MDELEM_DATA(md); - GPR_DEBUG_ASSERT(!is_mdelem_static(md)); - return set_user_data(im->user_data(), destroy_func, data); - } - } - GPR_UNREACHABLE_CODE(return nullptr); -} - -bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b) { - if (a.payload == b.payload) return true; - if (GRPC_MDELEM_IS_INTERNED(a) && GRPC_MDELEM_IS_INTERNED(b)) return false; - if (GRPC_MDISNULL(a) || GRPC_MDISNULL(b)) return false; - return grpc_slice_eq(GRPC_MDKEY(a), GRPC_MDKEY(b)) && - grpc_slice_eq(GRPC_MDVALUE(a), GRPC_MDVALUE(b)); -} - -static void note_disposed_interned_metadata(uint32_t hash) { - mdtab_shard* shard = &g_shards[SHARD_IDX(hash)]; - gpr_atm_no_barrier_fetch_add(&shard->free_estimate, 1); -} - -void grpc_mdelem_do_unref(grpc_mdelem gmd DEBUG_ARGS) { - switch (GRPC_MDELEM_STORAGE(gmd)) { - case GRPC_MDELEM_STORAGE_EXTERNAL: - case GRPC_MDELEM_STORAGE_STATIC: - return; - case GRPC_MDELEM_STORAGE_INTERNED: { - auto* md = reinterpret_cast<InternedMetadata*> GRPC_MDELEM_DATA(gmd); - uint32_t hash = md->hash(); - if (GPR_UNLIKELY(md->Unref(FWD_DEBUG_ARGS))) { - /* once the refcount hits zero, some other thread can come along and - free md at any time: it's unsafe from this point on to access it */ - note_disposed_interned_metadata(hash); - } - break; - } - case GRPC_MDELEM_STORAGE_ALLOCATED: { - auto* md = reinterpret_cast<AllocatedMetadata*> GRPC_MDELEM_DATA(gmd); - if (GPR_UNLIKELY(md->Unref(FWD_DEBUG_ARGS))) { - delete md; - } - break; - } - } -} - -void grpc_mdelem_on_final_unref(grpc_mdelem_data_storage storage, void* ptr, - uint32_t hash DEBUG_ARGS) { -#ifndef NDEBUG - (void)file; - (void)line; -#endif - switch (storage) { - case GRPC_MDELEM_STORAGE_EXTERNAL: - case GRPC_MDELEM_STORAGE_STATIC: - return; - case GRPC_MDELEM_STORAGE_INTERNED: { - note_disposed_interned_metadata(hash); - break; - } - case GRPC_MDELEM_STORAGE_ALLOCATED: { - delete reinterpret_cast<AllocatedMetadata*>(ptr); - break; - } - } -} diff --git a/contrib/libs/grpc/src/core/lib/transport/metadata.h b/contrib/libs/grpc/src/core/lib/transport/metadata.h deleted file mode 100644 index 8812819248..0000000000 --- a/contrib/libs/grpc/src/core/lib/transport/metadata.h +++ /dev/null @@ -1,449 +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. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_METADATA_H -#define GRPC_CORE_LIB_TRANSPORT_METADATA_H - -#include <grpc/support/port_platform.h> - -#include <atomic> - -#include <grpc/grpc.h> -#include <grpc/impl/codegen/log.h> -#include <grpc/slice.h> - -#include "src/core/lib/debug/trace.h" -#include "src/core/lib/gpr/useful.h" -#include "src/core/lib/gprpp/sync.h" -#include "src/core/lib/slice/slice_utils.h" - -extern grpc_core::DebugOnlyTraceFlag grpc_trace_metadata; - -/* This file provides a mechanism for tracking metadata through the grpc stack. - It's not intended for consumption outside of the library. - - Metadata is tracked in the context of a sharded global grpc_mdctx. The - context tracks unique strings (grpc_mdstr) and pairs of strings - (grpc_mdelem). Any of these objects can be checked for equality by comparing - their pointers. These objects are reference counted. - - grpc_mdelem can additionally store a (non-NULL) user data pointer. This - pointer is intended to be used to cache semantic meaning of a metadata - element. For example, an OAuth token may cache the credentials it represents - and the time at which it expires in the mdelem user data. - - Combining this metadata cache and the hpack compression table allows us to - simply lookup complete preparsed objects quickly, incurring a few atomic - ops per metadata element on the fast path. - - grpc_mdelem instances MAY live longer than their refcount implies, and are - garbage collected periodically, meaning cached data can easily outlive a - single request. - - STATIC METADATA: in static_metadata.h we declare a set of static metadata. - These mdelems and mdstrs are available via pre-declared code generated macros - and are available to code anywhere between grpc_init() and grpc_shutdown(). - They are not refcounted, but can be passed to _ref and _unref functions - declared here - in which case those functions are effectively no-ops. */ - -/* Forward declarations */ -typedef struct grpc_mdelem grpc_mdelem; - -/* if changing this, make identical changes in: - - grpc_core::{InternedMetadata, AllocatedMetadata} - - grpc_metadata in grpc_types.h */ -typedef struct grpc_mdelem_data { - const grpc_slice key; - const grpc_slice value; - /* there is a private part to this in metadata.c */ -} grpc_mdelem_data; - -/* GRPC_MDELEM_STORAGE_* enum values that can be treated as interned always have - this bit set in their integer value */ -#define GRPC_MDELEM_STORAGE_INTERNED_BIT 1 - -/* External and static storage metadata has no refcount to ref/unref. Allocated - * and interned metadata do have a refcount. Metadata ref and unref methods use - * a switch statement on this enum to determine which behaviour to execute. - * Keeping the no-ref cases together and the ref-cases together leads to - * slightly better code generation (9 inlined instructions rather than 10). */ -typedef enum { - /* memory pointed to by grpc_mdelem::payload is owned by an external system */ - GRPC_MDELEM_STORAGE_EXTERNAL = 0, - /* memory is in the static metadata table */ - GRPC_MDELEM_STORAGE_STATIC = GRPC_MDELEM_STORAGE_INTERNED_BIT, - /* memory pointed to by grpc_mdelem::payload is allocated by the metadata - system */ - GRPC_MDELEM_STORAGE_ALLOCATED = 2, - /* memory pointed to by grpc_mdelem::payload is interned by the metadata - system */ - GRPC_MDELEM_STORAGE_INTERNED = 2 | GRPC_MDELEM_STORAGE_INTERNED_BIT, -} grpc_mdelem_data_storage; - -struct grpc_mdelem { - /* a grpc_mdelem_data* generally, with the two lower bits signalling memory - ownership as per grpc_mdelem_data_storage */ - uintptr_t payload; -}; - -#define GRPC_MDELEM_DATA(md) ((grpc_mdelem_data*)((md).payload & ~(uintptr_t)3)) -#define GRPC_MDELEM_STORAGE(md) \ - ((grpc_mdelem_data_storage)((md).payload & (uintptr_t)3)) -#ifdef __cplusplus -#define GRPC_MAKE_MDELEM(data, storage) \ - (grpc_mdelem{((uintptr_t)(data)) | ((uintptr_t)(storage))}) -#else -#define GRPC_MAKE_MDELEM(data, storage) \ - ((grpc_mdelem){((uintptr_t)(data)) | ((uintptr_t)(storage))}) -#endif -#define GRPC_MDELEM_IS_INTERNED(md) \ - ((grpc_mdelem_data_storage)((md).payload & \ - (uintptr_t)GRPC_MDELEM_STORAGE_INTERNED_BIT)) - -/* Given arbitrary input slices, create a grpc_mdelem object. The caller refs - * the input slices; we unref them. This method is always safe to call; however, - * if we know data about the slices in question (e.g. if we knew our key was - * static) we can call specializations that save on cycle count. */ -grpc_mdelem grpc_mdelem_from_slices(const grpc_slice& key, - const grpc_slice& value); - -/* Like grpc_mdelem_from_slices, but we know that key is a static slice. This - saves us a few branches and a no-op call to md_unref() for the key. */ -grpc_mdelem grpc_mdelem_from_slices(const grpc_core::StaticMetadataSlice& key, - const grpc_slice& value); - -/* Like grpc_mdelem_from_slices, but key is static and val is static. */ -grpc_mdelem grpc_mdelem_from_slices( - const grpc_core::StaticMetadataSlice& key, - const grpc_core::StaticMetadataSlice& value); - -/* Like grpc_mdelem_from_slices, but key is static and val is interned. */ -grpc_mdelem grpc_mdelem_from_slices(const grpc_core::StaticMetadataSlice& key, - const grpc_core::ManagedMemorySlice& value); - -/* Like grpc_mdelem_from_slices, but key and val are interned. */ -grpc_mdelem grpc_mdelem_from_slices(const grpc_core::ManagedMemorySlice& key, - const grpc_core::ManagedMemorySlice& value); - -/* Cheaply convert a grpc_metadata to a grpc_mdelem; may use the grpc_metadata - object as backing storage (so lifetimes should align) */ -grpc_mdelem grpc_mdelem_from_grpc_metadata(grpc_metadata* metadata); - -/* Does not unref the slices; if a new non-interned mdelem is needed, allocates - one if compatible_external_backing_store is NULL, or uses - compatible_external_backing_store if it is non-NULL (in which case it's the - users responsibility to ensure that it outlives usage) */ -grpc_mdelem grpc_mdelem_create( - const grpc_slice& key, const grpc_slice& value, - grpc_mdelem_data* compatible_external_backing_store); - -/* Like grpc_mdelem_create, but we know that key is static. */ -grpc_mdelem grpc_mdelem_create( - const grpc_core::StaticMetadataSlice& key, const grpc_slice& value, - grpc_mdelem_data* compatible_external_backing_store); - -#define GRPC_MDKEY(md) (GRPC_MDELEM_DATA(md)->key) -#define GRPC_MDVALUE(md) (GRPC_MDELEM_DATA(md)->value) - -bool grpc_mdelem_eq(grpc_mdelem a, grpc_mdelem b); -/* Often we compare metadata where we know a-priori that the second parameter is - * static, and that the keys match. This most commonly happens when processing - * metadata batch callouts in initial/trailing filters. In this case, fastpath - * grpc_mdelem_eq and remove unnecessary checks. */ -inline bool grpc_mdelem_static_value_eq(grpc_mdelem a, grpc_mdelem b_static) { - if (a.payload == b_static.payload) return true; - return grpc_slice_eq_static_interned(GRPC_MDVALUE(a), GRPC_MDVALUE(b_static)); -} -#define GRPC_MDISNULL(md) (GRPC_MDELEM_DATA(md) == NULL) - -inline bool grpc_mdelem_both_interned_eq(grpc_mdelem a_interned, - grpc_mdelem b_interned) { - GPR_DEBUG_ASSERT(GRPC_MDELEM_IS_INTERNED(a_interned) || - GRPC_MDISNULL(a_interned)); - GPR_DEBUG_ASSERT(GRPC_MDELEM_IS_INTERNED(b_interned) || - GRPC_MDISNULL(b_interned)); - return a_interned.payload == b_interned.payload; -} - -/* Mutator and accessor for grpc_mdelem user data. The destructor function - is used as a type tag and is checked during user_data fetch. */ -void* grpc_mdelem_get_user_data(grpc_mdelem md, void (*if_destroy_func)(void*)); -void* grpc_mdelem_set_user_data(grpc_mdelem md, void (*destroy_func)(void*), - void* data); - -// Defined in metadata.cc. -struct mdtab_shard; - -#ifndef NDEBUG -void grpc_mdelem_trace_ref(void* md, const grpc_slice& key, - const grpc_slice& value, intptr_t refcnt, - const char* file, int line); -void grpc_mdelem_trace_unref(void* md, const grpc_slice& key, - const grpc_slice& value, intptr_t refcnt, - const char* file, int line); -#endif -namespace grpc_core { - -typedef void (*destroy_user_data_func)(void* data); - -struct UserData { - Mutex mu_user_data; - std::atomic<destroy_user_data_func> destroy_user_data{nullptr}; - std::atomic<void*> data{nullptr}; -}; - -class StaticMetadata { - public: - StaticMetadata(const grpc_slice& key, const grpc_slice& value, uintptr_t idx) - : kv_({key, value}), hash_(0), static_idx_(idx) {} - - const grpc_mdelem_data& data() const { return kv_; } - - void HashInit(); - uint32_t hash() { return hash_; } - uintptr_t StaticIndex() { return static_idx_; } - - private: - grpc_mdelem_data kv_; - - /* private only data */ - uint32_t hash_; - uintptr_t static_idx_; -}; - -class RefcountedMdBase { - public: - RefcountedMdBase(const grpc_slice& key, const grpc_slice& value) - : key_(key), value_(value), refcnt_(1) {} - RefcountedMdBase(const grpc_slice& key, const grpc_slice& value, - uint32_t hash) - : key_(key), value_(value), refcnt_(1), hash_(hash) {} - - const grpc_slice& key() const { return key_; } - const grpc_slice& value() const { return value_; } - uint32_t hash() { return hash_; } - -#ifndef NDEBUG - void Ref(const char* file, int line) { - grpc_mdelem_trace_ref(this, key_, value_, RefValue(), file, line); - const intptr_t prior = refcnt_.fetch_add(1, std::memory_order_relaxed); - GPR_ASSERT(prior > 0); - } - bool Unref(const char* file, int line) { - grpc_mdelem_trace_unref(this, key_, value_, RefValue(), file, line); - return Unref(); - } -#endif - void Ref() { - /* we can assume the ref count is >= 1 as the application is calling - this function - meaning that no adjustment to mdtab_free is necessary, - simplifying the logic here to be just an atomic increment */ - refcnt_.fetch_add(1, std::memory_order_relaxed); - } - bool Unref() { - const intptr_t prior = refcnt_.fetch_sub(1, std::memory_order_acq_rel); - GPR_DEBUG_ASSERT(prior > 0); - return prior == 1; - } - - protected: -#ifndef NDEBUG - void TraceAtStart(const char* tag); -#endif - - intptr_t RefValue() { return refcnt_.load(std::memory_order_relaxed); } - bool AllRefsDropped() { return refcnt_.load(std::memory_order_acquire) == 0; } - bool FirstRef() { - return refcnt_.fetch_add(1, std::memory_order_relaxed) == 0; - } - - private: - /* must be byte compatible with grpc_mdelem_data */ - grpc_slice key_; - grpc_slice value_; - std::atomic<intptr_t> refcnt_{0}; - uint32_t hash_ = 0; -}; - -class InternedMetadata : public RefcountedMdBase { - public: - // TODO(arjunroy): Change to use strongly typed slices instead. - struct NoRefKey {}; - struct BucketLink { - explicit BucketLink(InternedMetadata* md) : next(md) {} - - InternedMetadata* next = nullptr; - }; - InternedMetadata(const grpc_slice& key, const grpc_slice& value, - uint32_t hash, InternedMetadata* next); - InternedMetadata(const grpc_slice& key, const grpc_slice& value, - uint32_t hash, InternedMetadata* next, const NoRefKey*); - - ~InternedMetadata(); - void RefWithShardLocked(mdtab_shard* shard); - UserData* user_data() { return &user_data_; } - InternedMetadata* bucket_next() { return link_.next; } - void set_bucket_next(InternedMetadata* md) { link_.next = md; } - - static size_t CleanupLinkedMetadata(BucketLink* head); - - private: - UserData user_data_; - BucketLink link_; -}; - -/* Shadow structure for grpc_mdelem_data for allocated elements */ -class AllocatedMetadata : public RefcountedMdBase { - public: - // TODO(arjunroy): Change to use strongly typed slices instead. - struct NoRefKey {}; - AllocatedMetadata(const grpc_slice& key, const grpc_slice& value); - AllocatedMetadata(const ManagedMemorySlice& key, - const UnmanagedMemorySlice& value); - AllocatedMetadata(const ExternallyManagedSlice& key, - const UnmanagedMemorySlice& value); - AllocatedMetadata(const grpc_slice& key, const grpc_slice& value, - const NoRefKey*); - ~AllocatedMetadata(); - - UserData* user_data() { return &user_data_; } - - private: - UserData user_data_; -}; - -} // namespace grpc_core - -#ifndef NDEBUG -#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s), __FILE__, __LINE__) -inline grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd, const char* file, - int line) { -#else // ifndef NDEBUG -#define GRPC_MDELEM_REF(s) grpc_mdelem_ref((s)) -inline grpc_mdelem grpc_mdelem_ref(grpc_mdelem gmd) { -#endif // ifndef NDEBUG - switch (GRPC_MDELEM_STORAGE(gmd)) { - case GRPC_MDELEM_STORAGE_EXTERNAL: - case GRPC_MDELEM_STORAGE_STATIC: - break; - case GRPC_MDELEM_STORAGE_INTERNED: { - auto* md = - reinterpret_cast<grpc_core::InternedMetadata*> GRPC_MDELEM_DATA(gmd); - /* use C assert to have this removed in opt builds */ -#ifndef NDEBUG - md->Ref(file, line); -#else - md->Ref(); -#endif - break; - } - case GRPC_MDELEM_STORAGE_ALLOCATED: { - auto* md = - reinterpret_cast<grpc_core::AllocatedMetadata*> GRPC_MDELEM_DATA(gmd); -#ifndef NDEBUG - md->Ref(file, line); -#else - md->Ref(); -#endif - break; - } - } - return gmd; -} - -#ifndef NDEBUG -#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s), __FILE__, __LINE__) -void grpc_mdelem_on_final_unref(grpc_mdelem_data_storage storage, void* ptr, - uint32_t hash, const char* file, int line); -inline void grpc_mdelem_unref(grpc_mdelem gmd, const char* file, int line) { -#else -#define GRPC_MDELEM_UNREF(s) grpc_mdelem_unref((s)) -void grpc_mdelem_on_final_unref(grpc_mdelem_data_storage storage, void* ptr, - uint32_t hash); -inline void grpc_mdelem_unref(grpc_mdelem gmd) { -#endif - const grpc_mdelem_data_storage storage = GRPC_MDELEM_STORAGE(gmd); - switch (storage) { - case GRPC_MDELEM_STORAGE_EXTERNAL: - case GRPC_MDELEM_STORAGE_STATIC: - return; - case GRPC_MDELEM_STORAGE_INTERNED: - case GRPC_MDELEM_STORAGE_ALLOCATED: - auto* md = - reinterpret_cast<grpc_core::RefcountedMdBase*> GRPC_MDELEM_DATA(gmd); - /* once the refcount hits zero, some other thread can come along and - free an interned md at any time: it's unsafe from this point on to - access it so we read the hash now. */ - uint32_t hash = md->hash(); -#ifndef NDEBUG - if (GPR_UNLIKELY(md->Unref(file, line))) { - grpc_mdelem_on_final_unref(storage, md, hash, file, line); -#else - if (GPR_UNLIKELY(md->Unref())) { - grpc_mdelem_on_final_unref(storage, md, hash); -#endif - } - return; - } -} - -#define GRPC_MDNULL GRPC_MAKE_MDELEM(NULL, GRPC_MDELEM_STORAGE_EXTERNAL) - -/* We add 32 bytes of padding as per RFC-7540 section 6.5.2. */ -#define GRPC_MDELEM_LENGTH(e) \ - (GRPC_SLICE_LENGTH(GRPC_MDKEY((e))) + GRPC_SLICE_LENGTH(GRPC_MDVALUE((e))) + \ - 32) - -#define GRPC_MDSTR_KV_HASH(k_hash, v_hash) \ - (::grpc_core::RotateLeft(size_t(k_hash), size_t(2)) ^ (v_hash)) - -void grpc_mdctx_global_init(void); -void grpc_mdctx_global_shutdown(); - -/* Like grpc_mdelem_from_slices, but we know that key is a static or interned - slice and value is not static or interned. This gives us an inlinable - fastpath - we know we must allocate metadata now, and that we do not need to - unref the value (rather, we just transfer the ref). We can avoid a ref since: - 1) the key slice is passed in already ref'd - 2) We're guaranteed to create a new Allocated slice, thus meaning the - ref can be considered 'transferred'.*/ -inline grpc_mdelem grpc_mdelem_from_slices( - const grpc_core::ManagedMemorySlice& key, - const grpc_core::UnmanagedMemorySlice& value) { - using grpc_core::AllocatedMetadata; - return GRPC_MAKE_MDELEM(new AllocatedMetadata(key, value), - GRPC_MDELEM_STORAGE_ALLOCATED); -} - -inline grpc_mdelem grpc_mdelem_from_slices( - const grpc_core::ExternallyManagedSlice& key, - const grpc_core::UnmanagedMemorySlice& value) { - using grpc_core::AllocatedMetadata; - return GRPC_MAKE_MDELEM(new AllocatedMetadata(key, value), - GRPC_MDELEM_STORAGE_ALLOCATED); -} - -inline grpc_mdelem grpc_mdelem_from_slices( - const grpc_core::StaticMetadataSlice& key, - const grpc_core::UnmanagedMemorySlice& value) { - using grpc_core::AllocatedMetadata; - return GRPC_MAKE_MDELEM(new AllocatedMetadata(key, value), - GRPC_MDELEM_STORAGE_ALLOCATED); -} - -#endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_H */ diff --git a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc b/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc deleted file mode 100644 index cef8a04dfb..0000000000 --- a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc +++ /dev/null @@ -1,99 +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. - * - */ - -#include <grpc/support/port_platform.h> - -#include "src/core/lib/transport/metadata_batch.h" - -#include <stdbool.h> -#include <string.h> - -#include "y_absl/container/inlined_vector.h" - -#include <grpc/support/alloc.h> -#include <grpc/support/log.h> - -#include "src/core/lib/profiling/timers.h" -#include "src/core/lib/slice/slice_internal.h" -#include "src/core/lib/slice/slice_string_helpers.h" - -void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, - const grpc_slice& value) { - grpc_mdelem old_mdelem = storage->md; - grpc_mdelem new_mdelem = grpc_mdelem_from_slices( - grpc_slice_ref_internal(GRPC_MDKEY(old_mdelem)), value); - storage->md = new_mdelem; - GRPC_MDELEM_UNREF(old_mdelem); -} - -namespace { - -class CopySink { - public: - explicit CopySink(grpc_metadata_batch* dst) : dst_(dst) {} - - void Encode(grpc_mdelem md) { - // If the mdelem is not external, take a ref. - // Otherwise, create a new copy, holding its own refs to the - // underlying slices. - if (GRPC_MDELEM_STORAGE(md) != GRPC_MDELEM_STORAGE_EXTERNAL) { - md = GRPC_MDELEM_REF(md); - } else { - md = grpc_mdelem_from_slices(grpc_slice_copy(GRPC_MDKEY(md)), - grpc_slice_copy(GRPC_MDVALUE(md))); - } - // Error unused in non-debug builds. - grpc_error_handle GRPC_UNUSED error = dst_->Append(md); - // The only way that Append() can fail is if - // there's a duplicate entry for a callout. However, that can't be - // the case here, because we would not have been allowed to create - // a source batch that had that kind of conflict. - GPR_DEBUG_ASSERT(error == GRPC_ERROR_NONE); - } - - template <class T, class V> - void Encode(T trait, V value) { - dst_->Set(trait, value); - } - - template <class T> - void Encode(T trait, const grpc_core::Slice& value) { - dst_->Set(trait, std::move(value.AsOwned())); - } - - private: - grpc_metadata_batch* dst_; -}; - -} // namespace - -void grpc_metadata_batch_copy(const grpc_metadata_batch* src, - grpc_metadata_batch* dst) { - dst->Clear(); - CopySink sink(dst); - src->Encode(&sink); -} - -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_core::StringViewFromSlice(GRPC_MDKEY(md))), - GRPC_ERROR_STR_VALUE, grpc_core::StringViewFromSlice(GRPC_MDVALUE(md))); - return out; -} diff --git a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h b/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h index 2052ba640b..5a6701efb7 100644 --- a/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h +++ b/contrib/libs/grpc/src/core/lib/transport/metadata_batch.h @@ -23,54 +23,26 @@ #include <stdbool.h> +#include <limits> + #include "y_absl/strings/match.h" #include "y_absl/strings/str_join.h" #include "y_absl/types/optional.h" #include <grpc/grpc.h> #include <grpc/slice.h> +#include <grpc/status.h> #include <grpc/support/time.h> +#include "src/core/lib/compression/compression_internal.h" #include "src/core/lib/gprpp/chunked_vector.h" #include "src/core/lib/gprpp/table.h" #include "src/core/lib/iomgr/exec_ctx.h" #include "src/core/lib/slice/slice.h" #include "src/core/lib/surface/validate_metadata.h" -#include "src/core/lib/transport/metadata.h" #include "src/core/lib/transport/parsed_metadata.h" -#include "src/core/lib/transport/static_metadata.h" #include "src/core/lib/transport/timeout_encoding.h" -typedef struct grpc_linked_mdelem { - grpc_linked_mdelem() {} - - grpc_mdelem md; - struct grpc_linked_mdelem* next = nullptr; - struct grpc_linked_mdelem* prev = nullptr; - void* reserved; -} grpc_linked_mdelem; - -typedef struct grpc_mdelem_list { - size_t count; - size_t default_count; // Number of default keys. - grpc_linked_mdelem* head; - grpc_linked_mdelem* tail; -} grpc_mdelem_list; - -struct grpc_filtered_mdelem { - grpc_error_handle error; - grpc_mdelem md; -}; -#define GRPC_FILTERED_ERROR(error) \ - { (error), GRPC_MDNULL } -#define GRPC_FILTERED_MDELEM(md) \ - { GRPC_ERROR_NONE, (md) } -#define GRPC_FILTERED_REMOVE() \ - { GRPC_ERROR_NONE, GRPC_MDNULL } - -grpc_error_handle grpc_attach_md_to_error(grpc_error_handle src, - grpc_mdelem md); - namespace grpc_core { // grpc-timeout metadata trait. @@ -81,15 +53,17 @@ namespace grpc_core { // to name this in MetadataMap, but ultimately once the transition is done we // should not need to. struct GrpcTimeoutMetadata { + static constexpr bool kRepeatable = false; using ValueType = grpc_millis; using MementoType = grpc_millis; static y_absl::string_view key() { return "grpc-timeout"; } - static MementoType ParseMemento(Slice value) { - grpc_millis timeout; - if (GPR_UNLIKELY(!grpc_http2_decode_timeout(value.c_slice(), &timeout))) { - timeout = GRPC_MILLIS_INF_FUTURE; + static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) { + auto timeout = ParseTimeout(value); + if (!timeout.has_value()) { + on_error("invalid value", value); + return GRPC_MILLIS_INF_FUTURE; } - return timeout; + return *timeout; } static ValueType MementoToValue(MementoType timeout) { if (timeout == GRPC_MILLIS_INF_FUTURE) { @@ -98,15 +72,14 @@ struct GrpcTimeoutMetadata { return ExecCtx::Get()->Now() + timeout; } static Slice Encode(ValueType x) { - char timeout[GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE]; - grpc_http2_encode_timeout(x, timeout); - return Slice::FromCopiedString(timeout); + return Timeout::FromDuration(x - ExecCtx::Get()->Now()).Encode(); } static MementoType DisplayValue(MementoType x) { return x; } }; // TE metadata trait. struct TeMetadata { + static constexpr bool kRepeatable = false; // HTTP2 says that TE can either be empty or "trailers". // Empty means this trait is not included, "trailers" means kTrailers, and // kInvalid is used to remember an invalid value. @@ -116,17 +89,19 @@ struct TeMetadata { }; using MementoType = ValueType; static y_absl::string_view key() { return "te"; } - static MementoType ParseMemento(Slice value) { + static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) { auto out = kInvalid; if (value == "trailers") { out = kTrailers; + } else { + on_error("invalid value", value); } return out; } static ValueType MementoToValue(MementoType te) { return te; } static StaticSlice Encode(ValueType x) { GPR_ASSERT(x == kTrailers); - return StaticSlice(GRPC_MDSTR_TRAILERS); + return StaticSlice::FromStaticString("trailers"); } static const char* DisplayValue(MementoType te) { switch (te) { @@ -138,10 +113,223 @@ struct TeMetadata { } }; +// content-type metadata trait. +struct ContentTypeMetadata { + static constexpr bool kRepeatable = false; + // gRPC says that content-type can be application/grpc[;something] + // Core has only ever verified the prefix. + // IF we want to start verifying more, we can expand this type. + enum ValueType { + kApplicationGrpc, + kEmpty, + kInvalid, + }; + using MementoType = ValueType; + static y_absl::string_view key() { return "content-type"; } + static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) { + auto out = kInvalid; + auto value_string = value.as_string_view(); + if (value_string == "application/grpc") { + out = kApplicationGrpc; + } else if (y_absl::StartsWith(value_string, "application/grpc;")) { + out = kApplicationGrpc; + } else if (y_absl::StartsWith(value_string, "application/grpc+")) { + out = kApplicationGrpc; + } else if (value_string.empty()) { + out = kEmpty; + } else { + on_error("invalid value", value); + } + return out; + } + static ValueType MementoToValue(MementoType content_type) { + return content_type; + } + static StaticSlice Encode(ValueType x) { + switch (x) { + case kEmpty: + return StaticSlice::FromStaticString(""); + case kApplicationGrpc: + return StaticSlice::FromStaticString("application/grpc"); + case kInvalid: + abort(); + } + GPR_UNREACHABLE_CODE( + return StaticSlice::FromStaticString("unrepresentable value")); + } + static const char* DisplayValue(MementoType content_type) { + switch (content_type) { + case ValueType::kApplicationGrpc: + return "application/grpc"; + case ValueType::kEmpty: + return ""; + default: + return "<discarded-invalid-value>"; + } + } +}; + +// scheme metadata trait. +struct HttpSchemeMetadata { + static constexpr bool kRepeatable = false; + enum ValueType { + kHttp, + kHttps, + kInvalid, + }; + using MementoType = ValueType; + static y_absl::string_view key() { return ":scheme"; } + static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) { + return Parse(value.as_string_view(), on_error); + } + static ValueType Parse(y_absl::string_view value, + MetadataParseErrorFn on_error) { + if (value == "http") { + return kHttp; + } else if (value == "https") { + return kHttps; + } + on_error("invalid value", Slice::FromCopiedBuffer(value)); + return kInvalid; + } + static ValueType MementoToValue(MementoType content_type) { + return content_type; + } + static StaticSlice Encode(ValueType x) { + switch (x) { + case kHttp: + return StaticSlice::FromStaticString("http"); + case kHttps: + return StaticSlice::FromStaticString("https"); + default: + abort(); + } + } + static const char* DisplayValue(MementoType content_type) { + switch (content_type) { + case kHttp: + return "http"; + case kHttps: + return "https"; + default: + return "<discarded-invalid-value>"; + } + } +}; + +// method metadata trait. +struct HttpMethodMetadata { + static constexpr bool kRepeatable = false; + enum ValueType { + kPost, + kPut, + kGet, + kInvalid, + }; + using MementoType = ValueType; + static y_absl::string_view key() { return ":method"; } + static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) { + auto out = kInvalid; + auto value_string = value.as_string_view(); + if (value_string == "POST") { + out = kPost; + } else if (value_string == "PUT") { + out = kPut; + } else if (value_string == "GET") { + out = kGet; + } else { + on_error("invalid value", value); + } + return out; + } + static ValueType MementoToValue(MementoType content_type) { + return content_type; + } + static StaticSlice Encode(ValueType x) { + switch (x) { + case kPost: + return StaticSlice::FromStaticString("POST"); + case kPut: + return StaticSlice::FromStaticString("PUT"); + case kGet: + return StaticSlice::FromStaticString("GET"); + default: + abort(); + } + } + static const char* DisplayValue(MementoType content_type) { + switch (content_type) { + case kPost: + return "POST"; + case kPut: + return "PUT"; + case kGet: + return "GET"; + default: + return "<discarded-invalid-value>"; + } + } +}; + +// Base type for metadata pertaining to a single compression algorithm +// (e.g., "grpc-encoding"). +struct CompressionAlgorithmBasedMetadata { + using ValueType = grpc_compression_algorithm; + using MementoType = ValueType; + static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) { + auto algorithm = ParseCompressionAlgorithm(value.as_string_view()); + if (!algorithm.has_value()) { + on_error("invalid value", value); + return GRPC_COMPRESS_NONE; + } + return *algorithm; + } + static ValueType MementoToValue(MementoType x) { return x; } + static Slice Encode(ValueType x) { + GPR_ASSERT(x != GRPC_COMPRESS_ALGORITHMS_COUNT); + return Slice::FromStaticString(CompressionAlgorithmAsString(x)); + } + static const char* DisplayValue(MementoType x) { + if (const char* p = CompressionAlgorithmAsString(x)) { + return p; + } else { + return "<discarded-invalid-value>"; + } + } +}; + +// grpc-encoding metadata trait. +struct GrpcEncodingMetadata : public CompressionAlgorithmBasedMetadata { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "grpc-encoding"; } +}; + +// grpc-internal-encoding-request metadata trait. +struct GrpcInternalEncodingRequest : public CompressionAlgorithmBasedMetadata { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "grpc-internal-encoding-request"; } +}; + +// grpc-accept-encoding metadata trait. +struct GrpcAcceptEncodingMetadata { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "grpc-accept-encoding"; } + using ValueType = CompressionAlgorithmSet; + using MementoType = ValueType; + static MementoType ParseMemento(Slice value, MetadataParseErrorFn) { + return CompressionAlgorithmSet::FromString(value.as_string_view()); + } + static ValueType MementoToValue(MementoType x) { return x; } + static Slice Encode(ValueType x) { return x.ToSlice(); } + static TString DisplayValue(MementoType x) { return x.ToString(); } +}; + struct SimpleSliceBasedMetadata { using ValueType = Slice; using MementoType = Slice; - static MementoType ParseMemento(Slice value) { return value.TakeOwned(); } + static MementoType ParseMemento(Slice value, MetadataParseErrorFn) { + return value.TakeOwned(); + } static ValueType MementoToValue(MementoType value) { return value; } static Slice Encode(const ValueType& x) { return x.Ref(); } static y_absl::string_view DisplayValue(const MementoType& value) { @@ -151,39 +339,167 @@ struct SimpleSliceBasedMetadata { // user-agent metadata trait. struct UserAgentMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; static y_absl::string_view key() { return "user-agent"; } }; // grpc-message metadata trait. struct GrpcMessageMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; static y_absl::string_view key() { return "grpc-message"; } }; // host metadata trait. struct HostMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; static y_absl::string_view key() { return "host"; } }; // x-endpoint-load-metrics-bin metadata trait. struct XEndpointLoadMetricsBinMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; static y_absl::string_view key() { return "x-endpoint-load-metrics-bin"; } }; // grpc-server-stats-bin metadata trait. struct GrpcServerStatsBinMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; static y_absl::string_view key() { return "grpc-server-stats-bin"; } }; // grpc-trace-bin metadata trait. struct GrpcTraceBinMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; static y_absl::string_view key() { return "grpc-trace-bin"; } }; // grpc-tags-bin metadata trait. struct GrpcTagsBinMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; static y_absl::string_view key() { return "grpc-tags-bin"; } }; +// :authority metadata trait. +struct HttpAuthorityMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return ":authority"; } +}; + +// :path metadata trait. +struct HttpPathMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return ":path"; } +}; + +// We separate SimpleIntBasedMetadata into two pieces: one that does not depend +// on the invalid value, and one that does. This allows the compiler to easily +// see the functions that are shared, and helps reduce code bloat here. +template <typename Int> +struct SimpleIntBasedMetadataBase { + using ValueType = Int; + using MementoType = Int; + static ValueType MementoToValue(MementoType value) { return value; } + static Slice Encode(ValueType x) { return Slice::FromInt64(x); } + static Int DisplayValue(MementoType x) { return x; } +}; + +template <typename Int, Int kInvalidValue> +struct SimpleIntBasedMetadata : public SimpleIntBasedMetadataBase<Int> { + static constexpr Int invalid_value() { return kInvalidValue; } + static Int ParseMemento(Slice value, MetadataParseErrorFn on_error) { + Int out; + if (!y_absl::SimpleAtoi(value.as_string_view(), &out)) { + on_error("not an integer", value); + out = kInvalidValue; + } + return out; + } +}; + +// grpc-status metadata trait. +struct GrpcStatusMetadata + : public SimpleIntBasedMetadata<grpc_status_code, GRPC_STATUS_UNKNOWN> { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "grpc-status"; } +}; + +// grpc-previous-rpc-attempts metadata trait. +struct GrpcPreviousRpcAttemptsMetadata + : public SimpleIntBasedMetadata<uint32_t, 0> { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "grpc-previous-rpc-attempts"; } +}; + +// grpc-retry-pushback-ms metadata trait. +struct GrpcRetryPushbackMsMetadata + : public SimpleIntBasedMetadata<grpc_millis, GRPC_MILLIS_INF_PAST> { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "grpc-retry-pushback-ms"; } +}; + +// :status metadata trait. +// TODO(ctiller): consider moving to uint16_t +struct HttpStatusMetadata : public SimpleIntBasedMetadata<uint32_t, 0> { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return ":status"; } +}; + +// "secret" metadata trait used to pass load balancing token between filters. +// This should not be exposed outside of gRPC core. +class GrpcLbClientStats; +struct GrpcLbClientStatsMetadata { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "grpclb_client_stats"; } + using ValueType = GrpcLbClientStats*; + using MementoType = ValueType; + static ValueType MementoToValue(MementoType value) { return value; } + static Slice Encode(ValueType) { abort(); } + static const char* DisplayValue(MementoType) { return "<internal-lb-stats>"; } + static MementoType ParseMemento(Slice, MetadataParseErrorFn) { + return nullptr; + } +}; + +// lb-token metadata +struct LbTokenMetadata : public SimpleSliceBasedMetadata { + static constexpr bool kRepeatable = false; + static y_absl::string_view key() { return "lb-token"; } +}; + +// lb-cost-bin metadata +struct LbCostBinMetadata { + static constexpr bool kRepeatable = true; + static y_absl::string_view key() { return "lb-cost-bin"; } + struct ValueType { + double cost; + TString name; + }; + using MementoType = ValueType; + static ValueType MementoToValue(MementoType value) { return value; } + static Slice Encode(const ValueType& x) { + auto slice = + MutableSlice::CreateUninitialized(sizeof(double) + x.name.length()); + memcpy(slice.data(), &x.cost, sizeof(double)); + memcpy(slice.data() + sizeof(double), x.name.data(), x.name.length()); + return Slice(std::move(slice)); + } + static TString DisplayValue(MementoType x) { + return y_absl::StrCat(x.name, ":", x.cost); + } + static MementoType ParseMemento(Slice value, MetadataParseErrorFn on_error) { + if (value.length() < sizeof(double)) { + on_error("too short", value); + return {0, ""}; + } + MementoType out; + memcpy(&out.cost, value.data(), sizeof(double)); + out.name = TString( + reinterpret_cast<const char*>(value.data()) + sizeof(double), + value.length() - sizeof(double)); + return out; + } +}; + namespace metadata_detail { // Helper type - maps a string name to a trait. @@ -193,7 +509,7 @@ struct NameLookup; template <typename Trait, typename... Traits> struct NameLookup<Trait, Traits...> { // Call op->Found(Trait()) if op->name == Trait::key() for some Trait in - // Traits. If not found, call op->NotFount(). + // Traits. If not found, call op->NotFound(). template <typename Op> static auto Lookup(y_absl::string_view key, Op* op) -> decltype(op->Found(Trait())) { @@ -219,9 +535,11 @@ struct NameLookup<> { template <typename ParseMementoFn, typename MementoToValueFn> struct ParseValue { template <ParseMementoFn parse_memento, MementoToValueFn memento_to_value> - static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value) - -> decltype(memento_to_value(parse_memento(std::move(*value)))) { - return memento_to_value(parse_memento(std::move(*value))); + static GPR_ATTRIBUTE_NOINLINE auto Parse(Slice* value, + MetadataParseErrorFn on_error) + -> decltype(memento_to_value(parse_memento(std::move(*value), + on_error))) { + return memento_to_value(parse_memento(std::move(*value), on_error)); } }; @@ -231,36 +549,44 @@ struct ParseValue { template <typename Container> class ParseHelper { public: - ParseHelper(Slice value, size_t transport_size) - : value_(std::move(value)), transport_size_(transport_size) {} + ParseHelper(Slice value, MetadataParseErrorFn on_error, size_t transport_size) + : value_(std::move(value)), + on_error_(on_error), + transport_size_(transport_size) {} template <typename Trait> - ParsedMetadata<Container> Found(Trait trait) { + GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> Found(Trait trait) { return ParsedMetadata<Container>( - trait, Trait::ParseMemento(std::move(value_)), transport_size_); + trait, + ParseValueToMemento<typename Trait::MementoType, Trait::ParseMemento>(), + transport_size_); } GPR_ATTRIBUTE_NOINLINE ParsedMetadata<Container> NotFound( y_absl::string_view key) { - return ParsedMetadata<Container>( - grpc_mdelem_from_slices(grpc_slice_intern(grpc_slice_from_static_buffer( - key.data(), key.size())), - value_.TakeCSlice())); + return ParsedMetadata<Container>(Slice::FromCopiedString(key), + std::move(value_)); } private: + template <typename T, T (*parse_memento)(Slice, MetadataParseErrorFn)> + GPR_ATTRIBUTE_NOINLINE T ParseValueToMemento() { + return parse_memento(std::move(value_), on_error_); + } + Slice value_; + MetadataParseErrorFn on_error_; const size_t transport_size_; }; // This is an "Op" type for NameLookup. -// Used for MetadataMap::Parse, its Found/NotFound methods turn a slice into a +// Used for MetadataMap::Append, its Found/NotFound methods turn a slice into a // value and add it to a container. template <typename Container> class AppendHelper { public: - AppendHelper(Container* container, Slice value) - : container_(container), value_(std::move(value)) {} + AppendHelper(Container* container, Slice value, MetadataParseErrorFn on_error) + : container_(container), value_(std::move(value)), on_error_(on_error) {} template <typename Trait> GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) { @@ -268,50 +594,232 @@ class AppendHelper { trait, ParseValue<decltype(Trait::ParseMemento), decltype(Trait::MementoToValue)>:: template Parse<Trait::ParseMemento, Trait::MementoToValue>( - &value_)); + &value_, on_error_)); } - void NotFound(y_absl::string_view key) { - GPR_ASSERT(GRPC_ERROR_NONE == - container_->Append(grpc_mdelem_from_slices( - grpc_slice_intern( - grpc_slice_from_static_buffer(key.data(), key.length())), - value_.TakeCSlice()))); + GPR_ATTRIBUTE_NOINLINE void NotFound(y_absl::string_view key) { + container_->AppendUnknown(key, std::move(value_)); } private: Container* const container_; Slice value_; + MetadataParseErrorFn on_error_; +}; + +// This is an "Op" type for NameLookup. +// Used for MetadataMap::Remove, its Found/NotFound methods remove a key from +// the container. +template <typename Container> +class RemoveHelper { + public: + explicit RemoveHelper(Container* container) : container_(container) {} + + template <typename Trait> + GPR_ATTRIBUTE_NOINLINE void Found(Trait trait) { + container_->Remove(trait); + } + + GPR_ATTRIBUTE_NOINLINE void NotFound(y_absl::string_view key) { + container_->RemoveUnknown(key); + } + + private: + Container* const container_; +}; + +// This is an "Op" type for NameLookup. +// Used for MetadataMap::GetStringValue, its Found/NotFound methods generated a +// string value from the container. +template <typename Container> +class GetStringValueHelper { + public: + explicit GetStringValueHelper(const Container* container, + TString* backing) + : container_(container), backing_(backing) {} + + template <typename Trait> + GPR_ATTRIBUTE_NOINLINE y_absl::enable_if_t< + Trait::kRepeatable == false && + std::is_same<Slice, typename Trait::ValueType>::value, + y_absl::optional<y_absl::string_view>> + Found(Trait) { + const auto* value = container_->get_pointer(Trait()); + if (value == nullptr) return y_absl::nullopt; + return value->as_string_view(); + } + + template <typename Trait> + GPR_ATTRIBUTE_NOINLINE y_absl::enable_if_t< + Trait::kRepeatable == true && + !std::is_same<Slice, typename Trait::ValueType>::value, + y_absl::optional<y_absl::string_view>> + Found(Trait) { + const auto* value = container_->get_pointer(Trait()); + if (value == nullptr) return y_absl::nullopt; + backing_->clear(); + for (const auto& v : *value) { + if (!backing_->empty()) backing_->push_back(','); + auto new_segment = Trait::Encode(v); + backing_->append(reinterpret_cast<const char*>(new_segment.begin()), reinterpret_cast<const char*>(new_segment.end())); + } + return *backing_; + } + + template <typename Trait> + GPR_ATTRIBUTE_NOINLINE y_absl::enable_if_t< + Trait::kRepeatable == false && + !std::is_same<Slice, typename Trait::ValueType>::value, + y_absl::optional<y_absl::string_view>> + Found(Trait) { + const auto* value = container_->get_pointer(Trait()); + if (value == nullptr) return y_absl::nullopt; + *backing_ = TString(Trait::Encode(*value).as_string_view()); + return *backing_; + } + + GPR_ATTRIBUTE_NOINLINE y_absl::optional<y_absl::string_view> NotFound( + y_absl::string_view key) { + return container_->GetStringValueUnknown(key, backing_); + } + + private: + const Container* const container_; + TString* backing_; +}; + +// Generate a strong type for metadata values per trait. +template <typename Which, typename Ignored = void> +struct Value; + +template <typename Which> +struct Value<Which, y_absl::enable_if_t<Which::kRepeatable == false, void>> { + Value() = default; + explicit Value(const typename Which::ValueType& value) : value(value) {} + explicit Value(typename Which::ValueType&& value) + : value(std::forward<typename Which::ValueType>(value)) {} + Value(const Value&) = delete; + Value& operator=(const Value&) = delete; + Value(Value&&) noexcept = default; + Value& operator=(Value&& other) noexcept { + value = std::move(other.value); + return *this; + } + template <typename Encoder> + void EncodeTo(Encoder* encoder) const { + encoder->Encode(Which(), value); + } + using StorageType = typename Which::ValueType; + GPR_NO_UNIQUE_ADDRESS StorageType value; +}; + +template <typename Which> +struct Value<Which, y_absl::enable_if_t<Which::kRepeatable == true, void>> { + Value() = default; + explicit Value(const typename Which::ValueType& value) { + this->value.push_back(value); + } + explicit Value(typename Which::ValueType&& value) { + this->value.emplace_back(std::forward<typename Which::ValueType>(value)); + } + Value(const Value&) = delete; + Value& operator=(const Value&) = delete; + Value(Value&& other) noexcept : value(std::move(other.value)) {} + Value& operator=(Value&& other) noexcept { + value = std::move(other.value); + return *this; + } + template <typename Encoder> + void EncodeTo(Encoder* encoder) const { + for (const auto& v : value) { + encoder->Encode(Which(), v); + } + } + using StorageType = y_absl::InlinedVector<typename Which::ValueType, 1>; + StorageType value; +}; + +// Encoder to copy some metadata +template <typename Output> +class CopySink { + public: + explicit CopySink(Output* dst) : dst_(dst) {} + + template <class T, class V> + void Encode(T trait, V value) { + dst_->Set(trait, value); + } + + template <class T> + void Encode(T trait, const Slice& value) { + dst_->Set(trait, std::move(value.AsOwned())); + } + + void Encode(const Slice& key, const Slice& value) { + dst_->AppendUnknown(key.as_string_view(), value.Ref()); + } + + private: + Output* dst_; }; } // namespace metadata_detail +// Helper function for encoders +// Given a metadata trait, convert the value to a slice. +template <typename Which> +y_absl::enable_if_t<std::is_same<typename Which::ValueType, Slice>::value, + const Slice&> +MetadataValueAsSlice(const Slice& slice) { + return slice; +} + +template <typename Which> +y_absl::enable_if_t<!std::is_same<typename Which::ValueType, Slice>::value, Slice> +MetadataValueAsSlice(typename Which::ValueType value) { + return Slice(Which::Encode(value)); +} + // MetadataMap encodes the mapping of metadata keys to metadata values. -// Right now the API presented is the minimal one that will allow us to -// substitute this type for grpc_metadata_batch in a relatively easy fashion. At -// that point we'll start iterating this API into something that's ergonomic -// again, whilst minimally holding the performance bar already set (and -// hopefully improving some things). -// In the meantime, we're not going to invest much time in ephemeral API -// documentation, so if you must use one of these APIs and it's not obvious -// how, reach out to ctiller. // -// MetadataMap takes a list of traits. Each of these trait objects defines -// one metadata field that is used by core, and so should have more specialized -// handling than just using the generic APIs. +// MetadataMap takes a derived class and list of traits. Each of these trait +// objects defines one metadata field that is used by core, and so should have +// more specialized handling than just using the generic APIs. +// +// MetadataMap is the backing type for some derived type via the curiously +// recursive template pattern. This is because many types consumed by +// MetadataMap require the container type to operate on, and many of those +// types are instantiated one per trait. A naive implementation without the +// Derived type would, for traits A,B,C, then instantiate for some +// T<Container, Trait>: +// - T<MetadataMap<A,B,C>, A>, +// - T<MetadataMap<A,B,C>, B>, +// - T<MetadataMap<A,B,C>, C>. +// Since these types ultimately need to be recorded in the .dynstr segment +// for dynamic linkers (if gRPC is linked as a static library) this would +// create O(N^2) bytes of symbols even in stripped libraries. To avoid this +// we use the derived type (e.g. grpc_metadata_batch right now) to capture +// the container type, and we would write T<grpc_metadata_batch, A>, etc... +// Note that now the container type uses a number of bytes that is independent +// of the number of traits, and so we return to a linear symbol table growth +// function. // // Each trait object has the following signature: // // Traits for the grpc-xyz metadata field: // struct GrpcXyzMetadata { // // The type that's stored on MetadataBatch // using ValueType = ...; +// // Can this metadata field be repeated? +// static constexpr bool kRepeatable = ...; // // The type that's stored in compression/decompression tables // using MementoType = ...; // // The string key for this metadata type (for transports that require it) // static y_absl::string_view key() { return "grpc-xyz"; } // // Parse a memento from a slice // // Takes ownership of value -// static MementoType ParseMemento(Slice value) { ... } +// // Calls fn in the case of an error that should be reported to the user +// static MementoType ParseMemento(Slice value, MementoParseErrorFn fn) { ... +// } // // Convert a memento to a value // static ValueType MementoToValue(MementoType memento) { ... } // // Convert a value to its canonical text wire format (the format that @@ -341,7 +849,7 @@ class AppendHelper { // for grpc-timeout we make the memento the timeout expressed on the wire, but // we make the value the timestamp of when the timeout will expire (i.e. the // deadline). -template <typename... Traits> +template <class Derived, typename... Traits> class MetadataMap { public: explicit MetadataMap(Arena* arena); @@ -350,7 +858,10 @@ class MetadataMap { MetadataMap(const MetadataMap&) = delete; MetadataMap& operator=(const MetadataMap&) = delete; MetadataMap(MetadataMap&&) noexcept; - MetadataMap& operator=(MetadataMap&&) noexcept; + // We never create MetadataMap directly, instead we create Derived, but we + // want to be able to move it without redeclaring this. + // NOLINTNEXTLINE(misc-unconventional-assign-operator) + Derived& operator=(MetadataMap&&) noexcept; // Encode this metadata map into some encoder. // For each field that is set in the MetadataMap, call @@ -367,17 +878,23 @@ class MetadataMap { // transitions. template <typename Encoder> void Encode(Encoder* encoder) const { - for (auto* l = list_.head; l; l = l->next) { - encoder->Encode(l->md); - } table_.ForEach(EncodeWrapper<Encoder>{encoder}); + for (const auto& unk : unknown_) { + encoder->Encode(unk.first, unk.second); + } } + // Similar to Encode, but targeted at logging: for each metadatum, + // call f(key, value) as y_absl::string_views. + void Log(y_absl::FunctionRef<void(y_absl::string_view, y_absl::string_view)> log_fn) + const; + // Get the pointer to the value of some known metadata. // Returns nullptr if the metadata is not present. // Causes a compilation error if Which is not an element of Traits. template <typename Which> - const typename Which::ValueType* get_pointer(Which) const { + const typename metadata_detail::Value<Which>::StorageType* get_pointer( + Which) const { if (auto* p = table_.template get<Value<Which>>()) return &p->value; return nullptr; } @@ -386,11 +903,20 @@ class MetadataMap { // Returns nullptr if the metadata is not present. // Causes a compilation error if Which is not an element of Traits. template <typename Which> - typename Which::ValueType* get_pointer(Which) { + typename metadata_detail::Value<Which>::StorageType* get_pointer(Which) { if (auto* p = table_.template get<Value<Which>>()) return &p->value; return nullptr; } + // Get the pointer to the value of some known metadata. + // Adds the default value for the metadata is not present. + // Causes a compilation error if Which is not an element of Traits. + template <typename Which> + typename metadata_detail::Value<Which>::StorageType* GetOrCreatePointer( + Which) { + return &table_.template get_or_create<Value<Which>>()->value; + } + // Get the value of some known metadata. // Returns nullopt if the metadata is not present. // Causes a compilation error if Which is not an element of Traits. @@ -403,9 +929,14 @@ class MetadataMap { // Set the value of some known metadata. // Returns a pointer to the new value. template <typename Which, typename... Args> - typename Which::ValueType* Set(Which, Args&&... args) { - return &table_.template set<Value<Which>>(std::forward<Args>(args)...) - ->value; + y_absl::enable_if_t<Which::kRepeatable == false, void> Set(Which, + Args&&... args) { + table_.template set<Value<Which>>(std::forward<Args>(args)...); + } + template <typename Which, typename... Args> + y_absl::enable_if_t<Which::kRepeatable == true, void> Set(Which, + Args&&... args) { + GetOrCreatePointer(Which())->emplace_back(std::forward<Args>(args)...); } // Remove a specific piece of known metadata. @@ -414,13 +945,31 @@ class MetadataMap { table_.template clear<Value<Which>>(); } + // Remove some metadata by name + void Remove(y_absl::string_view key) { + metadata_detail::RemoveHelper<Derived> helper(static_cast<Derived*>(this)); + metadata_detail::NameLookup<Traits...>::Lookup(key, &helper); + } + + void Remove(const char* key) { Remove(y_absl::string_view(key)); } + + // Retrieve some metadata by name + y_absl::optional<y_absl::string_view> GetStringValue(y_absl::string_view name, + TString* buffer) const { + metadata_detail::GetStringValueHelper<Derived> helper( + static_cast<const Derived*>(this), buffer); + return metadata_detail::NameLookup<Traits...>::Lookup(name, &helper); + } + // Extract a piece of known metadata. // Returns nullopt if the metadata was not present, or the value if it was. // The same as: // auto value = m.get(T()); // m.Remove(T()); template <typename Which> - y_absl::optional<typename Which::ValueType> Take(Which which) { + y_absl::enable_if_t<Which::kRepeatable == false, + y_absl::optional<typename Which::ValueType>> + Take(Which which) { if (auto* p = get_pointer(which)) { y_absl::optional<typename Which::ValueType> value(std::move(*p)); Remove(which); @@ -429,150 +978,61 @@ class MetadataMap { return {}; } + // Extract repeated known metadata. + // Returns an empty vector if the metadata was not present. + template <typename Which> + y_absl::enable_if_t<Which::kRepeatable == true, + typename metadata_detail::Value<Which>::StorageType> + Take(Which which) { + if (auto* p = get_pointer(which)) { + typename Value<Which>::StorageType value = std::move(*p); + Remove(which); + return value; + } + return {}; + } + // Parse metadata from a key/value pair, and return an object representing // that result. // TODO(ctiller): key should probably be an y_absl::string_view. // Once we don't care about interning anymore, make that change! - static ParsedMetadata<MetadataMap> Parse(y_absl::string_view key, Slice value, - uint32_t transport_size) { - metadata_detail::ParseHelper<MetadataMap> helper(value.TakeOwned(), - transport_size); + static ParsedMetadata<Derived> Parse(y_absl::string_view key, Slice value, + uint32_t transport_size, + MetadataParseErrorFn on_error) { + metadata_detail::ParseHelper<Derived> helper(value.TakeOwned(), on_error, + transport_size); return metadata_detail::NameLookup<Traits...>::Lookup(key, &helper); } // Set a value from a parsed metadata object. - GRPC_MUST_USE_RESULT grpc_error_handle - Set(const ParsedMetadata<MetadataMap>& m) { - return m.SetOnContainer(this); + void Set(const ParsedMetadata<Derived>& m) { + m.SetOnContainer(static_cast<Derived*>(this)); } // Append a key/value pair - takes ownership of value - void Append(y_absl::string_view key, Slice value) { - metadata_detail::AppendHelper<MetadataMap> helper(this, value.TakeOwned()); + void Append(y_absl::string_view key, Slice value, + MetadataParseErrorFn on_error) { + metadata_detail::AppendHelper<Derived> helper(static_cast<Derived*>(this), + value.TakeOwned(), on_error); metadata_detail::NameLookup<Traits...>::Lookup(key, &helper); } - // - // All APIs below this point are subject to change. - // - - template <typename F> - void ForEach(F f) const { - for (auto* l = list_.head; l; l = l->next) { - f(l->md); - } - } - - template <typename F> - grpc_error_handle Filter(F f, const char* composite_error_string) { - grpc_linked_mdelem* l = list_.head; - grpc_error_handle error = GRPC_ERROR_NONE; - auto add_error = [&](grpc_error_handle new_error) { - if (new_error == GRPC_ERROR_NONE) return; - if (error == GRPC_ERROR_NONE) { - error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(composite_error_string); - } - error = grpc_error_add_child(error, new_error); - }; - while (l) { - grpc_linked_mdelem* next = l->next; - grpc_filtered_mdelem new_mdelem = f(l->md); - add_error(new_mdelem.error); - if (GRPC_MDISNULL(new_mdelem.md)) { - Remove(l); - } else if (new_mdelem.md.payload != l->md.payload) { - add_error(Substitute(l, new_mdelem.md)); - } - l = next; - } - return error; - } - - GRPC_MUST_USE_RESULT grpc_error_handle Append(grpc_mdelem md) { - return AddTail(elem_storage_.EmplaceBack(), md); - } - - GRPC_MUST_USE_RESULT grpc_error_handle ReplaceOrAppend(grpc_slice key, - grpc_slice value) { - if (ReplaceIfExists(key, value)) return GRPC_ERROR_NONE; - return Append(grpc_mdelem_from_slices(key, value)); - } - - // Set key to value if it exists and return true, otherwise return false. - // If this function returns true, it takes ownership of key and value. - // If this function returns false, it does not take ownership of key nor - // value. - bool ReplaceIfExists(grpc_slice key, grpc_slice value); - void Clear(); - bool empty() const { return count() == 0; } - - size_t count() const { return list_.count + table_.count(); } - size_t non_deadline_count() const { return list_.count; } - size_t default_count() const { return list_.default_count; } - size_t TransportSize() const; - - void Remove(grpc_linked_mdelem* storage); - void Remove(grpc_metadata_batch_callouts_index idx); - - y_absl::optional<grpc_slice> Remove(grpc_slice key); - - grpc_error_handle Substitute(grpc_linked_mdelem* storage, - grpc_mdelem new_mdelem); - - y_absl::optional<y_absl::string_view> GetValue( - y_absl::string_view target_key, TString* concatenated_value) const; - - grpc_error_handle LinkHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; - grpc_error_handle LinkHead(grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) - GRPC_MUST_USE_RESULT; - grpc_error_handle LinkTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; - grpc_error_handle LinkTail(grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) - GRPC_MUST_USE_RESULT; - - grpc_error_handle AddHead(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; - grpc_error_handle AddHead(grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; - grpc_error_handle AddTail(grpc_linked_mdelem* storage) GRPC_MUST_USE_RESULT; - grpc_error_handle AddTail(grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) GRPC_MUST_USE_RESULT; - - void CopyFrom(MetadataMap* src, grpc_linked_mdelem* storage); - -#ifndef NDEBUG - void AssertOk(); -#else - void AssertOk() {} -#endif - - // TODO(ctiller): the following explicit deadline handling methods are - // deprecated in terms of the traits based APIs. - grpc_millis deadline() const { - return get(GrpcTimeoutMetadata()).value_or(GRPC_MILLIS_INF_FUTURE); - }; - - const grpc_metadata_batch_callouts* legacy_index() const { return &idx_; } + Derived Copy() const; + bool empty() const { return table_.empty() && unknown_.empty(); } + size_t count() const { return table_.count() + unknown_.size(); } private: - // Generate a strong type for metadata values per trait. + friend class metadata_detail::AppendHelper<Derived>; + friend class metadata_detail::GetStringValueHelper<Derived>; + friend class metadata_detail::RemoveHelper<Derived>; + friend class metadata_detail::CopySink<Derived>; + friend class ParsedMetadata<Derived>; + template <typename Which> - struct Value { - Value() = default; - explicit Value(const typename Which::ValueType& value) : value(value) {} - explicit Value(typename Which::ValueType&& value) - : value(std::forward<typename Which::ValueType>(value)) {} - Value(const Value&) = delete; - Value& operator=(const Value&) = delete; - Value(Value&&) noexcept = default; - Value& operator=(Value&& other) noexcept { - value = std::move(other.value); - return *this; - } - GPR_NO_UNIQUE_ADDRESS typename Which::ValueType value; - }; + using Value = metadata_detail::Value<Which>; + // Callable for the ForEach in Encode() -- for each value, call the // appropriate encoder method. template <typename Encoder> @@ -580,551 +1040,173 @@ class MetadataMap { Encoder* encoder; template <typename Which> void operator()(const Value<Which>& which) { - encoder->Encode(Which(), which.value); + which.EncodeTo(encoder); } }; - void AssertValidCallouts(); - grpc_error_handle LinkCallout(grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) - GRPC_MUST_USE_RESULT; - grpc_error_handle MaybeLinkCallout(grpc_linked_mdelem* storage) - GRPC_MUST_USE_RESULT; - void MaybeUnlinkCallout(grpc_linked_mdelem* storage); - - static void assert_valid_list(grpc_mdelem_list* list) { -#ifndef NDEBUG - grpc_linked_mdelem* l; - - GPR_ASSERT((list->head == nullptr) == (list->tail == nullptr)); - if (!list->head) return; - GPR_ASSERT(list->head->prev == nullptr); - GPR_ASSERT(list->tail->next == nullptr); - GPR_ASSERT((list->head == list->tail) == (list->head->next == nullptr)); - - size_t verified_count = 0; - for (l = list->head; l; l = l->next) { - GPR_ASSERT(!GRPC_MDISNULL(l->md)); - GPR_ASSERT((l->prev == nullptr) == (l == list->head)); - GPR_ASSERT((l->next == nullptr) == (l == list->tail)); - if (l->next) GPR_ASSERT(l->next->prev == l); - if (l->prev) GPR_ASSERT(l->prev->next == l); - verified_count++; + // Encoder to compute TransportSize + class TransportSizeEncoder { + public: + void Encode(const Slice& key, const Slice& value) { + size_ += key.length() + value.length() + 32; } - GPR_ASSERT(list->count == verified_count); -#else - // Avoid unused-parameter warning for debug-only parameter - (void)list; -#endif /* NDEBUG */ - } - - 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 void link_head(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { - assert_valid_list(list); - GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md)); - storage->prev = nullptr; - storage->next = list->head; - storage->reserved = nullptr; - if (list->head != nullptr) { - list->head->prev = storage; - } else { - list->tail = storage; - } - list->head = storage; - list->count++; - assert_valid_list(list); - } - - static void link_tail(grpc_mdelem_list* list, grpc_linked_mdelem* storage) { - assert_valid_list(list); - GPR_DEBUG_ASSERT(!GRPC_MDISNULL(storage->md)); - storage->prev = list->tail; - storage->next = nullptr; - storage->reserved = nullptr; - if (list->tail != nullptr) { - list->tail->next = storage; - } else { - list->head = storage; - } - list->tail = storage; - list->count++; - assert_valid_list(list); - } - static void unlink_storage(grpc_mdelem_list* list, - grpc_linked_mdelem* storage) { - assert_valid_list(list); - if (storage->prev != nullptr) { - storage->prev->next = storage->next; - } else { - list->head = storage->next; - } - if (storage->next != nullptr) { - storage->next->prev = storage->prev; - } else { - list->tail = storage->prev; + template <typename Which> + void Encode(Which, const typename Which::ValueType& value) { + Add(Which(), value); } - list->count--; - assert_valid_list(list); - } - // Table of known metadata types. - Table<Value<Traits>...> table_; - /** Metadata elements in this batch */ - grpc_mdelem_list list_; - grpc_metadata_batch_callouts idx_; - // Backing store for added metadata. - ChunkedVector<grpc_linked_mdelem, 10> elem_storage_; -}; - -template <typename... Traits> -void MetadataMap<Traits...>::AssertValidCallouts() { -#ifndef NDEBUG - for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) { - grpc_slice key_interned = grpc_slice_intern(GRPC_MDKEY(l->md)); - grpc_metadata_batch_callouts_index callout_idx = - GRPC_BATCH_INDEX_OF(key_interned); - if (callout_idx != GRPC_BATCH_CALLOUTS_COUNT) { - GPR_ASSERT(idx_.array[callout_idx] == l); + void Encode(ContentTypeMetadata, + const typename ContentTypeMetadata::ValueType& value) { + if (value == ContentTypeMetadata::kInvalid) return; + Add(ContentTypeMetadata(), value); } - grpc_slice_unref_internal(key_interned); - } -#endif -} - -#ifndef NDEBUG -template <typename... Traits> -void MetadataMap<Traits...>::AssertOk() { - assert_valid_list(&list_); -} -#endif /* NDEBUG */ - -template <typename... Traits> -MetadataMap<Traits...>::MetadataMap(Arena* arena) : elem_storage_(arena) { - memset(&list_, 0, sizeof(list_)); - memset(&idx_, 0, sizeof(idx_)); -} - -template <typename... Traits> -MetadataMap<Traits...>::MetadataMap(MetadataMap&& other) noexcept - : table_(std::move(other.table_)) { - list_ = other.list_; - idx_ = other.idx_; - memset(&other.list_, 0, sizeof(list_)); - memset(&other.idx_, 0, sizeof(idx_)); -} - -template <typename... Traits> -MetadataMap<Traits...>& MetadataMap<Traits...>::operator=( - MetadataMap&& other) noexcept { - Clear(); - table_ = std::move(other.table_); - list_ = other.list_; - idx_ = other.idx_; - memset(&other.list_, 0, sizeof(list_)); - memset(&other.idx_, 0, sizeof(idx_)); - return *this; -} -template <typename... Traits> -MetadataMap<Traits...>::~MetadataMap() { - AssertValidCallouts(); - for (auto* l = list_.head; l; l = l->next) { - GRPC_MDELEM_UNREF(l->md); - } -} + size_t size() const { return size_; } -template <typename... Traits> -y_absl::optional<grpc_slice> MetadataMap<Traits...>::Remove(grpc_slice key) { - for (auto* l = list_.head; l; l = l->next) { - if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) { - auto out = grpc_slice_ref_internal(GRPC_MDVALUE(l->md)); - Remove(l); - return out; + private: + template <typename Which> + void Add(Which, const typename Which::ValueType& value) { + size_ += Which::key().length() + Which::Encode(value).length() + 32; } - } - return {}; -} - -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::LinkCallout( - grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { - AssertValidCallouts(); - GPR_DEBUG_ASSERT(idx >= 0 && idx < GRPC_BATCH_CALLOUTS_COUNT); - if (GPR_LIKELY(idx_.array[idx] == nullptr)) { - ++list_.default_count; - idx_.array[idx] = storage; - AssertValidCallouts(); - return GRPC_ERROR_NONE; - } - AssertValidCallouts(); - return error_with_md(storage->md); -} - -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::MaybeLinkCallout( - grpc_linked_mdelem* storage) { - grpc_metadata_batch_callouts_index idx = - GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); - if (idx == GRPC_BATCH_CALLOUTS_COUNT) { - return GRPC_ERROR_NONE; - } - return LinkCallout(storage, idx); -} - -template <typename... Traits> -void MetadataMap<Traits...>::MaybeUnlinkCallout(grpc_linked_mdelem* storage) { - grpc_metadata_batch_callouts_index idx = - GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)); - if (idx == GRPC_BATCH_CALLOUTS_COUNT) { - return; - } - --list_.default_count; - GPR_DEBUG_ASSERT(idx_.array[idx] != nullptr); - idx_.array[idx] = nullptr; -} - -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::AddHead(grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { - GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); - storage->md = elem_to_add; - return LinkHead(storage); -} - -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::LinkHead( - grpc_linked_mdelem* storage) { - AssertValidCallouts(); - grpc_error_handle err = MaybeLinkCallout(storage); - if (err != GRPC_ERROR_NONE) { - AssertValidCallouts(); - return err; - } - link_head(&list_, storage); - AssertValidCallouts(); - return GRPC_ERROR_NONE; -} - -// 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? -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::LinkHead( - grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { - GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx); - AssertValidCallouts(); - grpc_error_handle err = LinkCallout(storage, idx); - if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) { - AssertValidCallouts(); - return err; - } - link_head(&list_, storage); - AssertValidCallouts(); - return GRPC_ERROR_NONE; -} -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::AddTail(grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { - GPR_DEBUG_ASSERT(!GRPC_MDISNULL(elem_to_add)); - storage->md = elem_to_add; - return LinkTail(storage); -} - -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::LinkTail( - grpc_linked_mdelem* storage) { - AssertValidCallouts(); - grpc_error_handle err = MaybeLinkCallout(storage); - if (err != GRPC_ERROR_NONE) { - AssertValidCallouts(); - return err; - } - link_tail(&list_, storage); - AssertValidCallouts(); - return GRPC_ERROR_NONE; -} + uint32_t size_ = 0; + }; -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::LinkTail( - grpc_linked_mdelem* storage, grpc_metadata_batch_callouts_index idx) { - GPR_DEBUG_ASSERT(GRPC_BATCH_INDEX_OF(GRPC_MDKEY(storage->md)) == idx); - AssertValidCallouts(); - grpc_error_handle err = LinkCallout(storage, idx); - if (GPR_UNLIKELY(err != GRPC_ERROR_NONE)) { - AssertValidCallouts(); - return err; - } - link_tail(&list_, storage); - AssertValidCallouts(); - return GRPC_ERROR_NONE; -} + // Encoder to log some metadata + class LogEncoder { + public: + explicit LogEncoder( + y_absl::FunctionRef<void(y_absl::string_view, y_absl::string_view)> log_fn) + : log_fn_(log_fn) {} -template <typename... Traits> -void MetadataMap<Traits...>::Remove(grpc_linked_mdelem* storage) { - AssertValidCallouts(); - MaybeUnlinkCallout(storage); - unlink_storage(&list_, storage); - GRPC_MDELEM_UNREF(storage->md); - AssertValidCallouts(); -} + template <typename Which> + void Encode(Which, const typename Which::ValueType& value) { + log_fn_(Which::key(), y_absl::StrCat(Which::DisplayValue(value))); + } -template <typename... Traits> -void MetadataMap<Traits...>::Remove(grpc_metadata_batch_callouts_index idx) { - AssertValidCallouts(); - if (idx_.array[idx] == nullptr) return; - --list_.default_count; - unlink_storage(&list_, idx_.array[idx]); - GRPC_MDELEM_UNREF(idx_.array[idx]->md); - idx_.array[idx] = nullptr; - AssertValidCallouts(); -} + void Encode(const Slice& key, const Slice& value) { + log_fn_(key.as_string_view(), value.as_string_view()); + } -template <typename... Traits> -y_absl::optional<y_absl::string_view> MetadataMap<Traits...>::GetValue( - y_absl::string_view target_key, TString* concatenated_value) const { - // Find all values for the specified key. - y_absl::InlinedVector<y_absl::string_view, 1> values; - for (grpc_linked_mdelem* md = list_.head; md != nullptr; md = md->next) { - y_absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md)); - y_absl::string_view value = StringViewFromSlice(GRPC_MDVALUE(md->md)); - if (target_key == key) values.push_back(value); - } - // If none found, no match. - if (values.empty()) return y_absl::nullopt; - // If exactly one found, return it as-is. - if (values.size() == 1) return values.front(); - // If more than one found, concatenate the values, using - // *concatenated_values as a temporary holding place for the - // concatenated string. - *concatenated_value = y_absl::StrJoin(values, ","); - return *concatenated_value; -} + private: + y_absl::FunctionRef<void(y_absl::string_view, y_absl::string_view)> log_fn_; + }; -template <typename... Traits> -grpc_error_handle MetadataMap<Traits...>::Substitute( - grpc_linked_mdelem* storage, grpc_mdelem new_mdelem) { - AssertValidCallouts(); - 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))) { - MaybeUnlinkCallout(storage); - storage->md = new_mdelem; - error = MaybeLinkCallout(storage); - if (error != GRPC_ERROR_NONE) { - unlink_storage(&list_, storage); - GRPC_MDELEM_UNREF(storage->md); - } - } else { - storage->md = new_mdelem; + void AppendUnknown(y_absl::string_view key, Slice value) { + unknown_.EmplaceBack(Slice::FromCopiedString(key), value.Ref()); } - GRPC_MDELEM_UNREF(old_mdelem); - AssertValidCallouts(); - return error; -} -template <typename... Traits> -void MetadataMap<Traits...>::Clear() { - // TODO(ctiller): implement this without deconstructing/reconstructing once - // linked_mdelem is no longer a thing. - auto* arena = elem_storage_.arena(); - this->~MetadataMap(); - new (this) MetadataMap(arena); -} - -template <typename... Traits> -size_t MetadataMap<Traits...>::TransportSize() const { - size_t size = 0; - for (grpc_linked_mdelem* elem = list_.head; elem != nullptr; - elem = elem->next) { - size += GRPC_MDELEM_LENGTH(elem->md); + void RemoveUnknown(y_absl::string_view key) { + unknown_.SetEnd(std::remove_if(unknown_.begin(), unknown_.end(), + [key](const std::pair<Slice, Slice>& p) { + return p.first.as_string_view() == key; + })); } - return size; -} -template <typename... Traits> -bool MetadataMap<Traits...>::ReplaceIfExists(grpc_slice key, grpc_slice value) { - AssertValidCallouts(); - for (grpc_linked_mdelem* l = list_.head; l != nullptr; l = l->next) { - if (grpc_slice_eq(GRPC_MDKEY(l->md), key)) { - auto new_mdelem = grpc_mdelem_from_slices(key, value); - GRPC_MDELEM_UNREF(l->md); - l->md = new_mdelem; - AssertValidCallouts(); - return true; + y_absl::optional<y_absl::string_view> GetStringValueUnknown( + y_absl::string_view key, TString* backing) const { + y_absl::optional<y_absl::string_view> out; + for (const auto& p : unknown_) { + if (p.first.as_string_view() == key) { + if (!out.has_value()) { + out = p.second.as_string_view(); + } else { + out = *backing = y_absl::StrCat(*out, ",", p.second.as_string_view()); + } + } } + return out; } - AssertValidCallouts(); - return false; -} - -} // namespace grpc_core - -using grpc_metadata_batch = grpc_core::MetadataMap< - grpc_core::GrpcTimeoutMetadata, grpc_core::TeMetadata, - grpc_core::UserAgentMetadata, grpc_core::GrpcMessageMetadata, - grpc_core::HostMetadata, grpc_core::XEndpointLoadMetricsBinMetadata, - grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata, - grpc_core::GrpcTagsBinMetadata>; - -inline void grpc_metadata_batch_clear(grpc_metadata_batch* batch) { - batch->Clear(); -} -inline bool grpc_metadata_batch_is_empty(grpc_metadata_batch* batch) { - return batch->empty(); -} - -/* Returns the transport size of the batch. */ -inline size_t grpc_metadata_batch_size(grpc_metadata_batch* batch) { - return batch->TransportSize(); -} -/** Remove \a storage from the batch, unreffing the mdelem contained */ -inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch, - grpc_linked_mdelem* storage) { - batch->Remove(storage); -} -inline void grpc_metadata_batch_remove(grpc_metadata_batch* batch, - grpc_metadata_batch_callouts_index idx) { - batch->Remove(idx); -} - -/** Substitute a new mdelem for an old value */ -inline grpc_error_handle grpc_metadata_batch_substitute( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_mdelem new_mdelem) { - return batch->Substitute(storage, new_mdelem); -} - -void grpc_metadata_batch_set_value(grpc_linked_mdelem* storage, - const grpc_slice& value); - -/** Returns metadata value(s) for the specified key. - If the key is not present in the batch, returns y_absl::nullopt. - If the key is present exactly once in the batch, returns a string_view of - that value. - If the key is present more than once in the batch, constructs a - comma-concatenated string of all values in concatenated_value and returns a - string_view of that string. */ -inline y_absl::optional<y_absl::string_view> grpc_metadata_batch_get_value( - grpc_metadata_batch* batch, y_absl::string_view target_key, - TString* concatenated_value) { - return batch->GetValue(target_key, concatenated_value); -} - -/** Add \a storage to the beginning of \a batch. storage->md is - assumed to be valid. - \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. */ -inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage) { - return batch->LinkHead(storage); -} + // Table of known metadata types. + Table<Value<Traits>...> table_; + // Backing store for added metadata. + ChunkedVector<std::pair<Slice, Slice>, 10> unknown_; +}; -inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_head( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) { - return batch->LinkHead(storage, idx); +// Ok/not-ok check for metadata maps that contain GrpcStatusMetadata, so that +// they can be used as result types for TrySeq. +template <typename Derived, typename... Args> +inline bool IsStatusOk(const MetadataMap<Derived, Args...>& m) { + return m.get(GrpcStatusMetadata()).value_or(GRPC_STATUS_UNKNOWN) == + GRPC_STATUS_OK; } -/** Add \a storage to the end of \a batch. storage->md is - assumed to be valid. - \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. */ -inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage) { - return batch->LinkTail(storage); -} +template <typename Derived, typename... Traits> +MetadataMap<Derived, Traits...>::MetadataMap(Arena* arena) : unknown_(arena) {} -inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_link_tail( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_metadata_batch_callouts_index idx) { - return batch->LinkTail(storage, idx); -} +template <typename Derived, typename... Traits> +MetadataMap<Derived, Traits...>::MetadataMap(MetadataMap&& other) noexcept + : table_(std::move(other.table_)), unknown_(std::move(other.unknown_)) {} -/** Add \a elem_to_add as the first element in \a batch, using - \a storage as backing storage for the linked list element. - \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. - Takes ownership of \a elem_to_add */ -inline grpc_error_handle grpc_metadata_batch_add_head( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { - return batch->AddHead(storage, elem_to_add); +// We never create MetadataMap directly, instead we create Derived, but we want +// to be able to move it without redeclaring this. +// NOLINTNEXTLINE(misc-unconventional-assign-operator) +template <typename Derived, typename... Traits> +Derived& MetadataMap<Derived, Traits...>::operator=( + MetadataMap&& other) noexcept { + table_ = std::move(other.table_); + unknown_ = std::move(other.unknown_); + return static_cast<Derived&>(*this); } -// TODO(arjunroy, roth): Remove redundant methods. -// add/link_head/tail are almost identical. -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); -} +template <typename Derived, typename... Traits> +MetadataMap<Derived, Traits...>::~MetadataMap() = default; -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)); - storage->md = elem_to_add; - return grpc_metadata_batch_add_head(batch, storage, idx); +template <typename Derived, typename... Traits> +void MetadataMap<Derived, Traits...>::Clear() { + table_.ClearAll(); + unknown_.Clear(); } -/** Add \a elem_to_add as the last element in \a batch, using - \a storage as backing storage for the linked list element. - \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. - Takes ownership of \a elem_to_add */ -inline GRPC_MUST_USE_RESULT grpc_error_handle grpc_metadata_batch_add_tail( - grpc_metadata_batch* batch, grpc_linked_mdelem* storage, - grpc_mdelem elem_to_add) { - return batch->AddTail(storage, elem_to_add); +template <typename Derived, typename... Traits> +size_t MetadataMap<Derived, Traits...>::TransportSize() const { + TransportSizeEncoder enc; + Encode(&enc); + return enc.size(); } -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); +template <typename Derived, typename... Traits> +Derived MetadataMap<Derived, Traits...>::Copy() const { + Derived out(unknown_.arena()); + metadata_detail::CopySink<Derived> sink(&out); + Encode(&sink); + return out; } -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)); - storage->md = elem_to_add; - return grpc_metadata_batch_add_tail(batch, storage, idx); +template <typename Derived, typename... Traits> +void MetadataMap<Derived, Traits...>::Log( + y_absl::FunctionRef<void(y_absl::string_view, y_absl::string_view)> log_fn) + const { + LogEncoder enc(log_fn); + Encode(&enc); } -typedef grpc_filtered_mdelem (*grpc_metadata_batch_filter_func)( - void* user_data, grpc_mdelem elem); -inline GRPC_MUST_USE_RESULT 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) { - return batch->Filter([=](grpc_mdelem elem) { return func(user_data, elem); }, - composite_error_string); -} +} // namespace grpc_core -inline void grpc_metadata_batch_assert_ok(grpc_metadata_batch* batch) { - batch->AssertOk(); -} +struct grpc_metadata_batch; + +using grpc_metadata_batch_base = grpc_core::MetadataMap< + grpc_metadata_batch, + // Colon prefixed headers first + grpc_core::HttpPathMetadata, grpc_core::HttpAuthorityMetadata, + grpc_core::HttpMethodMetadata, grpc_core::HttpStatusMetadata, + grpc_core::HttpSchemeMetadata, + // Non-colon prefixed headers begin here + grpc_core::ContentTypeMetadata, grpc_core::TeMetadata, + grpc_core::GrpcEncodingMetadata, grpc_core::GrpcInternalEncodingRequest, + grpc_core::GrpcAcceptEncodingMetadata, grpc_core::GrpcStatusMetadata, + grpc_core::GrpcTimeoutMetadata, grpc_core::GrpcPreviousRpcAttemptsMetadata, + grpc_core::GrpcRetryPushbackMsMetadata, grpc_core::UserAgentMetadata, + grpc_core::GrpcMessageMetadata, grpc_core::HostMetadata, + grpc_core::XEndpointLoadMetricsBinMetadata, + grpc_core::GrpcServerStatsBinMetadata, grpc_core::GrpcTraceBinMetadata, + grpc_core::GrpcTagsBinMetadata, grpc_core::GrpcLbClientStatsMetadata, + grpc_core::LbCostBinMetadata, grpc_core::LbTokenMetadata>; -/// Copies \a src to \a dst. -/// -/// For each mdelem in \a src, if the mdelem is of storage types -/// GRPC_MDELEM_STORAGE_INTERNED or GRPC_MDELEM_STORAGE_ALLOCATED, -/// refs the original mdelem for the copy. Otherwise, makes a new -/// mdelem that will hold its own refs to the key and value slices. -void grpc_metadata_batch_copy(const grpc_metadata_batch* src, - grpc_metadata_batch* dst); +struct grpc_metadata_batch : public grpc_metadata_batch_base { + using grpc_metadata_batch_base::grpc_metadata_batch_base; +}; #endif /* GRPC_CORE_LIB_TRANSPORT_METADATA_BATCH_H */ diff --git a/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.cc b/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.cc index 4858e95a2e..c1df3c1b19 100644 --- a/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.cc +++ b/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.cc @@ -31,5 +31,7 @@ void DestroySliceValue(const Buffer& value) { grpc_slice_unref_internal(value.slice); } +void DestroyTrivialMemento(const Buffer&) {} + } // namespace metadata_detail } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.h b/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.h index 551d89f3cb..be78b565c8 100644 --- a/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.h +++ b/contrib/libs/grpc/src/core/lib/transport/parsed_metadata.h @@ -26,10 +26,12 @@ #include "src/core/lib/iomgr/error.h" #include "src/core/lib/slice/slice.h" #include "src/core/lib/surface/validate_metadata.h" -#include "src/core/lib/transport/metadata.h" namespace grpc_core { +using MetadataParseErrorFn = + y_absl::FunctionRef<void(y_absl::string_view error, const Slice& value)>; + namespace metadata_detail { // Helper to determine whether a traits metadata is inlinable inside a memento, @@ -38,15 +40,14 @@ template <typename Which> struct HasSimpleMemento { static constexpr bool value = std::is_trivial<typename Which::MementoType>::value && - sizeof(typename Which::MementoType) <= sizeof(uint64_t); + sizeof(typename Which::MementoType) <= sizeof(grpc_slice); }; // Storage type for a single metadata entry. union Buffer { - uint64_t trivial; + char trivial[sizeof(grpc_slice)]; void* pointer; grpc_slice slice; - grpc_mdelem mdelem; }; // Given a key and a value, concatenate together to make a debug string. @@ -71,7 +72,9 @@ GPR_ATTRIBUTE_NOINLINE TString MakeDebugStringPipeline( // Extract a trivial field value from a Buffer - for MakeDebugStringPipeline. template <typename Field> Field FieldFromTrivial(const Buffer& value) { - return static_cast<Field>(value.trivial); + Field x; + memcpy(&x, value.trivial, sizeof(x)); + return x; } // Extract a pointer field value from a Buffer - for MakeDebugStringPipeline. @@ -86,6 +89,9 @@ Slice SliceFromBuffer(const Buffer& buffer); // Unref the grpc_slice part of a Buffer (assumes it is in fact a grpc_slice). void DestroySliceValue(const Buffer& value); +// Destroy a trivial memento (empty function). +void DestroyTrivialMemento(const Buffer& value); + } // namespace metadata_detail // A parsed metadata value. @@ -107,7 +113,7 @@ class ParsedMetadata { uint32_t transport_size) : vtable_(ParsedMetadata::template TrivialTraitVTable<Which>()), transport_size_(transport_size) { - value_.trivial = static_cast<uint64_t>(value); + memcpy(value_.trivial, &value, sizeof(value)); } template <typename Which> ParsedMetadata( @@ -129,13 +135,12 @@ class ParsedMetadata { transport_size_(transport_size) { value_.slice = value.TakeCSlice(); } - // Takes ownership of elem - explicit ParsedMetadata(grpc_mdelem elem) - : vtable_(grpc_is_binary_header_internal(GRPC_MDKEY(elem)) - ? MdelemVtable<true>() - : MdelemVtable<false>()), - transport_size_(GRPC_MDELEM_LENGTH(elem)) { - value_.mdelem = elem; + // Construct metadata from a string key, slice value pair. + ParsedMetadata(Slice key, Slice value) + : vtable_(ParsedMetadata::KeyValueVTable(key.as_string_view())), + transport_size_(key.size() + value.size() + 32) { + value_.pointer = + new std::pair<Slice, Slice>(std::move(key), std::move(value)); } ParsedMetadata() : vtable_(EmptyVTable()), transport_size_(0) {} ~ParsedMetadata() { vtable_->destroy(value_); } @@ -158,9 +163,8 @@ class ParsedMetadata { } // Set this parsed value on a container. - GRPC_MUST_USE_RESULT grpc_error_handle - SetOnContainer(MetadataContainer* container) const { - return vtable_->set(value_, container); + void SetOnContainer(MetadataContainer* container) const { + vtable_->set(value_, container); } // Is this a binary header or not? @@ -168,16 +172,18 @@ class ParsedMetadata { // HTTP2 defined storage size of this metadatum. uint32_t transport_size() const { return transport_size_; } // Create a new parsed metadata with the same key but a different value. - ParsedMetadata WithNewValue(Slice value) const { + ParsedMetadata WithNewValue(Slice value, + MetadataParseErrorFn on_error) const { ParsedMetadata result; result.vtable_ = vtable_; result.value_ = value_; result.transport_size_ = - TransportSize(vtable_->key_length(value_), value.length()); - vtable_->with_new_value(&value, &result); + TransportSize(vtable_->key(value_).length(), value.length()); + vtable_->with_new_value(&value, on_error, &result); return result; } TString DebugString() const { return vtable_->debug_string(value_); } + y_absl::string_view key() const { return vtable_->key(value_); } // TODO(ctiller): move to transport static uint32_t TransportSize(uint32_t key_size, uint32_t value_size) { @@ -191,29 +197,36 @@ class ParsedMetadata { struct VTable { const bool is_binary_header; void (*const destroy)(const Buffer& value); - grpc_error_handle (*const set)(const Buffer& value, - MetadataContainer* container); + void (*const set)(const Buffer& value, MetadataContainer* container); // result is a bitwise copy of the originating ParsedMetadata. - void (*const with_new_value)(Slice* new_value, ParsedMetadata* result); + void (*const with_new_value)(Slice* new_value, + MetadataParseErrorFn on_error, + ParsedMetadata* result); TString (*const debug_string)(const Buffer& value); - // TODO(ctiller): when we delete mdelem, make this a simple integer constant - // on the vtable - size_t (*const key_length)(const Buffer& value); + y_absl::string_view (*const key)(const Buffer& value); }; static const VTable* EmptyVTable(); + static const VTable* KeyValueVTable(y_absl::string_view key); template <typename Which> static const VTable* TrivialTraitVTable(); template <typename Which> static const VTable* NonTrivialTraitVTable(); template <typename Which> static const VTable* SliceTraitVTable(); - template <bool kIsBinaryHeader> - static const VTable* MdelemVtable(); - template <Slice (*ParseMemento)(Slice)> - GPR_ATTRIBUTE_NOINLINE void WithNewValueSetSlice(Slice* slice) { - value_.slice = ParseMemento(std::move(*slice)).TakeCSlice(); + template <Slice (*ParseMemento)(Slice, MetadataParseErrorFn)> + GPR_ATTRIBUTE_NOINLINE static void WithNewValueSetSlice( + Slice* slice, MetadataParseErrorFn on_error, ParsedMetadata* result) { + result->value_.slice = + ParseMemento(std::move(*slice), on_error).TakeCSlice(); + } + + template <typename T, T (*ParseMemento)(Slice, MetadataParseErrorFn)> + GPR_ATTRIBUTE_NOINLINE static void WithNewValueSetTrivial( + Slice* slice, MetadataParseErrorFn on_error, ParsedMetadata* result) { + T memento = ParseMemento(std::move(*slice), on_error); + memcpy(result->value_.trivial, &memento, sizeof(memento)); } const VTable* vtable_; @@ -229,15 +242,15 @@ ParsedMetadata<MetadataContainer>::EmptyVTable() { static const VTable vtable = { false, // destroy - [](const Buffer&) {}, + metadata_detail::DestroyTrivialMemento, // set - [](const Buffer&, MetadataContainer*) { return GRPC_ERROR_NONE; }, + [](const Buffer&, MetadataContainer*) {}, // with_new_value - [](Slice*, ParsedMetadata*) {}, + [](Slice*, MetadataParseErrorFn, ParsedMetadata*) {}, // debug_string [](const Buffer&) -> TString { return "empty"; }, - // key_length - [](const Buffer&) -> size_t { return 0; }, + // key + [](const Buffer&) -> y_absl::string_view { return ""; }, }; return &vtable; } @@ -249,18 +262,17 @@ ParsedMetadata<MetadataContainer>::TrivialTraitVTable() { static const VTable vtable = { y_absl::EndsWith(Which::key(), "-bin"), // destroy - [](const Buffer&) {}, + metadata_detail::DestroyTrivialMemento, // set [](const Buffer& value, MetadataContainer* map) { - map->Set(Which(), - Which::MementoToValue( - static_cast<typename Which::MementoType>(value.trivial))); - return GRPC_ERROR_NONE; + map->Set( + Which(), + Which::MementoToValue( + metadata_detail::FieldFromTrivial<typename Which::MementoType>( + value))); }, // with_new_value - [](Slice* value, ParsedMetadata* result) { - result->value_.trivial = Which::ParseMemento(std::move(*value)); - }, + WithNewValueSetTrivial<typename Which::MementoType, Which::ParseMemento>, // debug_string [](const Buffer& value) { return metadata_detail::MakeDebugStringPipeline( @@ -268,8 +280,8 @@ ParsedMetadata<MetadataContainer>::TrivialTraitVTable() { metadata_detail::FieldFromTrivial<typename Which::MementoType>, Which::DisplayValue); }, - // key_length - [](const Buffer&) { return Which::key().size(); }, + // key + [](const Buffer&) { return Which::key(); }, }; return &vtable; } @@ -288,12 +300,11 @@ ParsedMetadata<MetadataContainer>::NonTrivialTraitVTable() { [](const Buffer& value, MetadataContainer* map) { auto* p = static_cast<typename Which::MementoType*>(value.pointer); map->Set(Which(), Which::MementoToValue(*p)); - return GRPC_ERROR_NONE; }, // with_new_value - [](Slice* value, ParsedMetadata* result) { - result->value_.pointer = new - typename Which::MementoType(Which::ParseMemento(std::move(*value))); + [](Slice* value, MetadataParseErrorFn on_error, ParsedMetadata* result) { + result->value_.pointer = new typename Which::MementoType( + Which::ParseMemento(std::move(*value), on_error)); }, // debug_string [](const Buffer& value) { @@ -302,8 +313,8 @@ ParsedMetadata<MetadataContainer>::NonTrivialTraitVTable() { metadata_detail::FieldFromPointer<typename Which::MementoType>, Which::DisplayValue); }, - // key_length - [](const Buffer&) { return Which::key().size(); }, + // key + [](const Buffer&) { return Which::key(); }, }; return &vtable; } @@ -320,61 +331,53 @@ ParsedMetadata<MetadataContainer>::SliceTraitVTable() { [](const Buffer& value, MetadataContainer* map) { map->Set(Which(), Which::MementoToValue( metadata_detail::SliceFromBuffer(value))); - return GRPC_ERROR_NONE; }, // with_new_value - [](Slice* value, ParsedMetadata* result) { - result->WithNewValueSetSlice<Which::ParseMemento>(value); - }, + WithNewValueSetSlice<Which::ParseMemento>, // debug_string [](const Buffer& value) { return metadata_detail::MakeDebugStringPipeline( Which::key(), value, metadata_detail::SliceFromBuffer, Which::DisplayValue); }, - // key_length - [](const Buffer&) { return Which::key().size(); }, + // key + [](const Buffer&) { return Which::key(); }, }; return &vtable; } template <typename MetadataContainer> -template <bool kIsBinaryHeader> const typename ParsedMetadata<MetadataContainer>::VTable* -ParsedMetadata<MetadataContainer>::MdelemVtable() { - static const VTable vtable = { - kIsBinaryHeader, - // destroy - [](const Buffer& value) { GRPC_MDELEM_UNREF(value.mdelem); }, - // set - [](const Buffer& value, MetadataContainer* map) { - auto md = GRPC_MDELEM_REF(value.mdelem); - auto err = map->Append(md); - // If an error occurs, md is not consumed and we need to. - // This is an awful API, but that's why we're replacing it. - if (err != GRPC_ERROR_NONE) { - GRPC_MDELEM_UNREF(md); - } - return err; - }, - // with_new_value - [](Slice* value_slice, ParsedMetadata* result) { - result->value_.mdelem = grpc_mdelem_from_slices( - static_cast<const ManagedMemorySlice&>( - grpc_slice_ref_internal(GRPC_MDKEY(result->value_.mdelem))), - value_slice->TakeCSlice()); - }, - // debug_string - [](const Buffer& value) { - return metadata_detail::MakeDebugString( - StringViewFromSlice(GRPC_MDKEY(value.mdelem)), - StringViewFromSlice(GRPC_MDVALUE(value.mdelem))); - }, - // key_length - [](const Buffer& value) { - return GRPC_SLICE_LENGTH(GRPC_MDKEY(value.mdelem)); - }}; - return &vtable; +ParsedMetadata<MetadataContainer>::KeyValueVTable(y_absl::string_view key) { + using KV = std::pair<Slice, Slice>; + static const auto destroy = [](const Buffer& value) { + delete static_cast<KV*>(value.pointer); + }; + static const auto set = [](const Buffer& value, MetadataContainer* map) { + auto* p = static_cast<KV*>(value.pointer); + map->AppendUnknown(p->first.as_string_view(), p->second.Ref()); + }; + static const auto with_new_value = [](Slice* value, MetadataParseErrorFn, + ParsedMetadata* result) { + auto* p = new KV{ + static_cast<KV*>(result->value_.pointer)->first.Ref(), + std::move(*value), + }; + result->value_.pointer = p; + }; + static const auto debug_string = [](const Buffer& value) { + auto* p = static_cast<KV*>(value.pointer); + return y_absl::StrCat(p->first.as_string_view(), ": ", + p->second.as_string_view()); + }; + static const auto key_fn = [](const Buffer& value) { + return static_cast<KV*>(value.pointer)->first.as_string_view(); + }; + static const VTable vtable[2] = { + {false, destroy, set, with_new_value, debug_string, key_fn}, + {true, destroy, set, with_new_value, debug_string, key_fn}, + }; + return &vtable[y_absl::EndsWith(key, "-bin")]; } } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/transport/static_metadata.cc b/contrib/libs/grpc/src/core/lib/transport/static_metadata.cc deleted file mode 100644 index 0ea4b614a7..0000000000 --- a/contrib/libs/grpc/src/core/lib/transport/static_metadata.cc +++ /dev/null @@ -1,1032 +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. - */ - -/* - * WARNING: Auto-generated code. - * - * To make changes to this file, change - * tools/codegen/core/gen_static_metadata.py, and then re-run it. - * - * See metadata.h for an explanation of the interface here, and metadata.cc for - * an explanation of what's going on. - */ - -#include <grpc/support/port_platform.h> - -#include "src/core/lib/transport/static_metadata.h" - -#include "src/core/lib/slice/slice_internal.h" - -namespace grpc_core { -StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT] = { - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[3].base, 10, - g_static_metadata_bytes + 19), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 0), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, - g_static_metadata_bytes + 5), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[31].base, 3, - g_static_metadata_bytes + 603), - 1), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, - g_static_metadata_bytes + 5), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[32].base, 4, - g_static_metadata_bytes + 606), - 2), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 5, - g_static_metadata_bytes + 0), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[33].base, 1, - g_static_metadata_bytes + 610), - 3), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[0].base, 5, - g_static_metadata_bytes + 0), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[34].base, 11, - g_static_metadata_bytes + 611), - 4), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7, - g_static_metadata_bytes + 29), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[35].base, 4, - g_static_metadata_bytes + 622), - 5), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7, - g_static_metadata_bytes + 29), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[36].base, 5, - g_static_metadata_bytes + 626), - 6), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[37].base, 3, - g_static_metadata_bytes + 631), - 7), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[38].base, 3, - g_static_metadata_bytes + 634), - 8), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[39].base, 3, - g_static_metadata_bytes + 637), - 9), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[40].base, 3, - g_static_metadata_bytes + 640), - 10), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[41].base, 3, - g_static_metadata_bytes + 643), - 11), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[42].base, 3, - g_static_metadata_bytes + 646), - 12), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[2].base, 7, - g_static_metadata_bytes + 12), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[43].base, 3, - g_static_metadata_bytes + 649), - 13), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[44].base, 14, - g_static_metadata_bytes + 652), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 14), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 15, - g_static_metadata_bytes + 108), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[45].base, 13, - g_static_metadata_bytes + 666), - 15), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[46].base, 15, - g_static_metadata_bytes + 679), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 16), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[47].base, 13, - g_static_metadata_bytes + 694), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 17), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[48].base, 6, - g_static_metadata_bytes + 707), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 18), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[49].base, 27, - g_static_metadata_bytes + 713), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 19), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[50].base, 3, - g_static_metadata_bytes + 740), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 20), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[51].base, 5, - g_static_metadata_bytes + 743), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 21), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[52].base, 13, - g_static_metadata_bytes + 748), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 22), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[53].base, 13, - g_static_metadata_bytes + 761), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 23), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[54].base, 19, - g_static_metadata_bytes + 774), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 24), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 16, - g_static_metadata_bytes + 92), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 25), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[55].base, 16, - g_static_metadata_bytes + 793), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 26), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[56].base, 14, - g_static_metadata_bytes + 809), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 27), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[57].base, 16, - g_static_metadata_bytes + 823), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 28), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[58].base, 13, - g_static_metadata_bytes + 839), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 29), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 12, - g_static_metadata_bytes + 80), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 30), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[59].base, 6, - g_static_metadata_bytes + 852), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 31), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[60].base, 4, - g_static_metadata_bytes + 858), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 32), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[61].base, 4, - g_static_metadata_bytes + 862), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 33), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[62].base, 6, - g_static_metadata_bytes + 866), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 34), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[63].base, 7, - g_static_metadata_bytes + 872), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 35), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[64].base, 4, - g_static_metadata_bytes + 879), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 36), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[65].base, 4, - g_static_metadata_bytes + 883), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 37), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[66].base, 8, - g_static_metadata_bytes + 887), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 38), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[67].base, 17, - g_static_metadata_bytes + 895), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 39), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[68].base, 13, - g_static_metadata_bytes + 912), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 40), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[69].base, 8, - g_static_metadata_bytes + 925), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 41), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[70].base, 19, - g_static_metadata_bytes + 933), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 42), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[71].base, 13, - g_static_metadata_bytes + 952), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 43), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[72].base, 4, - g_static_metadata_bytes + 965), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 44), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[73].base, 8, - g_static_metadata_bytes + 969), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 45), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[74].base, 12, - g_static_metadata_bytes + 977), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 46), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[75].base, 18, - g_static_metadata_bytes + 989), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 47), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[76].base, 19, - g_static_metadata_bytes + 1007), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 48), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[77].base, 5, - g_static_metadata_bytes + 1026), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 49), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[78].base, 7, - g_static_metadata_bytes + 1031), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 50), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[79].base, 7, - g_static_metadata_bytes + 1038), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 51), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[80].base, 11, - g_static_metadata_bytes + 1045), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 52), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[81].base, 6, - g_static_metadata_bytes + 1056), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 53), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[82].base, 10, - g_static_metadata_bytes + 1062), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 54), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[83].base, 25, - g_static_metadata_bytes + 1072), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 55), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[84].base, 17, - g_static_metadata_bytes + 1097), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 56), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[85].base, 10, - g_static_metadata_bytes + 1114), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 57), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[86].base, 4, - g_static_metadata_bytes + 1124), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 58), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[87].base, 3, - g_static_metadata_bytes + 1128), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 59), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[88].base, 16, - g_static_metadata_bytes + 1131), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 60), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 11, - g_static_metadata_bytes + 36), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[89].base, 1, - g_static_metadata_bytes + 1147), - 61), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 11, - g_static_metadata_bytes + 36), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[15].base, 1, - g_static_metadata_bytes + 213), - 62), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[5].base, 11, - g_static_metadata_bytes + 36), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[16].base, 1, - g_static_metadata_bytes + 214), - 63), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 13, - g_static_metadata_bytes + 47), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[90].base, 8, - g_static_metadata_bytes + 1148), - 64), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 13, - g_static_metadata_bytes + 47), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 4, - g_static_metadata_bytes + 578), - 65), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[6].base, 13, - g_static_metadata_bytes + 47), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[26].base, 7, - g_static_metadata_bytes + 571), - 66), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[8].base, 12, - g_static_metadata_bytes + 80), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[91].base, 16, - g_static_metadata_bytes + 1156), - 67), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[4].base, 7, - g_static_metadata_bytes + 29), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[92].base, 4, - g_static_metadata_bytes + 1172), - 68), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[1].base, 7, - g_static_metadata_bytes + 5), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[93].base, 3, - g_static_metadata_bytes + 1176), - 69), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 15, - g_static_metadata_bytes + 108), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 70), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 16, - g_static_metadata_bytes + 92), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[90].base, 8, - g_static_metadata_bytes + 1148), - 71), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[9].base, 16, - g_static_metadata_bytes + 92), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 4, - g_static_metadata_bytes + 578), - 72), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[94].base, 11, - g_static_metadata_bytes + 1179), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[19].base, 0, - g_static_metadata_bytes + 217), - 73), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[90].base, 8, - g_static_metadata_bytes + 1148), - 74), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[26].base, 7, - g_static_metadata_bytes + 571), - 75), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[95].base, 16, - g_static_metadata_bytes + 1190), - 76), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 4, - g_static_metadata_bytes + 578), - 77), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[96].base, 13, - g_static_metadata_bytes + 1206), - 78), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[97].base, 12, - g_static_metadata_bytes + 1219), - 79), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[7].base, 20, - g_static_metadata_bytes + 60), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[98].base, 21, - g_static_metadata_bytes + 1231), - 80), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 15, - g_static_metadata_bytes + 108), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[90].base, 8, - g_static_metadata_bytes + 1148), - 81), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 15, - g_static_metadata_bytes + 108), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[27].base, 4, - g_static_metadata_bytes + 578), - 82), - StaticMetadata( - StaticMetadataSlice(&g_static_metadata_slice_refcounts[10].base, 15, - g_static_metadata_bytes + 108), - StaticMetadataSlice(&g_static_metadata_slice_refcounts[96].base, 13, - g_static_metadata_bytes + 1206), - 83), -}; - -/* Warning: the core static metadata currently operates under the soft -constraint that the first GRPC_CHTTP2_LAST_STATIC_ENTRY (61) entries must -contain metadata specified by the http2 hpack standard. The CHTTP2 transport -reads the core metadata with this assumption in mind. If the order of the core -static metadata is to be changed, then the CHTTP2 transport must be changed as -well to stop relying on the core metadata. */ - -grpc_mdelem g_static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT] = { - // clang-format off - /* GRPC_MDELEM_AUTHORITY_EMPTY: - ":authority": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[0].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_METHOD_GET: - ":method": "GET" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[1].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_METHOD_POST: - ":method": "POST" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[2].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_PATH_SLASH: - ":path": "/" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[3].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML: - ":path": "/index.html" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[4].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_SCHEME_HTTP: - ":scheme": "http" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[5].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_SCHEME_HTTPS: - ":scheme": "https" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[6].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STATUS_200: - ":status": "200" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[7].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STATUS_204: - ":status": "204" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[8].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STATUS_206: - ":status": "206" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[9].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STATUS_304: - ":status": "304" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[10].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STATUS_400: - ":status": "400" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[11].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STATUS_404: - ":status": "404" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[12].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STATUS_500: - ":status": "500" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[13].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_CHARSET_EMPTY: - "accept-charset": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[14].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE: - "accept-encoding": "gzip, deflate" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[15].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY: - "accept-language": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[16].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_RANGES_EMPTY: - "accept-ranges": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[17].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_EMPTY: - "accept": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[18].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY: - "access-control-allow-origin": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[19].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_AGE_EMPTY: - "age": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[20].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ALLOW_EMPTY: - "allow": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[21].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_AUTHORIZATION_EMPTY: - "authorization": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[22].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CACHE_CONTROL_EMPTY: - "cache-control": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[23].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY: - "content-disposition": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[24].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_ENCODING_EMPTY: - "content-encoding": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[25].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY: - "content-language": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[26].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_LENGTH_EMPTY: - "content-length": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[27].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_LOCATION_EMPTY: - "content-location": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[28].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_RANGE_EMPTY: - "content-range": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[29].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_TYPE_EMPTY: - "content-type": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[30].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_COOKIE_EMPTY: - "cookie": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[31].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_DATE_EMPTY: - "date": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[32].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ETAG_EMPTY: - "etag": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[33].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_EXPECT_EMPTY: - "expect": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[34].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_EXPIRES_EMPTY: - "expires": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[35].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_FROM_EMPTY: - "from": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[36].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_HOST_EMPTY: - "host": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[37].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_IF_MATCH_EMPTY: - "if-match": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[38].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY: - "if-modified-since": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[39].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_IF_NONE_MATCH_EMPTY: - "if-none-match": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[40].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_IF_RANGE_EMPTY: - "if-range": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[41].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY: - "if-unmodified-since": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[42].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_LAST_MODIFIED_EMPTY: - "last-modified": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[43].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_LINK_EMPTY: - "link": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[44].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_LOCATION_EMPTY: - "location": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[45].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_MAX_FORWARDS_EMPTY: - "max-forwards": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[46].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY: - "proxy-authenticate": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[47].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY: - "proxy-authorization": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[48].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_RANGE_EMPTY: - "range": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[49].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_REFERER_EMPTY: - "referer": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[50].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_REFRESH_EMPTY: - "refresh": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[51].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_RETRY_AFTER_EMPTY: - "retry-after": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[52].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_SERVER_EMPTY: - "server": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[53].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_SET_COOKIE_EMPTY: - "set-cookie": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[54].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY: - "strict-transport-security": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[55].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_TRANSFER_ENCODING_EMPTY: - "transfer-encoding": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[56].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_USER_AGENT_EMPTY: - "user-agent": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[57].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_VARY_EMPTY: - "vary": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[58].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_VIA_EMPTY: - "via": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[59].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY: - "www-authenticate": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[60].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_STATUS_0: - "grpc-status": "0" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[61].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_STATUS_1: - "grpc-status": "1" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[62].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_STATUS_2: - "grpc-status": "2" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[63].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ENCODING_IDENTITY: - "grpc-encoding": "identity" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[64].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ENCODING_GZIP: - "grpc-encoding": "gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[65].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ENCODING_DEFLATE: - "grpc-encoding": "deflate" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[66].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC: - "content-type": "application/grpc" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[67].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_SCHEME_GRPC: - ":scheme": "grpc" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[68].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_METHOD_PUT: - ":method": "PUT" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[69].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_ENCODING_EMPTY: - "accept-encoding": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[70].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_ENCODING_IDENTITY: - "content-encoding": "identity" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[71].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_CONTENT_ENCODING_GZIP: - "content-encoding": "gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[72].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_LB_COST_BIN_EMPTY: - "lb-cost-bin": "" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[73].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY: - "grpc-accept-encoding": "identity" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[74].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE: - "grpc-accept-encoding": "deflate" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[75].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE: - "grpc-accept-encoding": "identity,deflate" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[76].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP: - "grpc-accept-encoding": "gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[77].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP: - "grpc-accept-encoding": "identity,gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[78].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP: - "grpc-accept-encoding": "deflate,gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[79].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP: - "grpc-accept-encoding": "identity,deflate,gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[80].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY: - "accept-encoding": "identity" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[81].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_ENCODING_GZIP: - "accept-encoding": "gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[82].data(), - GRPC_MDELEM_STORAGE_STATIC), - /* GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP: - "accept-encoding": "identity,gzip" */ - GRPC_MAKE_MDELEM( - &g_static_mdelem_table[83].data(), - GRPC_MDELEM_STORAGE_STATIC) - // clang-format on -}; -} // namespace grpc_core - -uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 4, 4, 6, 6, 8, 8, 2, 4, 4}; - -static const int8_t elems_r[] = { - 18, 11, -8, 0, -1, -46, 11, 0, 13, 10, 7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -51, 0, -54, -55, -56, -57, -58, -59, -60, -61, -62, -63, - 0, 33, 32, 31, 30, 29, 29, 28, 27, 26, 25, 24, 23, 22, - 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 4, 3, 0, 0, 0, 0, 0, -8, 0}; -static uint32_t elems_phash(uint32_t i) { - i -= 33; - uint32_t x = i % 97; - uint32_t y = i / 97; - uint32_t h = x; - if (y < GPR_ARRAY_SIZE(elems_r)) { - uint32_t delta = static_cast<uint32_t>(elems_r[y]); - h += delta; - } - return h; -} - -static const uint16_t elem_keys[] = { - 235, 236, 237, 238, 239, 240, 241, 719, 720, 431, 432, 130, - 131, 1009, 910, 811, 620, 621, 33, 34, 584, 1017, 918, 4375, - 4573, 4672, 4771, 4870, 4969, 5068, 5167, 5266, 5365, 5464, 5563, 5662, - 5761, 5860, 5959, 1035, 6058, 6157, 6256, 6355, 6454, 6553, 6652, 6751, - 6850, 6949, 7048, 7147, 7246, 7345, 7444, 7543, 7642, 7741, 7840, 7939, - 8038, 8137, 8236, 8335, 8434, 8533, 488, 8632, 8731, 9325, 0, 783, - 0, 192, 0, 0, 788, 789, 790, 791, 684, 316, 0, 0, - 1080, 981, 0, 883, 510, 511, 1086}; -static const uint8_t elem_idxs[] = { - 7, 8, 9, 10, 11, 12, 13, 75, 77, 5, 6, 1, 2, 70, 25, 30, - 66, 65, 3, 4, 61, 82, 72, 14, 16, 17, 18, 19, 20, 21, 22, 23, - 24, 26, 27, 28, 29, 31, 32, 15, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, - 57, 58, 68, 59, 60, 73, 255, 74, 255, 69, 255, 255, 76, 78, 79, 80, - 64, 0, 255, 255, 81, 71, 255, 67, 62, 63, 83}; - -grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b) { - if (a == -1 || b == -1) return GRPC_MDNULL; - uint32_t k = static_cast<uint32_t>(a * 99 + b); - uint32_t h = elems_phash(k); - return h < GPR_ARRAY_SIZE(elem_keys) && elem_keys[h] == k && - elem_idxs[h] != 255 - ? GRPC_MAKE_MDELEM( - &grpc_core::g_static_mdelem_table[elem_idxs[h]].data(), - GRPC_MDELEM_STORAGE_STATIC) - : GRPC_MDNULL; -} - -const uint8_t grpc_static_accept_encoding_metadata[8] = {0, 74, 75, 76, - 77, 78, 79, 80}; - -const uint8_t grpc_static_accept_stream_encoding_metadata[4] = {0, 81, 82, 83}; diff --git a/contrib/libs/grpc/src/core/lib/transport/static_metadata.h b/contrib/libs/grpc/src/core/lib/transport/static_metadata.h deleted file mode 100644 index 488e5ec49b..0000000000 --- a/contrib/libs/grpc/src/core/lib/transport/static_metadata.h +++ /dev/null @@ -1,322 +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. - */ - -/* - * WARNING: Auto-generated code. - * - * To make changes to this file, change - * tools/codegen/core/gen_static_metadata.py, and then re-run it. - * - * See metadata.h for an explanation of the interface here, and metadata.cc for - * an explanation of what's going on. - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H -#define GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H - -#include <grpc/support/port_platform.h> - -#include <cstdint> - -#include "src/core/lib/slice/static_slice.h" -#include "src/core/lib/transport/metadata.h" - -#define GRPC_STATIC_MDELEM_COUNT 84 - -namespace grpc_core { -extern StaticMetadata g_static_mdelem_table[GRPC_STATIC_MDELEM_COUNT]; -extern grpc_mdelem g_static_mdelem_manifested[GRPC_STATIC_MDELEM_COUNT]; -} // namespace grpc_core - -extern uintptr_t grpc_static_mdelem_user_data[GRPC_STATIC_MDELEM_COUNT]; -/* ":authority": "" */ -#define GRPC_MDELEM_AUTHORITY_EMPTY (::grpc_core::g_static_mdelem_manifested[0]) -/* ":method": "GET" */ -#define GRPC_MDELEM_METHOD_GET (::grpc_core::g_static_mdelem_manifested[1]) -/* ":method": "POST" */ -#define GRPC_MDELEM_METHOD_POST (::grpc_core::g_static_mdelem_manifested[2]) -/* ":path": "/" */ -#define GRPC_MDELEM_PATH_SLASH (::grpc_core::g_static_mdelem_manifested[3]) -/* ":path": "/index.html" */ -#define GRPC_MDELEM_PATH_SLASH_INDEX_DOT_HTML \ - (::grpc_core::g_static_mdelem_manifested[4]) -/* ":scheme": "http" */ -#define GRPC_MDELEM_SCHEME_HTTP (::grpc_core::g_static_mdelem_manifested[5]) -/* ":scheme": "https" */ -#define GRPC_MDELEM_SCHEME_HTTPS (::grpc_core::g_static_mdelem_manifested[6]) -/* ":status": "200" */ -#define GRPC_MDELEM_STATUS_200 (::grpc_core::g_static_mdelem_manifested[7]) -/* ":status": "204" */ -#define GRPC_MDELEM_STATUS_204 (::grpc_core::g_static_mdelem_manifested[8]) -/* ":status": "206" */ -#define GRPC_MDELEM_STATUS_206 (::grpc_core::g_static_mdelem_manifested[9]) -/* ":status": "304" */ -#define GRPC_MDELEM_STATUS_304 (::grpc_core::g_static_mdelem_manifested[10]) -/* ":status": "400" */ -#define GRPC_MDELEM_STATUS_400 (::grpc_core::g_static_mdelem_manifested[11]) -/* ":status": "404" */ -#define GRPC_MDELEM_STATUS_404 (::grpc_core::g_static_mdelem_manifested[12]) -/* ":status": "500" */ -#define GRPC_MDELEM_STATUS_500 (::grpc_core::g_static_mdelem_manifested[13]) -/* "accept-charset": "" */ -#define GRPC_MDELEM_ACCEPT_CHARSET_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[14]) -/* "accept-encoding": "gzip, deflate" */ -#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP_COMMA_DEFLATE \ - (::grpc_core::g_static_mdelem_manifested[15]) -/* "accept-language": "" */ -#define GRPC_MDELEM_ACCEPT_LANGUAGE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[16]) -/* "accept-ranges": "" */ -#define GRPC_MDELEM_ACCEPT_RANGES_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[17]) -/* "accept": "" */ -#define GRPC_MDELEM_ACCEPT_EMPTY (::grpc_core::g_static_mdelem_manifested[18]) -/* "access-control-allow-origin": "" */ -#define GRPC_MDELEM_ACCESS_CONTROL_ALLOW_ORIGIN_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[19]) -/* "age": "" */ -#define GRPC_MDELEM_AGE_EMPTY (::grpc_core::g_static_mdelem_manifested[20]) -/* "allow": "" */ -#define GRPC_MDELEM_ALLOW_EMPTY (::grpc_core::g_static_mdelem_manifested[21]) -/* "authorization": "" */ -#define GRPC_MDELEM_AUTHORIZATION_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[22]) -/* "cache-control": "" */ -#define GRPC_MDELEM_CACHE_CONTROL_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[23]) -/* "content-disposition": "" */ -#define GRPC_MDELEM_CONTENT_DISPOSITION_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[24]) -/* "content-encoding": "" */ -#define GRPC_MDELEM_CONTENT_ENCODING_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[25]) -/* "content-language": "" */ -#define GRPC_MDELEM_CONTENT_LANGUAGE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[26]) -/* "content-length": "" */ -#define GRPC_MDELEM_CONTENT_LENGTH_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[27]) -/* "content-location": "" */ -#define GRPC_MDELEM_CONTENT_LOCATION_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[28]) -/* "content-range": "" */ -#define GRPC_MDELEM_CONTENT_RANGE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[29]) -/* "content-type": "" */ -#define GRPC_MDELEM_CONTENT_TYPE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[30]) -/* "cookie": "" */ -#define GRPC_MDELEM_COOKIE_EMPTY (::grpc_core::g_static_mdelem_manifested[31]) -/* "date": "" */ -#define GRPC_MDELEM_DATE_EMPTY (::grpc_core::g_static_mdelem_manifested[32]) -/* "etag": "" */ -#define GRPC_MDELEM_ETAG_EMPTY (::grpc_core::g_static_mdelem_manifested[33]) -/* "expect": "" */ -#define GRPC_MDELEM_EXPECT_EMPTY (::grpc_core::g_static_mdelem_manifested[34]) -/* "expires": "" */ -#define GRPC_MDELEM_EXPIRES_EMPTY (::grpc_core::g_static_mdelem_manifested[35]) -/* "from": "" */ -#define GRPC_MDELEM_FROM_EMPTY (::grpc_core::g_static_mdelem_manifested[36]) -/* "host": "" */ -#define GRPC_MDELEM_HOST_EMPTY (::grpc_core::g_static_mdelem_manifested[37]) -/* "if-match": "" */ -#define GRPC_MDELEM_IF_MATCH_EMPTY (::grpc_core::g_static_mdelem_manifested[38]) -/* "if-modified-since": "" */ -#define GRPC_MDELEM_IF_MODIFIED_SINCE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[39]) -/* "if-none-match": "" */ -#define GRPC_MDELEM_IF_NONE_MATCH_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[40]) -/* "if-range": "" */ -#define GRPC_MDELEM_IF_RANGE_EMPTY (::grpc_core::g_static_mdelem_manifested[41]) -/* "if-unmodified-since": "" */ -#define GRPC_MDELEM_IF_UNMODIFIED_SINCE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[42]) -/* "last-modified": "" */ -#define GRPC_MDELEM_LAST_MODIFIED_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[43]) -/* "link": "" */ -#define GRPC_MDELEM_LINK_EMPTY (::grpc_core::g_static_mdelem_manifested[44]) -/* "location": "" */ -#define GRPC_MDELEM_LOCATION_EMPTY (::grpc_core::g_static_mdelem_manifested[45]) -/* "max-forwards": "" */ -#define GRPC_MDELEM_MAX_FORWARDS_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[46]) -/* "proxy-authenticate": "" */ -#define GRPC_MDELEM_PROXY_AUTHENTICATE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[47]) -/* "proxy-authorization": "" */ -#define GRPC_MDELEM_PROXY_AUTHORIZATION_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[48]) -/* "range": "" */ -#define GRPC_MDELEM_RANGE_EMPTY (::grpc_core::g_static_mdelem_manifested[49]) -/* "referer": "" */ -#define GRPC_MDELEM_REFERER_EMPTY (::grpc_core::g_static_mdelem_manifested[50]) -/* "refresh": "" */ -#define GRPC_MDELEM_REFRESH_EMPTY (::grpc_core::g_static_mdelem_manifested[51]) -/* "retry-after": "" */ -#define GRPC_MDELEM_RETRY_AFTER_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[52]) -/* "server": "" */ -#define GRPC_MDELEM_SERVER_EMPTY (::grpc_core::g_static_mdelem_manifested[53]) -/* "set-cookie": "" */ -#define GRPC_MDELEM_SET_COOKIE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[54]) -/* "strict-transport-security": "" */ -#define GRPC_MDELEM_STRICT_TRANSPORT_SECURITY_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[55]) -/* "transfer-encoding": "" */ -#define GRPC_MDELEM_TRANSFER_ENCODING_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[56]) -/* "user-agent": "" */ -#define GRPC_MDELEM_USER_AGENT_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[57]) -/* "vary": "" */ -#define GRPC_MDELEM_VARY_EMPTY (::grpc_core::g_static_mdelem_manifested[58]) -/* "via": "" */ -#define GRPC_MDELEM_VIA_EMPTY (::grpc_core::g_static_mdelem_manifested[59]) -/* "www-authenticate": "" */ -#define GRPC_MDELEM_WWW_AUTHENTICATE_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[60]) -/* "grpc-status": "0" */ -#define GRPC_MDELEM_GRPC_STATUS_0 (::grpc_core::g_static_mdelem_manifested[61]) -/* "grpc-status": "1" */ -#define GRPC_MDELEM_GRPC_STATUS_1 (::grpc_core::g_static_mdelem_manifested[62]) -/* "grpc-status": "2" */ -#define GRPC_MDELEM_GRPC_STATUS_2 (::grpc_core::g_static_mdelem_manifested[63]) -/* "grpc-encoding": "identity" */ -#define GRPC_MDELEM_GRPC_ENCODING_IDENTITY \ - (::grpc_core::g_static_mdelem_manifested[64]) -/* "grpc-encoding": "gzip" */ -#define GRPC_MDELEM_GRPC_ENCODING_GZIP \ - (::grpc_core::g_static_mdelem_manifested[65]) -/* "grpc-encoding": "deflate" */ -#define GRPC_MDELEM_GRPC_ENCODING_DEFLATE \ - (::grpc_core::g_static_mdelem_manifested[66]) -/* "content-type": "application/grpc" */ -#define GRPC_MDELEM_CONTENT_TYPE_APPLICATION_SLASH_GRPC \ - (::grpc_core::g_static_mdelem_manifested[67]) -/* ":scheme": "grpc" */ -#define GRPC_MDELEM_SCHEME_GRPC (::grpc_core::g_static_mdelem_manifested[68]) -/* ":method": "PUT" */ -#define GRPC_MDELEM_METHOD_PUT (::grpc_core::g_static_mdelem_manifested[69]) -/* "accept-encoding": "" */ -#define GRPC_MDELEM_ACCEPT_ENCODING_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[70]) -/* "content-encoding": "identity" */ -#define GRPC_MDELEM_CONTENT_ENCODING_IDENTITY \ - (::grpc_core::g_static_mdelem_manifested[71]) -/* "content-encoding": "gzip" */ -#define GRPC_MDELEM_CONTENT_ENCODING_GZIP \ - (::grpc_core::g_static_mdelem_manifested[72]) -/* "lb-cost-bin": "" */ -#define GRPC_MDELEM_LB_COST_BIN_EMPTY \ - (::grpc_core::g_static_mdelem_manifested[73]) -/* "grpc-accept-encoding": "identity" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY \ - (::grpc_core::g_static_mdelem_manifested[74]) -/* "grpc-accept-encoding": "deflate" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE \ - (::grpc_core::g_static_mdelem_manifested[75]) -/* "grpc-accept-encoding": "identity,deflate" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE \ - (::grpc_core::g_static_mdelem_manifested[76]) -/* "grpc-accept-encoding": "gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_GZIP \ - (::grpc_core::g_static_mdelem_manifested[77]) -/* "grpc-accept-encoding": "identity,gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \ - (::grpc_core::g_static_mdelem_manifested[78]) -/* "grpc-accept-encoding": "deflate,gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_DEFLATE_COMMA_GZIP \ - (::grpc_core::g_static_mdelem_manifested[79]) -/* "grpc-accept-encoding": "identity,deflate,gzip" */ -#define GRPC_MDELEM_GRPC_ACCEPT_ENCODING_IDENTITY_COMMA_DEFLATE_COMMA_GZIP \ - (::grpc_core::g_static_mdelem_manifested[80]) -/* "accept-encoding": "identity" */ -#define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY \ - (::grpc_core::g_static_mdelem_manifested[81]) -/* "accept-encoding": "gzip" */ -#define GRPC_MDELEM_ACCEPT_ENCODING_GZIP \ - (::grpc_core::g_static_mdelem_manifested[82]) -/* "accept-encoding": "identity,gzip" */ -#define GRPC_MDELEM_ACCEPT_ENCODING_IDENTITY_COMMA_GZIP \ - (::grpc_core::g_static_mdelem_manifested[83]) - -grpc_mdelem grpc_static_mdelem_for_static_strings(intptr_t a, intptr_t b); -typedef enum { - GRPC_BATCH_PATH, - GRPC_BATCH_METHOD, - GRPC_BATCH_STATUS, - GRPC_BATCH_AUTHORITY, - GRPC_BATCH_SCHEME, - GRPC_BATCH_GRPC_STATUS, - GRPC_BATCH_GRPC_ENCODING, - GRPC_BATCH_GRPC_ACCEPT_ENCODING, - GRPC_BATCH_CONTENT_TYPE, - GRPC_BATCH_CONTENT_ENCODING, - GRPC_BATCH_ACCEPT_ENCODING, - GRPC_BATCH_GRPC_INTERNAL_ENCODING_REQUEST, - GRPC_BATCH_GRPC_PREVIOUS_RPC_ATTEMPTS, - GRPC_BATCH_GRPC_RETRY_PUSHBACK_MS, - GRPC_BATCH_CALLOUTS_COUNT -} grpc_metadata_batch_callouts_index; - -typedef union { - struct grpc_linked_mdelem* array[GRPC_BATCH_CALLOUTS_COUNT]; - struct { - struct grpc_linked_mdelem* path; - struct grpc_linked_mdelem* method; - struct grpc_linked_mdelem* status; - struct grpc_linked_mdelem* authority; - struct grpc_linked_mdelem* scheme; - struct grpc_linked_mdelem* grpc_status; - struct grpc_linked_mdelem* grpc_encoding; - struct grpc_linked_mdelem* grpc_accept_encoding; - struct grpc_linked_mdelem* content_type; - struct grpc_linked_mdelem* content_encoding; - struct grpc_linked_mdelem* accept_encoding; - struct grpc_linked_mdelem* grpc_internal_encoding_request; - struct grpc_linked_mdelem* grpc_previous_rpc_attempts; - struct grpc_linked_mdelem* grpc_retry_pushback_ms; - } named; -} grpc_metadata_batch_callouts; - -#define GRPC_BATCH_INDEX_OF(slice) \ - (GRPC_IS_STATIC_METADATA_STRING((slice)) && \ - reinterpret_cast<grpc_core::StaticSliceRefcount*>((slice).refcount) \ - ->index <= static_cast<uint32_t>(GRPC_BATCH_CALLOUTS_COUNT) \ - ? static_cast<grpc_metadata_batch_callouts_index>( \ - reinterpret_cast<grpc_core::StaticSliceRefcount*>( \ - (slice).refcount) \ - ->index) \ - : GRPC_BATCH_CALLOUTS_COUNT) - -extern const uint8_t grpc_static_accept_encoding_metadata[8]; -#define GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(algs) \ - (GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table \ - [grpc_static_accept_encoding_metadata[(algs)]] \ - .data(), \ - GRPC_MDELEM_STORAGE_STATIC)) - -extern const uint8_t grpc_static_accept_stream_encoding_metadata[4]; -#define GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(algs) \ - (GRPC_MAKE_MDELEM(&grpc_core::g_static_mdelem_table \ - [grpc_static_accept_stream_encoding_metadata[(algs)]] \ - .data(), \ - GRPC_MDELEM_STORAGE_STATIC)) -#endif /* GRPC_CORE_LIB_TRANSPORT_STATIC_METADATA_H */ diff --git a/contrib/libs/grpc/src/core/lib/transport/status_metadata.cc b/contrib/libs/grpc/src/core/lib/transport/status_metadata.cc deleted file mode 100644 index fb7064641d..0000000000 --- a/contrib/libs/grpc/src/core/lib/transport/status_metadata.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * - * 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 <grpc/support/port_platform.h> - -#include "src/core/lib/transport/status_metadata.h" - -#include "src/core/lib/gpr/string.h" -#include "src/core/lib/slice/slice_string_helpers.h" -#include "src/core/lib/transport/static_metadata.h" - -/* we offset status by a small amount when storing it into transport metadata - as metadata cannot store a 0 value (which is used as OK for grpc_status_codes - */ -#define STATUS_OFFSET 1 - -static void destroy_status(void* /*ignored*/) {} - -grpc_status_code grpc_get_status_code_from_metadata(grpc_mdelem md) { - if (grpc_mdelem_static_value_eq(md, GRPC_MDELEM_GRPC_STATUS_0)) { - return GRPC_STATUS_OK; - } - if (grpc_mdelem_static_value_eq(md, GRPC_MDELEM_GRPC_STATUS_1)) { - return GRPC_STATUS_CANCELLED; - } - if (grpc_mdelem_static_value_eq(md, GRPC_MDELEM_GRPC_STATUS_2)) { - return GRPC_STATUS_UNKNOWN; - } - void* user_data = grpc_mdelem_get_user_data(md, destroy_status); - if (user_data != nullptr) { - return static_cast<grpc_status_code>(reinterpret_cast<intptr_t>(user_data) - - STATUS_OFFSET); - } - uint32_t status; - if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(md), &status)) { - status = GRPC_STATUS_UNKNOWN; /* could not parse status code */ - } - grpc_mdelem_set_user_data(md, destroy_status, - reinterpret_cast<void*>(status + STATUS_OFFSET)); - return static_cast<grpc_status_code>(status); -} - -grpc_mdelem grpc_get_reffed_status_elem_slowpath(int status_code) { - char tmp[GPR_LTOA_MIN_BUFSIZE]; - gpr_ltoa(status_code, tmp); - return grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_STATUS, - grpc_core::UnmanagedMemorySlice(tmp)); -} diff --git a/contrib/libs/grpc/src/core/lib/transport/status_metadata.h b/contrib/libs/grpc/src/core/lib/transport/status_metadata.h deleted file mode 100644 index 24022c0cf5..0000000000 --- a/contrib/libs/grpc/src/core/lib/transport/status_metadata.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * 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. - * - */ - -#ifndef GRPC_CORE_LIB_TRANSPORT_STATUS_METADATA_H -#define GRPC_CORE_LIB_TRANSPORT_STATUS_METADATA_H - -#include <grpc/support/port_platform.h> - -#include <grpc/status.h> - -#include "src/core/lib/transport/metadata.h" -#include "src/core/lib/transport/static_metadata.h" - -grpc_status_code grpc_get_status_code_from_metadata(grpc_mdelem md); - -/** Get a grpc_mdelem of grpc-status: X where X is the numeric value of - status_code. - - The returned elem is owned by the caller. */ -grpc_mdelem grpc_get_reffed_status_elem_slowpath(int status_code); -inline grpc_mdelem grpc_get_reffed_status_elem(int status_code) { - switch (status_code) { - case 0: - return GRPC_MDELEM_GRPC_STATUS_0; - case 1: - return GRPC_MDELEM_GRPC_STATUS_1; - case 2: - return GRPC_MDELEM_GRPC_STATUS_2; - } - return grpc_get_reffed_status_elem_slowpath(status_code); -} - -#endif /* GRPC_CORE_LIB_TRANSPORT_STATUS_METADATA_H */ diff --git a/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc b/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc index 274006383f..f65586745b 100644 --- a/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc +++ b/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc @@ -23,83 +23,215 @@ #include <stdio.h> #include <string.h> +#include <grpc/support/log.h> + #include "src/core/lib/gpr/string.h" -static int64_t round_up(int64_t x, int64_t divisor) { - return (x / divisor + (x % divisor != 0)) * divisor; +namespace grpc_core { + +namespace { + +int64_t DivideRoundingUp(int64_t dividend, int64_t divisor) { + return (dividend + divisor - 1) / divisor; } -/* round an integer up to the next value with three significant figures */ -static int64_t round_up_to_three_sig_figs(int64_t x) { - if (x < 1000) return x; - if (x < 10000) return round_up(x, 10); - if (x < 100000) return round_up(x, 100); - if (x < 1000000) return round_up(x, 1000); - if (x < 10000000) return round_up(x, 10000); - if (x < 100000000) return round_up(x, 100000); - if (x < 1000000000) return round_up(x, 1000000); - return round_up(x, 10000000); +constexpr int64_t kSecondsPerMinute = 60; +constexpr int64_t kMinutesPerHour = 60; +constexpr int64_t kSecondsPerHour = kSecondsPerMinute * kMinutesPerHour; +constexpr int64_t kMaxHours = 27000; + +bool IsAllSpace(const uint8_t* p, const uint8_t* end) { + while (p != end && *p == ' ') p++; + return p == end; } -/* encode our minimum viable timeout value */ -static void enc_tiny(char* buffer) { memcpy(buffer, "1n", 3); } +} // namespace -/* encode our maximum timeout value, about 1157 days */ -static void enc_huge(char* buffer) { memcpy(buffer, "99999999S", 10); } +Timeout Timeout::FromDuration(grpc_millis duration) { + return Timeout::FromMillis(duration); +} -static void enc_ext(char* buffer, int64_t value, char ext) { - int n = int64_ttoa(value, buffer); - buffer[n] = ext; - buffer[n + 1] = 0; +double Timeout::RatioVersus(Timeout other) const { + double a = AsDuration(); + double b = other.AsDuration(); + if (b == 0) { + if (a > 0) return 100; + if (a < 0) return -100; + return 0; + } + return 100 * (a / b - 1); } -static void enc_seconds(char* buffer, int64_t sec) { - sec = round_up_to_three_sig_figs(sec); - if (sec % 3600 == 0) { - enc_ext(buffer, sec / 3600, 'H'); - } else if (sec % 60 == 0) { - enc_ext(buffer, sec / 60, 'M'); - } else { - enc_ext(buffer, sec, 'S'); +grpc_millis Timeout::AsDuration() const { + grpc_millis value = value_; + switch (unit_) { + case Unit::kNanoseconds: + return 0; + case Unit::kMilliseconds: + return value; + case Unit::kTenMilliseconds: + return value * 10; + case Unit::kHundredMilliseconds: + return value * 100; + case Unit::kSeconds: + return value * 1000; + case Unit::kTenSeconds: + return value * 10000; + case Unit::kHundredSeconds: + return value * 100000; + case Unit::kMinutes: + return value * 1000 * kSecondsPerMinute; + case Unit::kTenMinutes: + return value * 10000 * kSecondsPerMinute; + case Unit::kHundredMinutes: + return value * 100000 * kSecondsPerMinute; + case Unit::kHours: + return value * 1000 * kSecondsPerHour; } + GPR_UNREACHABLE_CODE(return -1); } -static void enc_millis(char* buffer, int64_t x) { - x = round_up_to_three_sig_figs(x); - if (x < GPR_MS_PER_SEC) { - enc_ext(buffer, x, 'm'); +Slice Timeout::Encode() const { + char buf[10]; + char* p = buf; + uint16_t n = value_; + int digits; + if (n >= 10000) { + digits = 5; + } else if (n >= 1000) { + digits = 4; + } else if (n >= 100) { + digits = 3; + } else if (n >= 10) { + digits = 2; } else { - if (x % GPR_MS_PER_SEC == 0) { - enc_seconds(buffer, x / GPR_MS_PER_SEC); - } else { - enc_ext(buffer, x, 'm'); + digits = 1; + } + switch (digits) { + case 5: + *p++ = '0' + n / 10000; + n %= 10000; + Y_ABSL_FALLTHROUGH_INTENDED; + case 4: + *p++ = '0' + n / 1000; + n %= 1000; + Y_ABSL_FALLTHROUGH_INTENDED; + case 3: + *p++ = '0' + n / 100; + n %= 100; + Y_ABSL_FALLTHROUGH_INTENDED; + case 2: + *p++ = '0' + n / 10; + n %= 10; + Y_ABSL_FALLTHROUGH_INTENDED; + case 1: + *p++ = '0' + n; + } + switch (unit_) { + case Unit::kNanoseconds: + *p++ = 'n'; + break; + case Unit::kHundredMilliseconds: + *p++ = '0'; + Y_ABSL_FALLTHROUGH_INTENDED; + case Unit::kTenMilliseconds: + *p++ = '0'; + Y_ABSL_FALLTHROUGH_INTENDED; + case Unit::kMilliseconds: + *p++ = 'm'; + break; + case Unit::kHundredSeconds: + *p++ = '0'; + Y_ABSL_FALLTHROUGH_INTENDED; + case Unit::kTenSeconds: + *p++ = '0'; + Y_ABSL_FALLTHROUGH_INTENDED; + case Unit::kSeconds: + *p++ = 'S'; + break; + case Unit::kHundredMinutes: + *p++ = '0'; + Y_ABSL_FALLTHROUGH_INTENDED; + case Unit::kTenMinutes: + *p++ = '0'; + Y_ABSL_FALLTHROUGH_INTENDED; + case Unit::kMinutes: + *p++ = 'M'; + break; + case Unit::kHours: + *p++ = 'H'; + break; + } + return Slice::FromCopiedBuffer(buf, p - buf); +} + +Timeout Timeout::FromMillis(int64_t millis) { + if (millis <= 0) { + return Timeout(1, Unit::kNanoseconds); + } else if (millis < 1000) { + return Timeout(millis, Unit::kMilliseconds); + } else if (millis < 10000) { + int64_t value = DivideRoundingUp(millis, 10); + if (value % 100 != 0) return Timeout(value, Unit::kTenMilliseconds); + } else if (millis < 100000) { + int64_t value = DivideRoundingUp(millis, 100); + if (value % 10 != 0) return Timeout(value, Unit::kHundredMilliseconds); + } + return Timeout::FromSeconds(DivideRoundingUp(millis, 1000)); +} + +Timeout Timeout::FromSeconds(int64_t seconds) { + GPR_DEBUG_ASSERT(seconds != 0); + if (seconds < 1000) { + if (seconds % kSecondsPerMinute != 0) { + return Timeout(seconds, Unit::kSeconds); + } + } else if (seconds < 10000) { + int64_t value = DivideRoundingUp(seconds, 10); + if ((value * 10) % kSecondsPerMinute != 0) { + return Timeout(value, Unit::kTenSeconds); + } + } else if (seconds < 100000) { + int64_t value = DivideRoundingUp(seconds, 100); + if ((value * 100) % kSecondsPerMinute != 0) { + return Timeout(value, Unit::kHundredSeconds); } } + return Timeout::FromMinutes(DivideRoundingUp(seconds, kSecondsPerMinute)); } -void grpc_http2_encode_timeout(grpc_millis timeout, char* buffer) { - const grpc_millis kMaxTimeout = 99999999000; - if (timeout <= 0) { - enc_tiny(buffer); - } else if (timeout < 1000 * GPR_MS_PER_SEC) { - enc_millis(buffer, timeout); - } else if (timeout >= kMaxTimeout) { - enc_huge(buffer); - } else { - enc_seconds(buffer, - timeout / GPR_MS_PER_SEC + (timeout % GPR_MS_PER_SEC != 0)); +Timeout Timeout::FromMinutes(int64_t minutes) { + GPR_DEBUG_ASSERT(minutes != 0); + if (minutes < 1000) { + if (minutes % kMinutesPerHour != 0) { + return Timeout(minutes, Unit::kMinutes); + } + } else if (minutes < 10000) { + int64_t value = DivideRoundingUp(minutes, 10); + if ((value * 10) % kMinutesPerHour != 0) { + return Timeout(value, Unit::kTenMinutes); + } + } else if (minutes < 100000) { + int64_t value = DivideRoundingUp(minutes, 100); + if ((value * 100) % kMinutesPerHour != 0) { + return Timeout(value, Unit::kHundredMinutes); + } } + return Timeout::FromHours(DivideRoundingUp(minutes, kMinutesPerHour)); } -static int is_all_whitespace(const char* p, const char* end) { - while (p != end && *p == ' ') p++; - return p == end; +Timeout Timeout::FromHours(int64_t hours) { + GPR_DEBUG_ASSERT(hours != 0); + if (hours < kMaxHours) { + return Timeout(hours, Unit::kHours); + } + return Timeout(kMaxHours, Unit::kHours); } -int grpc_http2_decode_timeout(const grpc_slice& text, grpc_millis* timeout) { +y_absl::optional<grpc_millis> ParseTimeout(const Slice& text) { grpc_millis x = 0; - const uint8_t* p = GRPC_SLICE_START_PTR(text); - const uint8_t* end = GRPC_SLICE_END_PTR(text); + const uint8_t* p = text.begin(); + const uint8_t* end = text.end(); int have_digit = 0; /* skip whitespace */ for (; p != end && *p == ' '; p++) { @@ -111,41 +243,43 @@ int grpc_http2_decode_timeout(const grpc_slice& text, grpc_millis* timeout) { /* spec allows max. 8 digits, but we allow values up to 1,000,000,000 */ if (x >= (100 * 1000 * 1000)) { if (x != (100 * 1000 * 1000) || digit != 0) { - *timeout = GRPC_MILLIS_INF_FUTURE; - return 1; + return GRPC_MILLIS_INF_FUTURE; } } x = x * 10 + digit; } - if (!have_digit) return 0; + if (!have_digit) return y_absl::nullopt; /* skip whitespace */ for (; p != end && *p == ' '; p++) { } - if (p == end) return 0; + if (p == end) return y_absl::nullopt; /* decode unit specifier */ + int64_t timeout; switch (*p) { case 'n': - *timeout = x / GPR_NS_PER_MS + (x % GPR_NS_PER_MS != 0); + timeout = x / GPR_NS_PER_MS + (x % GPR_NS_PER_MS != 0); break; case 'u': - *timeout = x / GPR_US_PER_MS + (x % GPR_US_PER_MS != 0); + timeout = x / GPR_US_PER_MS + (x % GPR_US_PER_MS != 0); break; case 'm': - *timeout = x; + timeout = x; break; case 'S': - *timeout = x * GPR_MS_PER_SEC; + timeout = x * GPR_MS_PER_SEC; break; case 'M': - *timeout = x * 60 * GPR_MS_PER_SEC; + timeout = x * 60 * GPR_MS_PER_SEC; break; case 'H': - *timeout = x * 60 * 60 * GPR_MS_PER_SEC; + timeout = x * 60 * 60 * GPR_MS_PER_SEC; break; default: - return 0; + return y_absl::nullopt; } p++; - return is_all_whitespace(reinterpret_cast<const char*>(p), - reinterpret_cast<const char*>(end)); + if (!IsAllSpace(p, end)) return y_absl::nullopt; + return timeout; } + +} // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.h b/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.h index c87ff39d49..c7f29fbf18 100644 --- a/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.h +++ b/contrib/libs/grpc/src/core/lib/transport/timeout_encoding.h @@ -21,18 +21,48 @@ #include <grpc/support/port_platform.h> -#include <grpc/slice.h> -#include <grpc/support/time.h> - -#include "src/core/lib/gpr/string.h" #include "src/core/lib/iomgr/exec_ctx.h" +#include "src/core/lib/slice/slice.h" + +namespace grpc_core { + +class Timeout { + public: + static Timeout FromDuration(grpc_millis duration); + + // Computes: 100 * ((this - other) / other) + double RatioVersus(Timeout other) const; + Slice Encode() const; + grpc_millis AsDuration() const; + + private: + enum class Unit : uint8_t { + kNanoseconds, + kMilliseconds, + kTenMilliseconds, + kHundredMilliseconds, + kSeconds, + kTenSeconds, + kHundredSeconds, + kMinutes, + kTenMinutes, + kHundredMinutes, + kHours, + }; + + Timeout(uint16_t value, Unit unit) : value_(value), unit_(unit) {} + + static Timeout FromMillis(int64_t millis); + static Timeout FromSeconds(int64_t seconds); + static Timeout FromMinutes(int64_t minutes); + static Timeout FromHours(int64_t hours); + + uint16_t value_; + Unit unit_; +}; -#define GRPC_HTTP2_TIMEOUT_ENCODE_MIN_BUFSIZE 10 +y_absl::optional<grpc_millis> ParseTimeout(const Slice& text); -/* Encode/decode timeouts to the GRPC over HTTP/2 format; - encoding may round up arbitrarily. If the timeout is larger than about 1157 - days, it will be capped and "99999999S" will be sent on the wire. */ -void grpc_http2_encode_timeout(grpc_millis timeout, char* buffer); -int grpc_http2_decode_timeout(const grpc_slice& text, grpc_millis* timeout); +} // namespace grpc_core #endif /* GRPC_CORE_LIB_TRANSPORT_TIMEOUT_ENCODING_H */ diff --git a/contrib/libs/grpc/src/core/lib/transport/transport.h b/contrib/libs/grpc/src/core/lib/transport/transport.h index c1b4d19c55..b7e7d0547f 100644 --- a/contrib/libs/grpc/src/core/lib/transport/transport.h +++ b/contrib/libs/grpc/src/core/lib/transport/transport.h @@ -24,13 +24,13 @@ #include <stddef.h> #include "src/core/lib/channel/context.h" -#include "src/core/lib/gprpp/arena.h" #include "src/core/lib/gprpp/orphanable.h" #include "src/core/lib/iomgr/call_combiner.h" #include "src/core/lib/iomgr/endpoint.h" #include "src/core/lib/iomgr/polling_entity.h" #include "src/core/lib/iomgr/pollset.h" #include "src/core/lib/iomgr/pollset_set.h" +#include "src/core/lib/resource_quota/arena.h" #include "src/core/lib/slice/slice_internal.h" #include "src/core/lib/transport/byte_stream.h" #include "src/core/lib/transport/connectivity_state.h" diff --git a/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc b/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc index d03a3b3886..5035599a9a 100644 --- a/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc +++ b/contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc @@ -40,47 +40,14 @@ /* These routines are here to facilitate debugging - they produce string representations of various transport data structures */ -namespace { -class MetadataListEncoder { - public: - explicit MetadataListEncoder(std::vector<TString>* out) : out_(out) {} - void Encode(const grpc_mdelem& md) { - MaybeAddComma(); - out_->push_back("key="); - char* dump = grpc_dump_slice(GRPC_MDKEY(md), GPR_DUMP_HEX | GPR_DUMP_ASCII); - out_->push_back(dump); - gpr_free(dump); - out_->push_back(" value="); - dump = grpc_dump_slice(GRPC_MDVALUE(md), GPR_DUMP_HEX | GPR_DUMP_ASCII); - out_->push_back(dump); - gpr_free(dump); - } - - void Encode(grpc_core::GrpcTimeoutMetadata, grpc_millis deadline) { - MaybeAddComma(); - out_->push_back(y_absl::StrFormat("deadline=%" PRId64, deadline)); - } - - template <typename Which> - void Encode(Which, const typename Which::ValueType& value) { - MaybeAddComma(); - out_->push_back( - y_absl::StrCat(Which::key(), "=", Which::DisplayValue(value))); - } - - private: - void MaybeAddComma() { - if (out_->size() != initial_size_) out_->push_back(", "); - } - std::vector<TString>* const out_; - const size_t initial_size_ = out_->size(); -}; -} // namespace - static void put_metadata_list(const grpc_metadata_batch& md, std::vector<TString>* out) { - MetadataListEncoder encoder(out); - md.Encode(&encoder); + bool first = true; + md.Log([out, &first](y_absl::string_view key, y_absl::string_view value) { + if (!first) out->push_back(", "); + first = false; + out->push_back(y_absl::StrCat(key, "=", value)); + }); } TString grpc_transport_stream_op_batch_string( diff --git a/contrib/libs/grpc/src/core/lib/uri/uri_parser.cc b/contrib/libs/grpc/src/core/lib/uri/uri_parser.cc index 2885957883..80317afa9c 100644 --- a/contrib/libs/grpc/src/core/lib/uri/uri_parser.cc +++ b/contrib/libs/grpc/src/core/lib/uri/uri_parser.cc @@ -1,20 +1,18 @@ -/* - * - * 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 <grpc/support/port_platform.h> @@ -36,14 +34,127 @@ namespace grpc_core { namespace { -// Checks if this string is made up of pchars, '/', '?', and '%' exclusively. + +// Returns true for any sub-delim character, as defined in: +// https://datatracker.ietf.org/doc/html/rfc3986#section-2.2 +bool IsSubDelimChar(char c) { + switch (c) { + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case '=': + return true; + } + return false; +} + +// Returns true for any unreserved character, as defined in: +// https://datatracker.ietf.org/doc/html/rfc3986#section-2.3 +bool IsUnreservedChar(char c) { + if (y_absl::ascii_isalnum(c)) return true; + switch (c) { + case '-': + case '.': + case '_': + case '~': + return true; + } + return false; +} + +// Returns true for any character in scheme, as defined in: +// https://datatracker.ietf.org/doc/html/rfc3986#section-3.1 +bool IsSchemeChar(char c) { + if (y_absl::ascii_isalnum(c)) return true; + switch (c) { + case '+': + case '-': + case '.': + return true; + } + return false; +} + +// Returns true for any character in authority, as defined in: +// https://datatracker.ietf.org/doc/html/rfc3986#section-3.2 +bool IsAuthorityChar(char c) { + if (IsUnreservedChar(c)) return true; + if (IsSubDelimChar(c)) return true; + switch (c) { + case ':': + case '[': + case ']': + case '@': + return true; + } + return false; +} + +// Returns true for any character in pchar, as defined in: +// https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 +bool IsPChar(char c) { + if (IsUnreservedChar(c)) return true; + if (IsSubDelimChar(c)) return true; + switch (c) { + case ':': + case '@': + return true; + } + return false; +} + +// Returns true for any character allowed in a URI path, as defined in: +// https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 +bool IsPathChar(char c) { return IsPChar(c) || c == '/'; } + +// Returns true for any character allowed in a URI query or fragment, +// as defined in: // See https://tools.ietf.org/html/rfc3986#section-3.4 -bool IsPCharString(y_absl::string_view str) { - return (str.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "0123456789" - "?/:@\\-._~!$&'()*+,;=%") == - y_absl::string_view::npos); +bool IsQueryOrFragmentChar(char c) { + return IsPChar(c) || c == '/' || c == '?'; +} + +// Same as IsQueryOrFragmentChar(), but excludes '&' and '='. +bool IsQueryKeyOrValueChar(char c) { + return c != '&' && c != '=' && IsQueryOrFragmentChar(c); +} + +// Returns a copy of str, percent-encoding any character for which +// is_allowed_char() returns false. +TString PercentEncode(y_absl::string_view str, + std::function<bool(char)> is_allowed_char) { + TString out; + for (char c : str) { + if (!is_allowed_char(c)) { + TString hex = y_absl::BytesToHexString(y_absl::string_view(&c, 1)); + GPR_ASSERT(hex.size() == 2); + // BytesToHexString() returns lower case, but + // https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2.1 says + // to prefer upper-case. + y_absl::AsciiStrToUpper(&hex); + out.push_back('%'); + out.append(hex); + } else { + out.push_back(c); + } + } + return out; +} + +// Checks if this string is made up of query/fragment chars and '%' exclusively. +// See https://tools.ietf.org/html/rfc3986#section-3.4 +bool IsQueryOrFragmentString(y_absl::string_view str) { + for (char c : str) { + if (!IsQueryOrFragmentChar(c) && c != '%') return false; + } + return true; } y_absl::Status MakeInvalidURIStatus(y_absl::string_view part_name, @@ -52,8 +163,13 @@ y_absl::Status MakeInvalidURIStatus(y_absl::string_view part_name, return y_absl::InvalidArgumentError(y_absl::StrFormat( "Could not parse '%s' from uri '%s'. %s", part_name, uri, extra)); } + } // namespace +TString URI::PercentEncodePath(y_absl::string_view str) { + return PercentEncode(str, IsPathChar); +} + // Similar to `grpc_permissive_percent_decode_slice`, this %-decodes all valid // triplets, and passes through the rest verbatim. TString URI::PercentDecode(y_absl::string_view str) { @@ -65,18 +181,14 @@ TString URI::PercentDecode(y_absl::string_view str) { out.reserve(str.size()); for (size_t i = 0; i < str.length(); i++) { unescaped = ""; - if (str[i] != '%') { - out += str[i]; - continue; - } - if (i + 3 >= str.length() || - !y_absl::CUnescape(y_absl::StrCat("\\x", str.substr(i + 1, 2)), - &unescaped) || - unescaped.length() > 1) { - out += str[i]; - } else { + if (str[i] == '%' && i + 3 <= str.length() && + y_absl::CUnescape(y_absl::StrCat("\\x", str.substr(i + 1, 2)), + &unescaped) && + unescaped.length() == 1) { out += unescaped[0]; i += 2; + } else { + out += str[i]; } } return out; @@ -86,11 +198,11 @@ y_absl::StatusOr<URI> URI::Parse(y_absl::string_view uri_text) { y_absl::StatusOr<TString> decoded; y_absl::string_view remaining = uri_text; // parse scheme - size_t idx = remaining.find(':'); - if (idx == remaining.npos || idx == 0) { + size_t offset = remaining.find(':'); + if (offset == remaining.npos || offset == 0) { return MakeInvalidURIStatus("scheme", uri_text, "Scheme not found."); } - TString scheme(remaining.substr(0, idx)); + TString scheme(remaining.substr(0, offset)); if (scheme.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+-.") != TString::npos) { @@ -102,30 +214,38 @@ y_absl::StatusOr<URI> URI::Parse(y_absl::string_view uri_text) { "scheme", uri_text, "Scheme must begin with an alpha character [A-Za-z]."); } - remaining.remove_prefix(scheme.length() + 1); + remaining.remove_prefix(offset + 1); // parse authority TString authority; - if (y_absl::StartsWith(remaining, "//")) { - remaining.remove_prefix(2); - authority = - PercentDecode(remaining.substr(0, remaining.find_first_of("/?#"))); - remaining.remove_prefix(authority.length()); + if (y_absl::ConsumePrefix(&remaining, "//")) { + offset = remaining.find_first_of("/?#"); + authority = PercentDecode(remaining.substr(0, offset)); + if (offset == remaining.npos) { + remaining = ""; + } else { + remaining.remove_prefix(offset); + } } // parse path TString path; if (!remaining.empty()) { - path = PercentDecode(remaining.substr(0, remaining.find_first_of("?#"))); - remaining.remove_prefix(path.length()); + offset = remaining.find_first_of("?#"); + path = PercentDecode(remaining.substr(0, offset)); + if (offset == remaining.npos) { + remaining = ""; + } else { + remaining.remove_prefix(offset); + } } // parse query std::vector<QueryParam> query_param_pairs; - if (!remaining.empty() && remaining[0] == '?') { - remaining.remove_prefix(1); - y_absl::string_view tmp_query = remaining.substr(0, remaining.find('#')); + if (y_absl::ConsumePrefix(&remaining, "?")) { + offset = remaining.find('#'); + y_absl::string_view tmp_query = remaining.substr(0, offset); if (tmp_query.empty()) { return MakeInvalidURIStatus("query", uri_text, "Invalid query string."); } - if (!IsPCharString(tmp_query)) { + if (!IsQueryOrFragmentString(tmp_query)) { return MakeInvalidURIStatus("query string", uri_text, "Query string contains invalid characters."); } @@ -136,12 +256,15 @@ y_absl::StatusOr<URI> URI::Parse(y_absl::string_view uri_text) { query_param_pairs.push_back({PercentDecode(possible_kv.first), PercentDecode(possible_kv.second)}); } - remaining.remove_prefix(tmp_query.length()); + if (offset == remaining.npos) { + remaining = ""; + } else { + remaining.remove_prefix(offset); + } } TString fragment; - if (!remaining.empty() && remaining[0] == '#') { - remaining.remove_prefix(1); - if (!IsPCharString(remaining)) { + if (y_absl::ConsumePrefix(&remaining, "#")) { + if (!IsQueryOrFragmentString(remaining)) { return MakeInvalidURIStatus("fragment", uri_text, "Fragment contains invalid characters."); } @@ -151,6 +274,18 @@ y_absl::StatusOr<URI> URI::Parse(y_absl::string_view uri_text) { std::move(query_param_pairs), std::move(fragment)); } +y_absl::StatusOr<URI> URI::Create(TString scheme, TString authority, + TString path, + std::vector<QueryParam> query_parameter_pairs, + TString fragment) { + if (!authority.empty() && !path.empty() && path[0] != '/') { + return y_absl::InvalidArgumentError( + "if authority is present, path must start with a '/'"); + } + return URI(std::move(scheme), std::move(authority), std::move(path), + std::move(query_parameter_pairs), std::move(fragment)); +} + URI::URI(TString scheme, TString authority, TString path, std::vector<QueryParam> query_parameter_pairs, TString fragment) : scheme_(std::move(scheme)), @@ -188,4 +323,39 @@ URI& URI::operator=(const URI& other) { } return *this; } + +namespace { + +// A pair formatter for use with y_absl::StrJoin() for formatting query params. +struct QueryParameterFormatter { + void operator()(TString* out, const URI::QueryParam& query_param) const { + out->append( + y_absl::StrCat(PercentEncode(query_param.key, IsQueryKeyOrValueChar), "=", + PercentEncode(query_param.value, IsQueryKeyOrValueChar))); + } +}; + +} // namespace + +TString URI::ToString() const { + std::vector<TString> parts = {PercentEncode(scheme_, IsSchemeChar), ":"}; + if (!authority_.empty()) { + parts.emplace_back("//"); + parts.emplace_back(PercentEncode(authority_, IsAuthorityChar)); + } + if (!path_.empty()) { + parts.emplace_back(PercentEncode(path_, IsPathChar)); + } + if (!query_parameter_pairs_.empty()) { + parts.push_back("?"); + parts.push_back( + y_absl::StrJoin(query_parameter_pairs_, "&", QueryParameterFormatter())); + } + if (!fragment_.empty()) { + parts.push_back("#"); + parts.push_back(PercentEncode(fragment_, IsQueryOrFragmentChar)); + } + return y_absl::StrJoin(parts, ""); +} + } // namespace grpc_core diff --git a/contrib/libs/grpc/src/core/lib/uri/uri_parser.h b/contrib/libs/grpc/src/core/lib/uri/uri_parser.h index b204ffe508..897f899532 100644 --- a/contrib/libs/grpc/src/core/lib/uri/uri_parser.h +++ b/contrib/libs/grpc/src/core/lib/uri/uri_parser.h @@ -1,20 +1,18 @@ -/* - * - * 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_LIB_URI_URI_PARSER_H #define GRPC_CORE_LIB_URI_URI_PARSER_H @@ -40,15 +38,23 @@ class URI { bool operator==(const QueryParam& other) const { return key == other.key && value == other.value; } + bool operator<(const QueryParam& other) const { + int c = key.compare(other.key); + if (c != 0) return c < 0; + return value < other.value; + } }; - // Creates an instance of GrpcURI by parsing an rfc3986 URI string. Returns - // an IllegalArgumentError on failure. + // Creates a URI by parsing an rfc3986 URI string. Returns an + // InvalidArgumentError on failure. static y_absl::StatusOr<URI> Parse(y_absl::string_view uri_text); - // Explicit construction by individual URI components - URI(TString scheme, TString authority, TString path, - std::vector<QueryParam> query_parameter_pairs, TString fragment_); + // Creates a URI from components. Returns an InvalidArgumentError on failure. + static y_absl::StatusOr<URI> Create( + TString scheme, TString authority, TString path, + std::vector<QueryParam> query_parameter_pairs, TString fragment); + URI() = default; + // Copy construction and assignment URI(const URI& other); URI& operator=(const URI& other); @@ -56,6 +62,8 @@ class URI { URI(URI&&) = default; URI& operator=(URI&&) = default; + static TString PercentEncodePath(y_absl::string_view str); + static TString PercentDecode(y_absl::string_view str); const TString& scheme() const { return scheme_; } @@ -76,7 +84,12 @@ class URI { } const TString& fragment() const { return fragment_; } + TString ToString() const; + private: + URI(TString scheme, TString authority, TString path, + std::vector<QueryParam> query_parameter_pairs, TString fragment); + TString scheme_; TString authority_; TString path_; @@ -86,4 +99,4 @@ class URI { }; } // namespace grpc_core -#endif /* GRPC_CORE_LIB_URI_URI_PARSER_H */ +#endif // GRPC_CORE_LIB_URI_URI_PARSER_H diff --git a/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc b/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc index 8a31816e40..72a7989bdf 100644 --- a/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc +++ b/contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc @@ -27,8 +27,6 @@ void grpc_chttp2_plugin_init(void); void grpc_chttp2_plugin_shutdown(void); void grpc_client_channel_init(void); void grpc_client_channel_shutdown(void); -void grpc_inproc_plugin_init(void); -void grpc_inproc_plugin_shutdown(void); void grpc_resolver_fake_init(void); void grpc_resolver_fake_shutdown(void); void grpc_lb_policy_grpclb_init(void); @@ -64,6 +62,8 @@ void ServiceConfigParserShutdown(void); #ifndef GRPC_NO_XDS namespace grpc_core { +void RbacFilterInit(void); +void RbacFilterShutdown(void); void XdsClientGlobalInit(); void XdsClientGlobalShutdown(); } // namespace grpc_core @@ -99,7 +99,6 @@ void grpc_register_built_in_plugins(void) { grpc_register_plugin(grpc_core::ServiceConfigParserInit, grpc_core::ServiceConfigParserShutdown); grpc_register_plugin(grpc_client_channel_init, grpc_client_channel_shutdown); - grpc_register_plugin(grpc_inproc_plugin_init, grpc_inproc_plugin_shutdown); grpc_register_plugin(grpc_resolver_fake_init, grpc_resolver_fake_shutdown); grpc_register_plugin(grpc_lb_policy_grpclb_init, grpc_lb_policy_grpclb_shutdown); @@ -128,6 +127,8 @@ void grpc_register_built_in_plugins(void) { grpc_register_plugin(grpc_core::FaultInjectionFilterInit, grpc_core::FaultInjectionFilterShutdown); #ifndef GRPC_NO_XDS + // rbac_filter is being guarded with GRPC_NO_XDS to avoid a dependency on the re2 library by default + grpc_register_plugin(grpc_core::RbacFilterInit, grpc_core::RbacFilterShutdown); grpc_register_plugin(grpc_core::XdsClientGlobalInit, grpc_core::XdsClientGlobalShutdown); grpc_register_plugin(grpc_certificate_provider_registry_init, diff --git a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc index b82d76fbff..93167bca5f 100644 --- a/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +++ b/contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc @@ -717,11 +717,11 @@ alts_handshaker_client* alts_grpc_handshaker_client_create( channel, nullptr, GRPC_PROPAGATE_DEFAULTS, interested_parties, grpc_slice_from_static_string(ALTS_SERVICE_METHOD), &slice, GRPC_MILLIS_INF_FUTURE, nullptr); + grpc_slice_unref_internal(slice); GRPC_CLOSURE_INIT(&client->on_handshaker_service_resp_recv, grpc_cb, client, grpc_schedule_on_exec_ctx); GRPC_CLOSURE_INIT(&client->on_status_received, on_status_received, client, grpc_schedule_on_exec_ctx); - grpc_slice_unref_internal(slice); return &client->base; } diff --git a/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session.h b/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session.h index 108c0cd133..adf31aebd3 100644 --- a/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session.h +++ b/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session.h @@ -21,11 +21,9 @@ #include <grpc/support/port_platform.h> -#include <grpc/slice.h> - -extern "C" { #include <openssl/ssl.h> -} + +#include <grpc/slice.h> #include "src/core/lib/gprpp/ref_counted.h" diff --git a/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session_cache.h b/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session_cache.h index 5db782913e..b5979df6ea 100644 --- a/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session_cache.h +++ b/contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session_cache.h @@ -21,14 +21,12 @@ #include <grpc/support/port_platform.h> -#include <grpc/slice.h> -#include <grpc/support/sync.h> +#include <map> -extern "C" { #include <openssl/ssl.h> -} -#include <map> +#include <grpc/slice.h> +#include <grpc/support/sync.h> #include "src/core/lib/gprpp/memory.h" #include "src/core/lib/gprpp/ref_counted.h" diff --git a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc index 0213d56af4..aa21c04d6e 100644 --- a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc +++ b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc @@ -35,6 +35,15 @@ #include <util/generic/string.h> +#include <openssl/bio.h> +#include <openssl/crypto.h> /* For OPENSSL_free */ +#include <openssl/engine.h> +#include <openssl/err.h> +#include <openssl/ssl.h> +#include <openssl/tls1.h> +#include <openssl/x509.h> +#include <openssl/x509v3.h> + #include "y_absl/strings/match.h" #include "y_absl/strings/string_view.h" @@ -45,17 +54,6 @@ #include <grpc/support/sync.h> #include <grpc/support/thd_id.h> -extern "C" { -#include <openssl/bio.h> -#include <openssl/crypto.h> /* For OPENSSL_free */ -#include <openssl/engine.h> -#include <openssl/err.h> -#include <openssl/ssl.h> -#include <openssl/tls1.h> -#include <openssl/x509.h> -#include <openssl/x509v3.h> -} - #include "src/core/lib/gpr/useful.h" #include "src/core/tsi/ssl/session_cache/ssl_session_cache.h" #include "src/core/tsi/ssl_types.h" @@ -1933,6 +1931,14 @@ static int server_handshaker_factory_new_session_callback( return 1; } +static int verify_cb(int ok, X509_STORE_CTX* ctx) { + int cert_error = X509_STORE_CTX_get_error(ctx); + if (cert_error != 0) { + gpr_log(GPR_ERROR, "Certificate verify failed with code %d", cert_error); + } + return ok; +} + /* --- tsi_ssl_handshaker_factory constructors. --- */ static tsi_ssl_handshaker_factory_vtable client_handshaker_factory_vtable = { @@ -2053,7 +2059,24 @@ tsi_result tsi_create_ssl_client_handshaker_factory_with_options( } else { SSL_CTX_set_verify(ssl_context, SSL_VERIFY_PEER, nullptr); } - /* TODO(jboeuf): Add revocation verification. */ + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + if (options->crl_directory != nullptr && + strcmp(options->crl_directory, "") != 0) { + gpr_log(GPR_INFO, "enabling client CRL checking with path: %s", + options->crl_directory); + X509_STORE* cert_store = SSL_CTX_get_cert_store(ssl_context); + X509_STORE_set_verify_cb(cert_store, verify_cb); + if (!X509_STORE_load_locations(cert_store, nullptr, + options->crl_directory)) { + gpr_log(GPR_ERROR, "Failed to load CRL File from directory."); + } else { + X509_VERIFY_PARAM* param = X509_STORE_get0_param(cert_store); + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + gpr_log(GPR_INFO, "enabled client side CRL checking."); + } + } +#endif *factory = impl; return TSI_OK; @@ -2215,7 +2238,24 @@ tsi_result tsi_create_ssl_server_handshaker_factory_with_options( nullptr); break; } - /* TODO(jboeuf): Add revocation verification. */ + +#if OPENSSL_VERSION_NUMBER >= 0x10100000 + if (options->crl_directory != nullptr && + strcmp(options->crl_directory, "") != 0) { + gpr_log(GPR_INFO, "enabling server CRL checking with path %s", + options->crl_directory); + X509_STORE* cert_store = SSL_CTX_get_cert_store(impl->ssl_contexts[i]); + X509_STORE_set_verify_cb(cert_store, verify_cb); + if (!X509_STORE_load_locations(cert_store, nullptr, + options->crl_directory)) { + gpr_log(GPR_ERROR, "Failed to load CRL File from directory."); + } else { + X509_VERIFY_PARAM* param = X509_STORE_get0_param(cert_store); + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK); + gpr_log(GPR_INFO, "enabled server CRL checking."); + } + } +#endif result = tsi_ssl_extract_x509_subject_names_from_pem_cert( options->pem_key_cert_pairs[i].cert_chain, diff --git a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.h b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.h index 88087e7a72..87a2b9da63 100644 --- a/contrib/libs/grpc/src/core/tsi/ssl_transport_security.h +++ b/contrib/libs/grpc/src/core/tsi/ssl_transport_security.h @@ -21,16 +21,14 @@ #include <grpc/support/port_platform.h> +#include <openssl/x509.h> + #include "y_absl/strings/string_view.h" #include <grpc/grpc_security_constants.h> #include "src/core/tsi/transport_security_interface.h" -extern "C" { -#include <openssl/x509.h> -} - /* Value for the TSI_CERTIFICATE_TYPE_PEER_PROPERTY property for X509 certs. */ #define TSI_X509_CERTIFICATE_TYPE "X509" @@ -159,6 +157,12 @@ struct tsi_ssl_client_handshaker_options { tsi_tls_version min_tls_version; tsi_tls_version max_tls_version; + /* The directory where all hashed CRL files enforced by the handshaker are + located. If the directory is invalid, CRL checking will fail open and just + log. An empty directory will not enable crl checking. Only OpenSSL version + > 1.1 is supported for CRL checking*/ + const char* crl_directory; + tsi_ssl_client_handshaker_options() : pem_key_cert_pair(nullptr), pem_root_certs(nullptr), @@ -169,7 +173,8 @@ struct tsi_ssl_client_handshaker_options { session_cache(nullptr), skip_server_certificate_verification(false), min_tls_version(tsi_tls_version::TSI_TLS1_2), - max_tls_version(tsi_tls_version::TSI_TLS1_3) {} + max_tls_version(tsi_tls_version::TSI_TLS1_3), + crl_directory(nullptr) {} }; /* Creates a client handshaker factory. @@ -289,6 +294,12 @@ struct tsi_ssl_server_handshaker_options { tsi_tls_version min_tls_version; tsi_tls_version max_tls_version; + /* The directory where all hashed CRL files are cached in the x.509 store and + * enforced by the handshaker are located. If the directory is invalid, CRL + * checking will fail open and just log. An empty directory will not enable + * crl checking. Only OpenSSL version > 1.1 is supported for CRL checking */ + const char* crl_directory; + tsi_ssl_server_handshaker_options() : pem_key_cert_pairs(nullptr), num_key_cert_pairs(0), @@ -300,7 +311,8 @@ struct tsi_ssl_server_handshaker_options { session_ticket_key(nullptr), session_ticket_key_size(0), min_tls_version(tsi_tls_version::TSI_TLS1_2), - max_tls_version(tsi_tls_version::TSI_TLS1_3) {} + max_tls_version(tsi_tls_version::TSI_TLS1_3), + crl_directory(nullptr) {} }; /* Creates a server handshaker factory. diff --git a/contrib/libs/grpc/src/cpp/common/channel_filter.cc b/contrib/libs/grpc/src/cpp/common/channel_filter.cc index 373aebf61b..739e2da74b 100644 --- a/contrib/libs/grpc/src/cpp/common/channel_filter.cc +++ b/contrib/libs/grpc/src/cpp/common/channel_filter.cc @@ -30,13 +30,14 @@ namespace grpc { // MetadataBatch -grpc_linked_mdelem* MetadataBatch::AddMetadata(const string& key, - const string& value) { - grpc_linked_mdelem* storage = new grpc_linked_mdelem; - storage->md = grpc_mdelem_from_slices(SliceFromCopiedString(key), - SliceFromCopiedString(value)); - GRPC_LOG_IF_ERROR("MetadataBatch::AddMetadata", batch_->LinkHead(storage)); - return storage; +void MetadataBatch::AddMetadata(const string& key, const string& value) { + batch_->Append(key, grpc_core::Slice::FromCopiedString(value), + [&](y_absl::string_view error, const grpc_core::Slice&) { + gpr_log(GPR_INFO, "%s", + y_absl::StrCat("MetadataBatch::AddMetadata error:", + error, " key=", key, " value=", value) + .c_str()); + }); } // ChannelData diff --git a/contrib/libs/grpc/src/cpp/common/channel_filter.h b/contrib/libs/grpc/src/cpp/common/channel_filter.h index 5364895e84..6e0830f977 100644 --- a/contrib/libs/grpc/src/cpp/common/channel_filter.h +++ b/contrib/libs/grpc/src/cpp/common/channel_filter.h @@ -51,10 +51,8 @@ class MetadataBatch { grpc_metadata_batch* batch() const { return batch_; } - /// Adds metadata and returns the newly allocated storage. - /// The caller takes ownership of the result, which must exist for the - /// lifetime of the gRPC call. - grpc_linked_mdelem* AddMetadata(const string& key, const string& value); + /// Adds metadata. + void AddMetadata(const string& key, const string& value); private: grpc_metadata_batch* batch_; // Not owned. diff --git a/contrib/libs/grpc/src/cpp/common/validate_service_config.cc b/contrib/libs/grpc/src/cpp/common/validate_service_config.cc index fa0c393792..e680d2c982 100644 --- a/contrib/libs/grpc/src/cpp/common/validate_service_config.cc +++ b/contrib/libs/grpc/src/cpp/common/validate_service_config.cc @@ -19,7 +19,7 @@ #include <grpc/grpc.h> #include <grpcpp/support/validate_service_config.h> -#include "src/core/ext/service_config/service_config.h" +#include "src/core/lib/service_config/service_config.h" namespace grpc { namespace experimental { diff --git a/contrib/libs/grpc/src/cpp/common/version_cc.cc b/contrib/libs/grpc/src/cpp/common/version_cc.cc index 8054bda78b..24bf9866c3 100644 --- a/contrib/libs/grpc/src/cpp/common/version_cc.cc +++ b/contrib/libs/grpc/src/cpp/common/version_cc.cc @@ -22,5 +22,5 @@ #include <grpcpp/grpcpp.h> namespace grpc { -TString Version() { return "1.43.2"; } +TString Version() { return "1.44.0"; } } // namespace grpc diff --git a/contrib/libs/grpc/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi b/contrib/libs/grpc/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi index 5f4a51f76f..54174b3c13 100644 --- a/contrib/libs/grpc/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi +++ b/contrib/libs/grpc/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi @@ -124,7 +124,9 @@ 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); - 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) + +cdef extern from "src/core/lib/address_utils/parse_address.h": + grpc_error_handle grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port); diff --git a/contrib/libs/grpc/src/python/grpcio/grpc/_grpcio_metadata.py b/contrib/libs/grpc/src/python/grpcio/grpc/_grpcio_metadata.py index 10322bde18..1ddb665169 100644 --- a/contrib/libs/grpc/src/python/grpcio/grpc/_grpcio_metadata.py +++ b/contrib/libs/grpc/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.43.2""" +__version__ = """1.44.0""" diff --git a/contrib/libs/grpc/src/python/grpcio_tests/tests/unit/_dns_resolver_test.py b/contrib/libs/grpc/src/python/grpcio_tests/tests/unit/_dns_resolver_test.py index f38a83b349..cc89dea1ef 100644 --- a/contrib/libs/grpc/src/python/grpcio_tests/tests/unit/_dns_resolver_test.py +++ b/contrib/libs/grpc/src/python/grpcio_tests/tests/unit/_dns_resolver_test.py @@ -50,7 +50,11 @@ class DNSResolverTest(unittest.TestCase): # NOTE(https://github.com/grpc/grpc/issues/18422) # In short, Gevent + C-Ares = Segfault. The C-Ares driver is not # supported by custom io manager like "gevent" - with grpc.insecure_channel('loopback4.unittest.grpc.io:%d' % + # NOTE(b/201064791): use loopback46.unittest.grpc.io since + # it returns the expected responses even when DNS64 dns servers + # are used on the test worker (and for purposes of this + # test the use of loopback4 vs loopback46 makes no difference). + with grpc.insecure_channel('loopback46.unittest.grpc.io:%d' % self._port) as channel: self.assertEqual( channel.unary_unary(_METHOD)( diff --git a/contrib/libs/grpc/test/core/util/port_server_client.cc b/contrib/libs/grpc/test/core/util/port_server_client.cc index 36124362c6..f5b5e28f95 100644 --- a/contrib/libs/grpc/test/core/util/port_server_client.cc +++ b/contrib/libs/grpc/test/core/util/port_server_client.cc @@ -58,7 +58,6 @@ static void freed_port_from_server(void* arg, grpc_error_handle /*error*/) { } void grpc_free_port_using_server(int port) { - grpc_httpcli_context context; grpc_httpcli_request req; grpc_httpcli_response rsp; freereq pr; @@ -84,9 +83,7 @@ void grpc_free_port_using_server(int port) { gpr_asprintf(&path, "/drop/%d", port); req.http.path = path; - grpc_httpcli_context_init(&context); - grpc_httpcli_get(&context, &pr.pops, grpc_core::ResourceQuota::Default(), - &req, + grpc_httpcli_get(&pr.pops, grpc_core::ResourceQuota::Default(), &req, grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC, GRPC_CLOSURE_CREATE(freed_port_from_server, &pr, grpc_schedule_on_exec_ctx), @@ -105,7 +102,6 @@ void grpc_free_port_using_server(int port) { } gpr_mu_unlock(pr.mu); - grpc_httpcli_context_destroy(&context); grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops), shutdown_closure); @@ -121,7 +117,6 @@ typedef struct portreq { int port = 0; int retries = 0; char* server = nullptr; - grpc_httpcli_context* ctx = nullptr; grpc_httpcli_response response = {}; } portreq; @@ -166,8 +161,7 @@ static void got_port_from_server(void* arg, grpc_error_handle error) { req.http.path = const_cast<char*>("/get"); grpc_http_response_destroy(&pr->response); pr->response = {}; - grpc_httpcli_get(pr->ctx, &pr->pops, grpc_core::ResourceQuota::Default(), - &req, + grpc_httpcli_get(&pr->pops, grpc_core::ResourceQuota::Default(), &req, grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC, GRPC_CLOSURE_CREATE(got_port_from_server, pr, grpc_schedule_on_exec_ctx), @@ -190,7 +184,6 @@ static void got_port_from_server(void* arg, grpc_error_handle error) { } int grpc_pick_port_using_server(void) { - grpc_httpcli_context context; grpc_httpcli_request req; portreq pr; grpc_closure* shutdown_closure; @@ -208,14 +201,11 @@ int grpc_pick_port_using_server(void) { grpc_schedule_on_exec_ctx); pr.port = -1; pr.server = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS); - pr.ctx = &context; req.host = const_cast<char*>(GRPC_PORT_SERVER_ADDRESS); req.http.path = const_cast<char*>("/get"); - grpc_httpcli_context_init(&context); - grpc_httpcli_get(&context, &pr.pops, grpc_core::ResourceQuota::Default(), - &req, + grpc_httpcli_get(&pr.pops, grpc_core::ResourceQuota::Default(), &req, grpc_core::ExecCtx::Get()->Now() + 30 * GPR_MS_PER_SEC, GRPC_CLOSURE_CREATE(got_port_from_server, &pr, grpc_schedule_on_exec_ctx), @@ -235,7 +225,6 @@ int grpc_pick_port_using_server(void) { gpr_mu_unlock(pr.mu); grpc_http_response_destroy(&pr.response); - grpc_httpcli_context_destroy(&context); grpc_pollset_shutdown(grpc_polling_entity_pollset(&pr.pops), shutdown_closure); diff --git a/contrib/libs/grpc/test/core/util/test_lb_policies.cc b/contrib/libs/grpc/test/core/util/test_lb_policies.cc index 17799626ae..059869cfd2 100644 --- a/contrib/libs/grpc/test/core/util/test_lb_policies.cc +++ b/contrib/libs/grpc/test/core/util/test_lb_policies.cc @@ -447,11 +447,11 @@ class FixedAddressLoadBalancingPolicy : public ForwardingLoadBalancingPolicy { config->address().c_str()); auto uri = URI::Parse(config->address()); args.config.reset(); - args.addresses.clear(); + args.addresses = ServerAddressList(); if (uri.ok()) { grpc_resolved_address address; GPR_ASSERT(grpc_parse_uri(*uri, &address)); - args.addresses.emplace_back(address, /*args=*/nullptr); + args.addresses->emplace_back(address, /*args=*/nullptr); } else { gpr_log(GPR_ERROR, "%s: could not parse URI (%s), using empty address list", |