aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2022-11-09 12:13:47 +0300
committerthegeorg <thegeorg@yandex-team.com>2022-11-09 12:13:47 +0300
commit80f5c1d76c74f49e72bece723f9c1b7a25852e70 (patch)
treed00038bca499594f3b058936272dea3b69bf822e /contrib/libs
parent41fc4a8aaa393fbb516c9e0edb6ffe98ab7097e5 (diff)
downloadydb-80f5c1d76c74f49e72bece723f9c1b7a25852e70.tar.gz
Update contrib/libs/grpc to 1.44.0
Diffstat (limited to 'contrib/libs')
-rw-r--r--contrib/libs/grpc/CMakeLists.txt45
-rw-r--r--contrib/libs/grpc/include/grpc/grpc_security.h10
-rw-r--r--contrib/libs/grpc/include/grpc/impl/codegen/compression_types.h2
-rw-r--r--contrib/libs/grpc/include/grpc/impl/codegen/grpc_types.h6
-rw-r--r--contrib/libs/grpc/include/grpcpp/create_channel_binder.h9
-rw-r--r--contrib/libs/grpc/include/grpcpp/impl/codegen/client_context.h2
-rw-r--r--contrib/libs/grpc/src/compiler/objective_c_generator_helpers.h26
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/backend_metric.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.cc130
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel.h16
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/client_channel_plugin.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/config_selector.h8
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/dynamic_filters.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.cc30
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/health/health_check_client.h6
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/http_connect_handshaker.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.cc29
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy.h22
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.cc7
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/address_filtering.h11
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc10
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc63
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h7
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc72
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/priority/priority.cc8
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc188
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/rls/rls.cc108
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc123
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h27
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/weighted_target/weighted_target.cc16
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc34
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc26
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc5
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc156
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/binder/binder_resolver.cc6
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc288
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h34
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc34
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc61
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc325
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h57
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc158
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc20
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h3
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc7
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc10
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc224
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_result_parsing.h4
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/retry_filter.cc101
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/retry_service_config.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/service_config_channel_arg_filter.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.cc28
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/client_channel/subchannel.h5
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/fault_injection/fault_injection_filter.cc85
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.cc14
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/fault_injection/service_config_parser.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/client/http_client_filter.cc174
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/client_authority_filter.cc32
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_compress_filter.cc182
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/message_compress/message_decompress_filter.cc30
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/http/server/http_server_filter.cc185
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/message_size/message_size_filter.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.cc157
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/rbac/rbac_filter.h74
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.cc605
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/rbac/rbac_service_config_parser.h70
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector.h5
-rw-r--r--contrib/libs/grpc/src/core/ext/filters/server_config_selector/server_config_selector_filter.cc17
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create.cc17
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/client/channel_create_impl.cc11
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.cc12
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/client/jni_utils.h6
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/server/binder_server.cc4
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/transport/binder_transport.cc67
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/binder/wire_format/wire_reader_impl.cc15
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/client/insecure/channel_create.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/server/chttp2_server.cc118
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_plugin.cc1
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/chttp2_transport.cc231
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/frame_data.cc1
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.cc620
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder.h228
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_index.h107
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc2
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_encoder_table.h2
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.cc51
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser.h1
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc95
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_parser_table.h26
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.cc46
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/internal.h33
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/parsing.cc6
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/popularity_count.h60
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/chttp2/transport/writing.cc163
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/inproc/inproc_plugin.cc4
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.cc74
-rw-r--r--contrib/libs/grpc/src/core/ext/transport/inproc/inproc_transport.h3
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.c61
-rw-r--r--contrib/libs/grpc/src/core/ext/upb-generated/envoy/extensions/filters/http/rbac/v3/rbac.upb.h146
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.c188
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/config/rbac/v3/rbac.upbdefs.h70
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.c56
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/rbac/v3/rbac.upbdefs.h40
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.c154
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/checked.upbdefs.h95
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.c58
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/eval.upbdefs.h55
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.c44
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/explain.upbdefs.h40
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.c153
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/syntax.upbdefs.h100
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.c75
-rw-r--r--contrib/libs/grpc/src/core/ext/upbdefs-generated/google/api/expr/v1alpha1/value.upbdefs.h55
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/upb_utils.h65
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_api.cc3539
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_api.h667
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.cc314
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_bootstrap.h35
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_certificate_provider.h1
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.cc108
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_channel_creds.h50
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_client.cc1578
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_client.h213
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_cluster.cc451
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_cluster.h111
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_common_types.cc388
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_common_types.h110
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_endpoint.cc364
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_endpoint.h135
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_http_filters.cc5
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.cc563
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_http_rbac_filter.h54
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_listener.cc1036
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_listener.h220
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_resource_type.cc (renamed from contrib/libs/grpc/src/core/ext/transport/chttp2/transport/hpack_utils.h)21
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_resource_type.h98
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_resource_type_impl.h87
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_route_config.cc993
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_route_config.h215
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_routing.cc19
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_routing.h13
-rw-r--r--contrib/libs/grpc/src/core/ext/xds/xds_server_config_fetcher.cc258
-rw-r--r--contrib/libs/grpc/src/core/lib/address_utils/parse_address.cc20
-rw-r--r--contrib/libs/grpc/src/core/lib/address_utils/parse_address.h5
-rw-r--r--contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.cc69
-rw-r--r--contrib/libs/grpc/src/core/lib/address_utils/sockaddr_utils.h17
-rw-r--r--contrib/libs/grpc/src/core/lib/backoff/backoff.cc34
-rw-r--r--contrib/libs/grpc/src/core/lib/backoff/backoff.h6
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/channel_args.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/channel_stack.cc8
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/channel_stack.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.cc14
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/channel_stack_builder.h11
-rw-r--r--contrib/libs/grpc/src/core/lib/channel/channelz.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/algorithm_metadata.h62
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/compression.cc130
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/compression_args.cc140
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/compression_args.h58
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/compression_internal.cc344
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/compression_internal.h133
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/message_compress.cc22
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/message_compress.h4
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/stream_compression.cc81
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/stream_compression.h117
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.cc231
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/stream_compression_gzip.h28
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.cc91
-rw-r--r--contrib/libs/grpc/src/core/lib/compression/stream_compression_identity.h29
-rw-r--r--contrib/libs/grpc/src/core/lib/gpr/useful.h4
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/bitset.h7
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/chunked_vector.h48
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/status_helper.cc48
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/status_helper.h25
-rw-r--r--contrib/libs/grpc/src/core/lib/gprpp/table.h11
-rw-r--r--contrib/libs/grpc/src/core/lib/http/httpcli.cc83
-rw-r--r--contrib/libs/grpc/src/core/lib/http/httpcli.h18
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/call_combiner.cc19
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/closure.h38
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/combiner.cc28
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/error.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/error.h3
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/event_engine/iomgr.cc5
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.cc6
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolved_address_internal.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/event_engine/resolver.cc114
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/exec_ctx.cc31
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/executor.cc11
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/fork_posix.cc5
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/iomgr_custom.cc5
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/iomgr_posix_cfstream.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/iomgr_windows.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/port.h4
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address.cc29
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address.h91
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.cc242
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address_custom.h120
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address_impl.h59
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.cc150
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address_posix.h47
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.cc169
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolve_address_windows.h47
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/resolved_address.h39
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_common.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.cc56
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix.h11
-rw-r--r--contrib/libs/grpc/src/core/lib/iomgr/unix_sockets_posix_noop.cc21
-rw-r--r--contrib/libs/grpc/src/core/lib/matchers/matchers.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/activity.h69
-rw-r--r--contrib/libs/grpc/src/core/lib/promise/detail/status.h5
-rw-r--r--contrib/libs/grpc/src/core/lib/resolver/resolver.cc (renamed from contrib/libs/grpc/src/core/ext/filters/client_channel/resolver.cc)42
-rw-r--r--contrib/libs/grpc/src/core/lib/resolver/resolver.h (renamed from contrib/libs/grpc/src/core/ext/filters/client_channel/resolver.h)87
-rw-r--r--contrib/libs/grpc/src/core/lib/resolver/resolver_factory.h (renamed from contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_factory.h)15
-rw-r--r--contrib/libs/grpc/src/core/lib/resolver/resolver_registry.cc (renamed from contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_registry.cc)5
-rw-r--r--contrib/libs/grpc/src/core/lib/resolver/resolver_registry.h (renamed from contrib/libs/grpc/src/core/ext/filters/client_channel/resolver_registry.h)9
-rw-r--r--contrib/libs/grpc/src/core/lib/resolver/server_address.cc (renamed from contrib/libs/grpc/src/core/ext/filters/client_channel/server_address.cc)2
-rw-r--r--contrib/libs/grpc/src/core/lib/resolver/server_address.h (renamed from contrib/libs/grpc/src/core/ext/filters/client_channel/server_address.h)8
-rw-r--r--contrib/libs/grpc/src/core/lib/resource_quota/api.h1
-rw-r--r--contrib/libs/grpc/src/core/lib/resource_quota/arena.cc (renamed from contrib/libs/grpc/src/core/lib/gprpp/arena.cc)29
-rw-r--r--contrib/libs/grpc/src/core/lib/resource_quota/arena.h (renamed from contrib/libs/grpc/src/core/lib/gprpp/arena.h)37
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.cc45
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/evaluate_args.h1
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.cc60
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/grpc_authorization_engine.h62
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/matchers.cc227
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/matchers.h211
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.cc442
-rw-r--r--contrib/libs/grpc/src/core/lib/security/authorization/rbac_policy.h170
-rw-r--r--contrib/libs/grpc/src/core/lib/security/context/security_context.cc6
-rw-r--r--contrib/libs/grpc/src/core/lib/security/context/security_context.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.cc10
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/composite/composite_credentials.h7
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/credentials.h30
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/credentials_metadata.cc61
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/external/aws_external_account_credentials.cc15
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.cc16
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/external/external_account_credentials.h9
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/external/url_external_account_credentials.cc5
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.cc9
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/fake/fake_credentials.h15
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/google_default/google_default_credentials.cc7
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.cc35
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/iam/iam_credentials.h11
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/jwt/json_token.cc10
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.cc44
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_credentials.h16
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/jwt/jwt_verifier.cc19
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc101
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/oauth2/oauth2_credentials.h28
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.cc13
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/plugin/plugin_credentials.h9
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/ssl/ssl_credentials.cc11
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc6
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h7
-rw-r--r--contrib/libs/grpc/src/core/lib/security/credentials/xds/xds_credentials.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/security_connector.h6
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.cc38
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/ssl_utils.h19
-rw-r--r--contrib/libs/grpc/src/core/lib/security/security_connector/tls/tls_security_connector.cc5
-rw-r--r--contrib/libs/grpc/src/core/lib/security/transport/auth_filters.h7
-rw-r--r--contrib/libs/grpc/src/core/lib/security/transport/client_auth_filter.cc86
-rw-r--r--contrib/libs/grpc/src/core/lib/security/transport/server_auth_filter.cc75
-rw-r--r--contrib/libs/grpc/src/core/lib/service_config/service_config.cc (renamed from contrib/libs/grpc/src/core/ext/service_config/service_config.cc)4
-rw-r--r--contrib/libs/grpc/src/core/lib/service_config/service_config.h (renamed from contrib/libs/grpc/src/core/ext/service_config/service_config.h)8
-rw-r--r--contrib/libs/grpc/src/core/lib/service_config/service_config_call_data.h (renamed from contrib/libs/grpc/src/core/ext/service_config/service_config_call_data.h)10
-rw-r--r--contrib/libs/grpc/src/core/lib/service_config/service_config_parser.cc (renamed from contrib/libs/grpc/src/core/ext/service_config/service_config_parser.cc)2
-rw-r--r--contrib/libs/grpc/src/core/lib/service_config/service_config_parser.h (renamed from contrib/libs/grpc/src/core/ext/service_config/service_config_parser.h)6
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/slice.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/slice.h56
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/slice_intern.cc104
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/slice_internal.h3
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/slice_refcount.h17
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/slice_refcount_base.h16
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/static_slice.cc377
-rw-r--r--contrib/libs/grpc/src/core/lib/slice/static_slice.h300
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/call.cc522
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/call.h8
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/channel.cc86
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/channel.h8
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/init.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/lame_client.cc1
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/server.cc41
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/server.h4
-rw-r--r--contrib/libs/grpc/src/core/lib/surface/version.cc4
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/error_utils.h14
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/metadata.cc714
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/metadata.h449
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/metadata_batch.cc99
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/metadata_batch.h1516
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/parsed_metadata.cc2
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/parsed_metadata.h187
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/static_metadata.cc1032
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/static_metadata.h322
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/status_metadata.cc63
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/status_metadata.h48
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/timeout_encoding.cc266
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/timeout_encoding.h50
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/transport.h2
-rw-r--r--contrib/libs/grpc/src/core/lib/transport/transport_op_string.cc45
-rw-r--r--contrib/libs/grpc/src/core/lib/uri/uri_parser.cc276
-rw-r--r--contrib/libs/grpc/src/core/lib/uri/uri_parser.h59
-rw-r--r--contrib/libs/grpc/src/core/plugin_registry/grpc_plugin_registry.cc7
-rw-r--r--contrib/libs/grpc/src/core/tsi/alts/handshaker/alts_handshaker_client.cc2
-rw-r--r--contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session.h6
-rw-r--r--contrib/libs/grpc/src/core/tsi/ssl/session_cache/ssl_session_cache.h8
-rw-r--r--contrib/libs/grpc/src/core/tsi/ssl_transport_security.cc66
-rw-r--r--contrib/libs/grpc/src/core/tsi/ssl_transport_security.h24
-rw-r--r--contrib/libs/grpc/src/cpp/common/channel_filter.cc15
-rw-r--r--contrib/libs/grpc/src/cpp/common/channel_filter.h6
-rw-r--r--contrib/libs/grpc/src/cpp/common/validate_service_config.cc2
-rw-r--r--contrib/libs/grpc/src/cpp/common/version_cc.cc2
-rw-r--r--contrib/libs/grpc/src/python/grpcio/grpc/_cython/_cygrpc/iomgr.pxd.pxi4
-rw-r--r--contrib/libs/grpc/src/python/grpcio/grpc/_grpcio_metadata.py2
-rw-r--r--contrib/libs/grpc/src/python/grpcio_tests/tests/unit/_dns_resolver_test.py6
-rw-r--r--contrib/libs/grpc/test/core/util/port_server_client.cc17
-rw-r--r--contrib/libs/grpc/test/core/util/test_lb_policies.cc4
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", &regex, 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, &not_rule_error_list));
+ if (!not_rule_error_list.empty()) {
+ error_list->push_back(
+ GRPC_ERROR_CREATE_FROM_VECTOR("notRule", &not_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, &not_rule_error_list));
+ if (!not_rule_error_list.empty()) {
+ error_list->push_back(
+ GRPC_ERROR_CREATE_FROM_VECTOR("notId", &not_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",