grpc 1.75.0 → 1.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +24 -5
- data/include/grpc/credentials.h +27 -6
- data/include/grpc/event_engine/memory_allocator.h +2 -0
- data/include/grpc/event_engine/memory_request.h +2 -0
- data/include/grpc/impl/channel_arg_names.h +5 -0
- data/include/grpc/support/metrics.h +7 -1
- data/src/core/call/call_filters.cc +5 -5
- data/src/core/call/call_filters.h +211 -37
- data/src/core/call/call_spine.cc +1 -1
- data/src/core/call/call_spine.h +54 -32
- data/src/core/call/channelz_context.h +30 -0
- data/src/core/call/client_call.cc +49 -10
- data/src/core/call/client_call.h +6 -3
- data/src/core/call/filter_fusion.h +9 -9
- data/src/core/call/interception_chain.h +7 -6
- data/src/core/call/metadata_batch.cc +49 -55
- data/src/core/call/metadata_batch.h +10 -9
- data/src/core/call/metadata_info.cc +1 -1
- data/src/core/call/parsed_metadata.h +2 -2
- data/src/core/call/request_buffer.cc +1 -1
- data/src/core/call/security_context.cc +2 -2
- data/src/core/call/security_context.h +1 -1
- data/src/core/call/server_call.cc +5 -5
- data/src/core/call/server_call.h +6 -4
- data/src/core/call/simple_slice_based_metadata.h +1 -1
- data/src/core/call/status_util.cc +1 -1
- data/src/core/channelz/channel_trace.cc +1 -1
- data/src/core/channelz/channel_trace.h +3 -3
- data/src/core/channelz/channelz.cc +25 -29
- data/src/core/channelz/channelz.h +73 -22
- data/src/core/channelz/channelz_registry.cc +2 -2
- data/src/core/channelz/channelz_registry.h +53 -2
- data/src/core/channelz/property_list.cc +18 -0
- data/src/core/channelz/property_list.h +15 -4
- data/src/core/channelz/text_encode.cc +66 -0
- data/src/core/channelz/text_encode.h +29 -0
- data/src/core/channelz/v2tov1/convert.cc +17 -6
- data/src/core/channelz/v2tov1/legacy_api.cc +18 -12
- data/src/core/channelz/v2tov1/property_list.cc +2 -1
- data/src/core/channelz/ztrace_collector.h +260 -87
- data/src/core/client_channel/backup_poller.cc +7 -8
- data/src/core/client_channel/buffered_call.cc +140 -0
- data/src/core/client_channel/buffered_call.h +104 -0
- data/src/core/client_channel/client_channel.cc +144 -84
- data/src/core/client_channel/client_channel.h +8 -11
- data/src/core/client_channel/client_channel_factory.h +1 -1
- data/src/core/client_channel/client_channel_filter.cc +424 -686
- data/src/core/client_channel/client_channel_filter.h +57 -150
- data/src/core/client_channel/client_channel_internal.h +8 -5
- data/src/core/client_channel/client_channel_service_config.cc +43 -3
- data/src/core/client_channel/client_channel_service_config.h +12 -1
- data/src/core/client_channel/config_selector.h +5 -5
- data/src/core/client_channel/connector.h +2 -0
- data/src/core/client_channel/dynamic_filters.cc +5 -5
- data/src/core/client_channel/global_subchannel_pool.cc +0 -37
- data/src/core/client_channel/global_subchannel_pool.h +1 -28
- data/src/core/client_channel/lb_metadata.h +1 -1
- data/src/core/client_channel/load_balanced_call_destination.cc +10 -12
- data/src/core/client_channel/load_balanced_call_destination.h +1 -1
- data/src/core/client_channel/local_subchannel_pool.cc +4 -4
- data/src/core/client_channel/retry_filter.cc +2 -2
- data/src/core/client_channel/retry_filter.h +3 -3
- data/src/core/client_channel/retry_filter_legacy_call_data.cc +11 -12
- data/src/core/client_channel/retry_filter_legacy_call_data.h +6 -8
- data/src/core/client_channel/retry_service_config.cc +3 -3
- data/src/core/client_channel/retry_service_config.h +1 -1
- data/src/core/client_channel/subchannel.cc +114 -25
- data/src/core/client_channel/subchannel.h +24 -8
- data/src/core/client_channel/subchannel_pool_interface.cc +2 -2
- data/src/core/client_channel/subchannel_pool_interface.h +1 -1
- data/src/core/client_channel/subchannel_stream_client.cc +5 -5
- data/src/core/client_channel/subchannel_stream_client.h +3 -3
- data/src/core/config/config_vars.cc +38 -3
- data/src/core/config/config_vars.h +26 -0
- data/src/core/config/core_configuration.cc +5 -5
- data/src/core/config/core_configuration.h +8 -8
- data/src/core/config/load_config.cc +13 -1
- data/src/core/config/load_config.h +2 -0
- data/src/core/credentials/call/call_credentials.h +4 -4
- data/src/core/credentials/call/call_creds_registry.h +1 -1
- data/src/core/credentials/call/call_creds_registry_init.cc +2 -2
- data/src/core/credentials/call/call_creds_util.cc +7 -6
- data/src/core/credentials/call/composite/composite_call_credentials.cc +6 -6
- data/src/core/credentials/call/composite/composite_call_credentials.h +1 -1
- data/src/core/credentials/call/external/aws_external_account_credentials.cc +9 -9
- data/src/core/credentials/call/external/aws_external_account_credentials.h +1 -1
- data/src/core/credentials/call/external/external_account_credentials.cc +12 -12
- data/src/core/credentials/call/external/external_account_credentials.h +1 -1
- data/src/core/credentials/call/external/file_external_account_credentials.cc +3 -3
- data/src/core/credentials/call/external/file_external_account_credentials.h +1 -1
- data/src/core/credentials/call/external/url_external_account_credentials.cc +7 -7
- data/src/core/credentials/call/external/url_external_account_credentials.h +1 -1
- data/src/core/credentials/call/gcp_service_account_identity/gcp_service_account_identity_credentials.cc +24 -71
- data/src/core/credentials/call/gcp_service_account_identity/gcp_service_account_identity_credentials.h +1 -8
- data/src/core/credentials/call/iam/iam_credentials.cc +6 -6
- data/src/core/credentials/call/iam/iam_credentials.h +1 -1
- data/src/core/credentials/call/json_util.cc +1 -1
- data/src/core/credentials/call/jwt/json_token.cc +7 -7
- data/src/core/credentials/call/jwt/jwt_credentials.cc +5 -5
- data/src/core/credentials/call/jwt/jwt_credentials.h +4 -4
- data/src/core/credentials/call/jwt/jwt_verifier.cc +19 -18
- data/src/core/credentials/call/jwt_token_file/jwt_token_file_call_credentials.cc +2 -2
- data/src/core/credentials/call/jwt_token_file/jwt_token_file_call_credentials.h +3 -3
- data/src/core/credentials/call/jwt_util.cc +3 -3
- data/src/core/credentials/call/jwt_util.h +1 -1
- data/src/core/credentials/call/oauth2/oauth2_credentials.cc +49 -72
- data/src/core/credentials/call/oauth2/oauth2_credentials.h +3 -9
- data/src/core/credentials/call/plugin/plugin_credentials.cc +6 -6
- data/src/core/credentials/call/plugin/plugin_credentials.h +2 -2
- data/src/core/credentials/call/token_fetcher/token_fetcher_credentials.cc +46 -0
- data/src/core/credentials/call/token_fetcher/token_fetcher_credentials.h +32 -3
- data/src/core/credentials/transport/alts/alts_credentials.cc +5 -5
- data/src/core/credentials/transport/alts/alts_security_connector.cc +17 -15
- data/src/core/credentials/transport/alts/check_gcp_environment_no_op.cc +1 -1
- data/src/core/credentials/transport/alts/grpc_alts_credentials_client_options.cc +23 -3
- data/src/core/credentials/transport/alts/grpc_alts_credentials_options.cc +10 -1
- data/src/core/credentials/transport/alts/grpc_alts_credentials_options.h +31 -0
- data/src/core/credentials/transport/alts/grpc_alts_credentials_server_options.cc +8 -3
- data/src/core/credentials/transport/channel_creds_registry.h +1 -1
- data/src/core/credentials/transport/channel_creds_registry_init.cc +1 -1
- data/src/core/credentials/transport/composite/composite_channel_credentials.cc +7 -7
- data/src/core/credentials/transport/composite/composite_channel_credentials.h +1 -1
- data/src/core/credentials/transport/fake/fake_credentials.cc +1 -1
- data/src/core/credentials/transport/fake/fake_credentials.h +1 -1
- data/src/core/credentials/transport/fake/fake_security_connector.cc +7 -7
- data/src/core/credentials/transport/google_default/credentials_generic.cc +2 -2
- data/src/core/credentials/transport/google_default/google_default_credentials.cc +83 -39
- data/src/core/credentials/transport/google_default/google_default_credentials.h +0 -2
- data/src/core/credentials/transport/insecure/insecure_security_connector.cc +3 -3
- data/src/core/credentials/transport/insecure/insecure_security_connector.h +2 -2
- data/src/core/credentials/transport/local/local_security_connector.cc +13 -13
- data/src/core/credentials/transport/security_connector.cc +6 -6
- data/src/core/credentials/transport/security_connector.h +2 -2
- data/src/core/credentials/transport/ssl/ssl_credentials.cc +13 -13
- data/src/core/credentials/transport/ssl/ssl_credentials.h +2 -2
- data/src/core/credentials/transport/ssl/ssl_security_connector.cc +8 -8
- data/src/core/credentials/transport/tls/certificate_provider_factory.h +1 -1
- data/src/core/credentials/transport/tls/certificate_provider_registry.cc +2 -2
- data/src/core/credentials/transport/tls/certificate_provider_registry.h +1 -1
- data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.cc +25 -25
- data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.h +2 -2
- data/src/core/credentials/transport/tls/grpc_tls_certificate_match.cc +1 -1
- data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.cc +8 -8
- data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.h +5 -5
- data/src/core/credentials/transport/tls/grpc_tls_certificate_verifier.cc +3 -3
- data/src/core/credentials/transport/tls/grpc_tls_certificate_verifier.h +4 -4
- data/src/core/credentials/transport/tls/grpc_tls_credentials_options.cc +18 -18
- data/src/core/credentials/transport/tls/grpc_tls_crl_provider.cc +5 -5
- data/src/core/credentials/transport/tls/grpc_tls_crl_provider.h +3 -3
- data/src/core/credentials/transport/tls/load_system_roots_supported.cc +1 -1
- data/src/core/credentials/transport/tls/spiffe_utils.cc +10 -8
- data/src/core/credentials/transport/tls/spiffe_utils.h +2 -2
- data/src/core/credentials/transport/tls/ssl_utils.cc +18 -13
- data/src/core/credentials/transport/tls/ssl_utils.h +2 -2
- data/src/core/credentials/transport/tls/tls_credentials.cc +3 -3
- data/src/core/credentials/transport/tls/tls_security_connector.cc +15 -15
- data/src/core/credentials/transport/tls/tls_security_connector.h +3 -3
- data/src/core/credentials/transport/transport_credentials.cc +3 -3
- data/src/core/credentials/transport/transport_credentials.h +4 -4
- data/src/core/credentials/transport/xds/xds_credentials.cc +5 -5
- data/src/core/credentials/transport/xds/xds_credentials.h +1 -1
- data/src/core/ext/filters/backend_metrics/backend_metric_filter.cc +2 -2
- data/src/core/ext/filters/backend_metrics/backend_metric_filter.h +4 -1
- data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc +6 -4
- data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.h +2 -2
- data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +7 -7
- data/src/core/ext/filters/fault_injection/fault_injection_filter.h +6 -3
- data/src/core/ext/filters/fault_injection/fault_injection_service_config_parser.h +1 -1
- data/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.cc +2 -2
- data/src/core/ext/filters/gcp_authentication/gcp_authentication_filter.h +6 -3
- data/src/core/ext/filters/gcp_authentication/gcp_authentication_service_config_parser.h +1 -1
- data/src/core/ext/filters/http/client/http_client_filter.cc +6 -6
- data/src/core/ext/filters/http/client/http_client_filter.h +4 -1
- data/src/core/ext/filters/http/client_authority_filter.cc +2 -2
- data/src/core/ext/filters/http/client_authority_filter.h +4 -1
- data/src/core/ext/filters/http/http_filters_plugin.cc +1 -1
- data/src/core/ext/filters/http/message_compress/compression_filter.cc +11 -11
- data/src/core/ext/filters/http/message_compress/compression_filter.h +24 -5
- data/src/core/ext/filters/http/server/http_server_filter.cc +3 -3
- data/src/core/ext/filters/http/server/http_server_filter.h +4 -1
- data/src/core/ext/filters/message_size/message_size_filter.cc +2 -2
- data/src/core/ext/filters/message_size/message_size_filter.h +8 -2
- data/src/core/ext/filters/rbac/rbac_filter.cc +1 -1
- data/src/core/ext/filters/rbac/rbac_filter.h +4 -1
- data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +3 -3
- data/src/core/ext/filters/rbac/rbac_service_config_parser.h +1 -1
- data/src/core/ext/filters/stateful_session/stateful_session_filter.cc +14 -14
- data/src/core/ext/filters/stateful_session/stateful_session_filter.h +13 -2
- data/src/core/ext/filters/stateful_session/stateful_session_service_config_parser.h +1 -1
- data/src/core/ext/transport/chttp2/alpn/alpn.cc +2 -2
- data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +58 -44
- data/src/core/ext/transport/chttp2/client/chttp2_connector.h +2 -3
- data/src/core/ext/transport/chttp2/server/chttp2_server.cc +25 -24
- data/src/core/ext/transport/chttp2/server/chttp2_server.h +1 -2
- data/src/core/ext/transport/chttp2/transport/bin_decoder.cc +6 -6
- data/src/core/ext/transport/chttp2/transport/bin_encoder.cc +6 -6
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +306 -148
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +10 -2
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +42 -7
- data/src/core/ext/transport/chttp2/transport/flow_control.h +223 -83
- data/src/core/ext/transport/chttp2/transport/flow_control_manager.h +105 -0
- data/src/core/ext/transport/chttp2/transport/frame.cc +175 -27
- data/src/core/ext/transport/chttp2/transport/frame.h +58 -10
- data/src/core/ext/transport/chttp2/transport/frame_data.cc +4 -4
- data/src/core/ext/transport/chttp2/transport/frame_data.h +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +5 -5
- data/src/core/ext/transport/chttp2/transport/frame_ping.cc +6 -6
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +7 -7
- data/src/core/ext/transport/chttp2/transport/frame_security.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/frame_settings.cc +7 -15
- data/src/core/ext/transport/chttp2/transport/frame_window_update.cc +6 -6
- data/src/core/ext/transport/chttp2/transport/goaway.cc +129 -0
- data/src/core/ext/transport/chttp2/transport/goaway.h +350 -0
- data/src/core/ext/transport/chttp2/transport/header_assembler.h +194 -54
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +3 -3
- data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +8 -6
- data/src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc +8 -8
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +3 -3
- data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +5 -5
- data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +34 -34
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +6 -7
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +8 -8
- data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +1 -1
- data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +1475 -632
- data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +384 -373
- data/src/core/ext/transport/chttp2/transport/http2_settings.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/http2_settings.h +6 -4
- data/src/core/ext/transport/chttp2/transport/http2_settings_manager.cc +4 -3
- data/src/core/ext/transport/chttp2/transport/http2_settings_manager.h +6 -5
- data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +417 -0
- data/src/core/ext/transport/chttp2/transport/http2_status.h +7 -1
- data/src/core/ext/transport/chttp2/transport/http2_transport.cc +337 -30
- data/src/core/ext/transport/chttp2/transport/http2_transport.h +196 -21
- data/src/core/ext/transport/chttp2/transport/http2_ztrace_collector.h +172 -72
- data/src/core/ext/transport/chttp2/transport/incoming_metadata_tracker.h +128 -0
- data/src/core/ext/transport/chttp2/transport/internal.h +31 -19
- data/src/core/ext/transport/chttp2/transport/keepalive.cc +12 -5
- data/src/core/ext/transport/chttp2/transport/keepalive.h +14 -10
- data/src/core/ext/transport/chttp2/transport/message_assembler.h +30 -21
- data/src/core/ext/transport/chttp2/transport/parsing.cc +25 -23
- data/src/core/ext/transport/chttp2/transport/ping_callbacks.cc +2 -2
- data/src/core/ext/transport/chttp2/transport/ping_callbacks.h +3 -3
- data/src/core/ext/transport/chttp2/transport/ping_promise.cc +70 -28
- data/src/core/ext/transport/chttp2/transport/ping_promise.h +63 -23
- data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +1 -1
- data/src/core/ext/transport/chttp2/transport/security_frame.cc +31 -0
- data/src/core/ext/transport/chttp2/transport/security_frame.h +32 -0
- data/src/core/ext/transport/chttp2/transport/stream.h +287 -0
- data/src/core/ext/transport/chttp2/transport/stream_data_queue.h +476 -208
- data/src/core/ext/transport/chttp2/transport/stream_lists.cc +8 -8
- data/src/core/ext/transport/chttp2/transport/transport_common.cc +17 -1
- data/src/core/ext/transport/chttp2/transport/transport_common.h +57 -0
- data/src/core/ext/transport/chttp2/transport/varint.h +2 -2
- data/src/core/ext/transport/chttp2/transport/writable_streams.h +202 -84
- data/src/core/ext/transport/chttp2/transport/write_size_policy.cc +2 -2
- data/src/core/ext/transport/chttp2/transport/writing.cc +6 -6
- data/src/core/ext/transport/inproc/inproc_transport.cc +9 -3
- data/src/core/ext/transport/inproc/legacy_inproc_transport.cc +11 -8
- data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb.h +740 -0
- data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb_minitable.c +218 -0
- data/src/core/ext/upb-gen/src/proto/grpc/channelz/v2/service.upb_minitable.h +46 -0
- data/src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb.h +87 -55
- data/src/core/ext/upb-gen/src/proto/grpc/gcp/handshaker.upb_minitable.c +23 -21
- data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/channelz.upbdefs.c +80 -0
- data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/channelz.upbdefs.h +47 -0
- data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/service.upbdefs.c +129 -0
- data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/v2/service.upbdefs.h +72 -0
- data/src/core/filter/auth/auth_filters.h +7 -1
- data/src/core/filter/auth/client_auth_filter.cc +2 -2
- data/src/core/filter/auth/server_auth_filter.cc +5 -5
- data/src/core/filter/blackboard.h +2 -2
- data/src/core/filter/filter_args.h +40 -2
- data/src/core/handshaker/endpoint_info/endpoint_info_handshaker.cc +2 -2
- data/src/core/handshaker/handshaker.cc +8 -8
- data/src/core/handshaker/handshaker.h +2 -2
- data/src/core/handshaker/http_connect/http_connect_handshaker.cc +5 -5
- data/src/core/handshaker/http_connect/http_proxy_mapper.cc +12 -12
- data/src/core/handshaker/http_connect/http_proxy_mapper.h +1 -1
- data/src/core/handshaker/http_connect/xds_http_proxy_mapper.cc +1 -1
- data/src/core/handshaker/http_connect/xds_http_proxy_mapper.h +1 -1
- data/src/core/handshaker/proxy_mapper.h +1 -1
- data/src/core/handshaker/proxy_mapper_registry.h +1 -1
- data/src/core/handshaker/security/legacy_secure_endpoint.cc +6 -6
- data/src/core/handshaker/security/pipelined_secure_endpoint.cc +38 -15
- data/src/core/handshaker/security/secure_endpoint.cc +31 -11
- data/src/core/handshaker/security/security_handshaker.cc +11 -8
- data/src/core/handshaker/security/security_handshaker.h +1 -1
- data/src/core/handshaker/tcp_connect/tcp_connect_handshaker.cc +6 -6
- data/src/core/lib/address_utils/parse_address.cc +5 -5
- data/src/core/lib/address_utils/parse_address.h +2 -2
- data/src/core/lib/address_utils/sockaddr_utils.cc +4 -4
- data/src/core/lib/address_utils/sockaddr_utils.h +1 -1
- data/src/core/lib/channel/channel_args.cc +1 -1
- data/src/core/lib/channel/channel_args.h +2 -2
- data/src/core/lib/channel/channel_stack.cc +29 -25
- data/src/core/lib/channel/channel_stack.h +8 -3
- data/src/core/lib/channel/channel_stack_builder.cc +8 -4
- data/src/core/lib/channel/channel_stack_builder.h +10 -9
- data/src/core/lib/channel/channel_stack_builder_impl.cc +8 -13
- data/src/core/lib/channel/channel_stack_builder_impl.h +1 -1
- data/src/core/lib/channel/connected_channel.cc +4 -4
- data/src/core/lib/channel/promise_based_filter.cc +132 -72
- data/src/core/lib/channel/promise_based_filter.h +39 -23
- data/src/core/lib/compression/compression_internal.cc +6 -6
- data/src/core/lib/compression/compression_internal.h +1 -1
- data/src/core/lib/compression/message_compress.cc +8 -8
- data/src/core/lib/debug/trace.cc +2 -5
- data/src/core/lib/debug/trace.h +10 -0
- data/src/core/lib/debug/trace_flags.cc +2 -2
- data/src/core/lib/debug/trace_flags.h +1 -1
- data/src/core/lib/event_engine/ares_resolver.cc +30 -28
- data/src/core/lib/event_engine/ares_resolver.h +4 -4
- data/src/core/lib/event_engine/cf_engine/cf_engine.cc +3 -3
- data/src/core/lib/event_engine/cf_engine/cfstream_endpoint.cc +2 -2
- data/src/core/lib/event_engine/cf_engine/cfstream_endpoint.h +1 -1
- data/src/core/lib/event_engine/cf_engine/dns_service_resolver.cc +4 -4
- data/src/core/lib/event_engine/cf_engine/dns_service_resolver.h +3 -3
- data/src/core/lib/event_engine/channel_args_endpoint_config.h +1 -1
- data/src/core/lib/event_engine/default_event_engine.cc +1 -1
- data/src/core/lib/event_engine/event_engine.cc +1 -1
- data/src/core/lib/event_engine/extensions/channelz.h +3 -3
- data/src/core/lib/event_engine/extensions/chaotic_good_extension.h +1 -1
- data/src/core/lib/event_engine/extensions/supports_fd.h +5 -5
- data/src/core/lib/event_engine/extensions/tcp_trace.h +8 -1
- data/src/core/lib/event_engine/grpc_polled_fd.h +1 -1
- data/src/core/lib/event_engine/memory_allocator_factory.h +1 -1
- data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc +12 -12
- data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.h +5 -5
- data/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc +15 -15
- data/src/core/lib/event_engine/posix_engine/ev_poll_posix.h +3 -3
- data/src/core/lib/event_engine/posix_engine/event_poller.h +2 -2
- data/src/core/lib/event_engine/posix_engine/event_poller_posix_default.cc +2 -2
- data/src/core/lib/event_engine/posix_engine/file_descriptor_collection.cc +1 -1
- data/src/core/lib/event_engine/posix_engine/file_descriptor_collection.h +1 -1
- data/src/core/lib/event_engine/posix_engine/grpc_polled_fd_posix.h +4 -4
- data/src/core/lib/event_engine/posix_engine/internal_errqueue.cc +1 -1
- data/src/core/lib/event_engine/posix_engine/lockfree_event.cc +3 -3
- data/src/core/lib/event_engine/posix_engine/lockfree_event.h +1 -1
- data/src/core/lib/event_engine/posix_engine/native_posix_dns_resolver.cc +3 -3
- data/src/core/lib/event_engine/posix_engine/native_posix_dns_resolver.h +1 -1
- data/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +28 -27
- data/src/core/lib/event_engine/posix_engine/posix_endpoint.h +17 -17
- data/src/core/lib/event_engine/posix_engine/posix_engine.cc +175 -177
- data/src/core/lib/event_engine/posix_engine/posix_engine.h +40 -61
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +11 -7
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener.h +4 -4
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.cc +9 -9
- data/src/core/lib/event_engine/posix_engine/posix_engine_listener_utils.h +1 -1
- data/src/core/lib/event_engine/posix_engine/posix_interface.h +2 -2
- data/src/core/lib/event_engine/posix_engine/posix_interface_posix.cc +5 -5
- data/src/core/lib/event_engine/posix_engine/posix_write_event_sink.h +1 -1
- data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc +1 -1
- data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h +1 -1
- data/src/core/lib/event_engine/posix_engine/timer.h +1 -1
- data/src/core/lib/event_engine/posix_engine/timer_manager.cc +4 -4
- data/src/core/lib/event_engine/posix_engine/timer_manager.h +1 -1
- data/src/core/lib/event_engine/posix_engine/traced_buffer_list.cc +2 -2
- data/src/core/lib/event_engine/posix_engine/traced_buffer_list.h +2 -2
- data/src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.cc +1 -1
- data/src/core/lib/event_engine/posix_engine/wakeup_fd_eventfd.h +2 -2
- data/src/core/lib/event_engine/posix_engine/wakeup_fd_pipe.cc +1 -1
- data/src/core/lib/event_engine/posix_engine/wakeup_fd_pipe.h +2 -2
- data/src/core/lib/event_engine/posix_engine/wakeup_fd_posix.h +1 -1
- data/src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.cc +2 -2
- data/src/core/lib/event_engine/posix_engine/wakeup_fd_posix_default.h +1 -1
- data/src/core/lib/event_engine/ref_counted_dns_resolver_interface.h +1 -1
- data/src/core/lib/event_engine/resolved_address.cc +3 -3
- data/src/core/lib/event_engine/shim.cc +8 -11
- data/src/core/lib/event_engine/shim.h +2 -1
- data/src/core/lib/event_engine/slice.cc +2 -2
- data/src/core/lib/event_engine/tcp_socket_utils.cc +15 -15
- data/src/core/lib/event_engine/thread_pool/thread_count.cc +1 -1
- data/src/core/lib/event_engine/thread_pool/thread_count.h +1 -1
- data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.cc +11 -11
- data/src/core/lib/event_engine/thread_pool/work_stealing_thread_pool.h +3 -3
- data/src/core/lib/event_engine/utils.cc +3 -3
- data/src/core/lib/event_engine/utils.h +1 -1
- data/src/core/lib/event_engine/windows/grpc_polled_fd_windows.cc +32 -32
- data/src/core/lib/event_engine/windows/grpc_polled_fd_windows.h +2 -2
- data/src/core/lib/event_engine/windows/iocp.cc +11 -11
- data/src/core/lib/event_engine/windows/iocp.h +1 -1
- data/src/core/lib/event_engine/windows/native_windows_dns_resolver.cc +5 -2
- data/src/core/lib/event_engine/windows/win_socket.cc +7 -7
- data/src/core/lib/event_engine/windows/win_socket.h +2 -2
- data/src/core/lib/event_engine/windows/windows_endpoint.cc +16 -16
- data/src/core/lib/event_engine/windows/windows_engine.cc +20 -18
- data/src/core/lib/event_engine/windows/windows_engine.h +3 -3
- data/src/core/lib/event_engine/windows/windows_listener.cc +10 -10
- data/src/core/lib/event_engine/windows/windows_listener.h +2 -2
- data/src/core/lib/event_engine/work_queue/basic_work_queue.h +2 -2
- data/src/core/lib/experiments/config.cc +4 -4
- data/src/core/lib/experiments/experiments.cc +255 -42
- data/src/core/lib/experiments/experiments.h +105 -21
- data/src/core/lib/iomgr/buffer_list.cc +1 -1
- data/src/core/lib/iomgr/call_combiner.cc +4 -4
- data/src/core/lib/iomgr/call_combiner.h +2 -2
- data/src/core/lib/iomgr/cfstream_handle.cc +1 -1
- data/src/core/lib/iomgr/closure.h +2 -2
- data/src/core/lib/iomgr/combiner.cc +2 -2
- data/src/core/lib/iomgr/endpoint.h +1 -1
- data/src/core/lib/iomgr/endpoint_cfstream.cc +7 -7
- data/src/core/lib/iomgr/endpoint_pair_posix.cc +6 -6
- data/src/core/lib/iomgr/endpoint_pair_windows.cc +16 -15
- data/src/core/lib/iomgr/error.cc +1 -1
- data/src/core/lib/iomgr/error.h +2 -2
- data/src/core/lib/iomgr/error_cfstream.cc +1 -1
- data/src/core/lib/iomgr/ev_apple.cc +1 -1
- data/src/core/lib/iomgr/ev_epoll1_linux.cc +19 -19
- data/src/core/lib/iomgr/ev_poll_posix.cc +14 -14
- data/src/core/lib/iomgr/ev_posix.cc +3 -3
- data/src/core/lib/iomgr/event_engine_shims/closure.cc +3 -3
- data/src/core/lib/iomgr/event_engine_shims/closure.h +1 -1
- data/src/core/lib/iomgr/event_engine_shims/endpoint.cc +10 -9
- data/src/core/lib/iomgr/event_engine_shims/endpoint.h +1 -1
- data/src/core/lib/iomgr/event_engine_shims/tcp_client.cc +2 -2
- data/src/core/lib/iomgr/exec_ctx.cc +3 -3
- data/src/core/lib/iomgr/exec_ctx.h +1 -1
- data/src/core/lib/iomgr/fork_posix.cc +1 -1
- data/src/core/lib/iomgr/internal_errqueue.cc +1 -1
- data/src/core/lib/iomgr/iocp_windows.cc +9 -9
- data/src/core/lib/iomgr/iomgr.cc +1 -1
- data/src/core/lib/iomgr/iomgr_windows.cc +3 -3
- data/src/core/lib/iomgr/lockfree_event.cc +3 -3
- data/src/core/lib/iomgr/polling_entity.cc +4 -4
- data/src/core/lib/iomgr/resolve_address.cc +1 -1
- data/src/core/lib/iomgr/resolve_address.h +2 -2
- data/src/core/lib/iomgr/resolve_address_posix.cc +4 -4
- data/src/core/lib/iomgr/resolve_address_windows.cc +1 -1
- data/src/core/lib/iomgr/sockaddr_utils_posix.cc +1 -1
- data/src/core/lib/iomgr/socket_utils_common_posix.cc +4 -4
- data/src/core/lib/iomgr/socket_windows.cc +6 -6
- data/src/core/lib/iomgr/tcp_client_cfstream.cc +1 -1
- data/src/core/lib/iomgr/tcp_client_posix.cc +7 -7
- data/src/core/lib/iomgr/tcp_client_windows.cc +4 -4
- data/src/core/lib/iomgr/tcp_posix.cc +47 -47
- data/src/core/lib/iomgr/tcp_server.cc +5 -0
- data/src/core/lib/iomgr/tcp_server.h +7 -0
- data/src/core/lib/iomgr/tcp_server_posix.cc +62 -31
- data/src/core/lib/iomgr/tcp_server_utils_posix.h +4 -1
- data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +7 -7
- data/src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc +4 -4
- data/src/core/lib/iomgr/tcp_server_windows.cc +70 -31
- data/src/core/lib/iomgr/tcp_windows.cc +8 -8
- data/src/core/lib/iomgr/timer_generic.cc +5 -5
- data/src/core/lib/iomgr/timer_manager.cc +3 -3
- data/src/core/lib/iomgr/unix_sockets_posix.cc +3 -3
- data/src/core/lib/iomgr/unix_sockets_posix.h +1 -1
- data/src/core/lib/iomgr/unix_sockets_posix_noop.cc +2 -2
- data/src/core/lib/iomgr/vsock.cc +1 -1
- data/src/core/lib/iomgr/vsock.h +1 -1
- data/src/core/lib/iomgr/wakeup_fd_pipe.cc +1 -1
- data/src/core/lib/promise/activity.cc +3 -3
- data/src/core/lib/promise/activity.h +11 -10
- data/src/core/lib/promise/all_ok.h +3 -3
- data/src/core/lib/promise/arena_promise.h +47 -6
- data/src/core/lib/promise/context.h +3 -3
- data/src/core/lib/promise/detail/join_state.h +10 -10
- data/src/core/lib/promise/detail/promise_factory.h +1 -1
- data/src/core/lib/promise/detail/promise_like.h +1 -1
- data/src/core/lib/promise/detail/seq_state.h +16 -16
- data/src/core/lib/promise/detail/status.h +2 -2
- data/src/core/lib/promise/exec_ctx_wakeup_scheduler.h +1 -1
- data/src/core/lib/promise/for_each.h +8 -8
- data/src/core/lib/promise/if.h +1 -1
- data/src/core/lib/promise/inter_activity_latch.h +3 -3
- data/src/core/lib/promise/inter_activity_mutex.h +1 -1
- data/src/core/lib/promise/interceptor_list.h +5 -5
- data/src/core/lib/promise/latch.h +9 -9
- data/src/core/lib/promise/loop.h +2 -2
- data/src/core/lib/promise/map.h +2 -2
- data/src/core/lib/promise/mpsc.cc +31 -30
- data/src/core/lib/promise/mpsc.h +2 -2
- data/src/core/lib/promise/observable.h +6 -6
- data/src/core/lib/promise/party.cc +43 -30
- data/src/core/lib/promise/party.h +27 -23
- data/src/core/lib/promise/pipe.h +31 -17
- data/src/core/lib/promise/poll.h +6 -5
- data/src/core/lib/promise/promise.h +2 -4
- data/src/core/lib/promise/sleep.cc +3 -1
- data/src/core/lib/promise/sleep.h +1 -1
- data/src/core/lib/promise/status_flag.h +8 -8
- data/src/core/lib/promise/try_join.h +5 -5
- data/src/core/lib/promise/try_seq.h +5 -5
- data/src/core/lib/promise/wait_set.h +2 -2
- data/src/core/lib/resource_quota/api.cc +1 -1
- data/src/core/lib/resource_quota/arena.cc +1 -1
- data/src/core/lib/resource_quota/arena.h +15 -2
- data/src/core/lib/resource_quota/connection_quota.cc +9 -7
- data/src/core/lib/resource_quota/connection_quota.h +1 -1
- data/src/core/lib/resource_quota/memory_quota.cc +48 -27
- data/src/core/lib/resource_quota/memory_quota.h +56 -20
- data/src/core/lib/resource_quota/periodic_update.h +1 -1
- data/src/core/lib/resource_quota/resource_quota.cc +8 -0
- data/src/core/lib/resource_quota/resource_quota.h +2 -1
- data/src/core/lib/resource_quota/stream_quota.cc +22 -0
- data/src/core/lib/resource_quota/stream_quota.h +31 -0
- data/src/core/lib/resource_quota/telemetry.h +55 -0
- data/src/core/lib/resource_quota/thread_quota.cc +2 -2
- data/src/core/lib/resource_quota/thread_quota.h +1 -1
- data/src/core/lib/resource_tracker/resource_tracker.cc +33 -0
- data/src/core/lib/resource_tracker/resource_tracker.h +46 -0
- data/src/core/lib/security/authorization/audit_logging.cc +7 -7
- data/src/core/lib/security/authorization/audit_logging.h +1 -1
- data/src/core/lib/security/authorization/authorization_policy_provider.h +1 -1
- data/src/core/lib/security/authorization/evaluate_args.cc +5 -5
- data/src/core/lib/security/authorization/evaluate_args.h +1 -1
- data/src/core/lib/security/authorization/grpc_authorization_engine.cc +2 -2
- data/src/core/lib/security/authorization/grpc_server_authz_filter.cc +3 -3
- data/src/core/lib/security/authorization/grpc_server_authz_filter.h +4 -1
- data/src/core/lib/security/authorization/matchers.cc +2 -2
- data/src/core/lib/security/authorization/stdout_logger.cc +3 -3
- data/src/core/lib/slice/percent_encoding.cc +1 -1
- data/src/core/lib/slice/slice.cc +1 -1
- data/src/core/lib/slice/slice.h +2 -2
- data/src/core/lib/slice/slice_buffer.cc +1 -1
- data/src/core/lib/slice/slice_internal.h +1 -1
- data/src/core/lib/surface/byte_buffer_reader.cc +2 -2
- data/src/core/lib/surface/call.cc +58 -28
- data/src/core/lib/surface/call.h +13 -6
- data/src/core/lib/surface/call_log_batch.cc +2 -2
- data/src/core/lib/surface/call_utils.cc +7 -7
- data/src/core/lib/surface/call_utils.h +85 -20
- data/src/core/lib/surface/channel.cc +6 -5
- data/src/core/lib/surface/channel.h +13 -3
- data/src/core/lib/surface/channel_create.cc +12 -8
- data/src/core/lib/surface/channel_create.h +1 -1
- data/src/core/lib/surface/channel_init.cc +84 -27
- data/src/core/lib/surface/channel_init.h +30 -13
- data/src/core/lib/surface/completion_queue.cc +21 -20
- data/src/core/lib/surface/completion_queue_factory.cc +7 -7
- data/src/core/lib/surface/connection_context.h +45 -2
- data/src/core/lib/surface/filter_stack_call.cc +25 -31
- data/src/core/lib/surface/filter_stack_call.h +6 -7
- data/src/core/lib/surface/init.cc +4 -4
- data/src/core/lib/surface/lame_client.cc +2 -2
- data/src/core/lib/surface/lame_client.h +3 -3
- data/src/core/lib/surface/legacy_channel.cc +10 -10
- data/src/core/lib/surface/legacy_channel.h +1 -1
- data/src/core/lib/surface/validate_metadata.cc +2 -2
- data/src/core/lib/surface/validate_metadata.h +3 -3
- data/src/core/lib/surface/version.cc +2 -2
- data/src/core/lib/transport/bdp_estimator.cc +2 -2
- data/src/core/lib/transport/bdp_estimator.h +5 -5
- data/src/core/lib/transport/connectivity_state.cc +1 -1
- data/src/core/lib/transport/connectivity_state.h +2 -2
- data/src/core/lib/transport/error_utils.h +1 -1
- data/src/core/lib/transport/promise_endpoint.cc +4 -4
- data/src/core/lib/transport/promise_endpoint.h +11 -11
- data/src/core/lib/transport/timeout_encoding.cc +4 -4
- data/src/core/lib/transport/transport.cc +3 -3
- data/src/core/lib/transport/transport.h +62 -4
- data/src/core/lib/transport/transport_framing_endpoint_extension.h +1 -1
- data/src/core/lib/transport/transport_op_string.cc +2 -2
- data/src/core/load_balancing/address_filtering.cc +1 -1
- data/src/core/load_balancing/address_filtering.h +2 -2
- data/src/core/load_balancing/backend_metric_parser.cc +1 -1
- data/src/core/load_balancing/backend_metric_parser.h +1 -1
- data/src/core/load_balancing/child_policy_handler.cc +8 -8
- data/src/core/load_balancing/child_policy_handler.h +2 -2
- data/src/core/load_balancing/delegating_helper.h +2 -2
- data/src/core/load_balancing/endpoint_list.cc +6 -6
- data/src/core/load_balancing/endpoint_list.h +2 -2
- data/src/core/load_balancing/grpclb/client_load_reporting_filter.cc +7 -5
- data/src/core/load_balancing/grpclb/client_load_reporting_filter.h +5 -1
- data/src/core/load_balancing/grpclb/grpclb.cc +37 -48
- data/src/core/load_balancing/grpclb/grpclb_client_stats.h +2 -2
- data/src/core/load_balancing/grpclb/load_balancer_api.cc +1 -1
- data/src/core/load_balancing/grpclb/load_balancer_api.h +1 -1
- data/src/core/load_balancing/health_check_client.cc +13 -9
- data/src/core/load_balancing/health_check_client_internal.h +5 -5
- data/src/core/load_balancing/lb_policy.h +11 -8
- data/src/core/load_balancing/lb_policy_factory.h +2 -2
- data/src/core/load_balancing/lb_policy_registry.cc +3 -3
- data/src/core/load_balancing/lb_policy_registry.h +2 -2
- data/src/core/load_balancing/oob_backend_metric.cc +11 -7
- data/src/core/load_balancing/oob_backend_metric_internal.h +4 -4
- data/src/core/load_balancing/outlier_detection/outlier_detection.cc +9 -17
- data/src/core/load_balancing/pick_first/pick_first.cc +62 -32
- data/src/core/load_balancing/priority/priority.cc +29 -30
- data/src/core/load_balancing/ring_hash/ring_hash.cc +11 -11
- data/src/core/load_balancing/rls/rls.cc +23 -23
- data/src/core/load_balancing/round_robin/round_robin.cc +16 -16
- data/src/core/load_balancing/subchannel_interface.h +2 -2
- data/src/core/load_balancing/weighted_round_robin/static_stride_scheduler.cc +3 -3
- data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +42 -41
- data/src/core/load_balancing/weighted_target/weighted_target.cc +14 -14
- data/src/core/load_balancing/xds/cds.cc +81 -37
- data/src/core/load_balancing/xds/xds_cluster_impl.cc +24 -41
- data/src/core/load_balancing/xds/xds_cluster_manager.cc +6 -6
- data/src/core/load_balancing/xds/xds_override_host.cc +14 -14
- data/src/core/load_balancing/xds/xds_override_host.h +1 -1
- data/src/core/load_balancing/xds/xds_wrr_locality.cc +5 -5
- data/src/core/resolver/dns/c_ares/dns_resolver_ares.cc +8 -8
- data/src/core/resolver/dns/c_ares/dns_resolver_ares.h +1 -1
- data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver.h +1 -1
- data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +4 -4
- data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +35 -35
- data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc +16 -16
- data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.h +2 -2
- data/src/core/resolver/dns/dns_resolver_plugin.cc +8 -5
- data/src/core/resolver/dns/event_engine/event_engine_client_channel_resolver.cc +10 -10
- data/src/core/resolver/dns/event_engine/event_engine_client_channel_resolver.h +1 -1
- data/src/core/resolver/dns/event_engine/service_config_helper.cc +2 -2
- data/src/core/resolver/dns/native/dns_resolver.cc +7 -7
- data/src/core/resolver/endpoint_addresses.cc +6 -6
- data/src/core/resolver/endpoint_addresses.h +4 -1
- data/src/core/resolver/fake/fake_resolver.cc +3 -3
- data/src/core/resolver/fake/fake_resolver.h +3 -3
- data/src/core/resolver/google_c2p/google_c2p_resolver.cc +46 -59
- data/src/core/resolver/polling_resolver.cc +8 -8
- data/src/core/resolver/polling_resolver.h +1 -1
- data/src/core/resolver/resolver.h +2 -2
- data/src/core/resolver/resolver_factory.h +2 -2
- data/src/core/resolver/resolver_registry.cc +5 -4
- data/src/core/resolver/resolver_registry.h +1 -1
- data/src/core/resolver/sockaddr/sockaddr_resolver.cc +4 -4
- data/src/core/resolver/xds/xds_config.cc +1 -1
- data/src/core/resolver/xds/xds_config.h +3 -3
- data/src/core/resolver/xds/xds_dependency_manager.cc +7 -7
- data/src/core/resolver/xds/xds_dependency_manager.h +3 -3
- data/src/core/resolver/xds/xds_resolver.cc +25 -22
- data/src/core/resolver/xds/xds_resolver_attributes.h +1 -1
- data/src/core/server/add_port.cc +2 -2
- data/src/core/server/server.cc +47 -43
- data/src/core/server/server.h +8 -7
- data/src/core/server/server_call_tracer_filter.cc +1 -1
- data/src/core/server/server_call_tracer_filter.h +9 -5
- data/src/core/server/server_config_selector.h +2 -2
- data/src/core/server/server_config_selector_filter.cc +5 -5
- data/src/core/server/xds_channel_stack_modifier.cc +3 -2
- data/src/core/server/xds_channel_stack_modifier.h +1 -1
- data/src/core/server/xds_server_config_fetcher.cc +19 -18
- data/src/core/service_config/service_config.h +1 -1
- data/src/core/service_config/service_config_channel_arg_filter.h +4 -1
- data/src/core/service_config/service_config_impl.cc +3 -3
- data/src/core/service_config/service_config_impl.h +4 -4
- data/src/core/service_config/service_config_parser.h +1 -1
- data/src/core/telemetry/call_tracer.cc +39 -49
- data/src/core/telemetry/call_tracer.h +201 -24
- data/src/core/telemetry/default_tcp_tracer.h +3 -3
- data/src/core/telemetry/histogram.h +205 -0
- data/src/core/telemetry/instrument.cc +999 -0
- data/src/core/telemetry/instrument.h +1105 -0
- data/src/core/telemetry/metrics.cc +15 -5
- data/src/core/telemetry/metrics.h +36 -5
- data/src/core/telemetry/stats.h +2 -2
- data/src/core/telemetry/stats_data.cc +1 -20
- data/src/core/telemetry/stats_data.h +2 -21
- data/src/core/transport/auth_context.cc +3 -3
- data/src/core/transport/auth_context.h +2 -1
- data/src/core/transport/auth_context_comparator_registry.h +1 -1
- data/src/core/tsi/alts/crypt/aes_gcm.cc +1 -1
- data/src/core/tsi/alts/frame_protector/alts_frame_protector.cc +2 -2
- data/src/core/tsi/alts/frame_protector/frame_handler.cc +1 -1
- data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +81 -48
- data/src/core/tsi/alts/handshaker/alts_handshaker_client.h +1 -0
- data/src/core/tsi/alts/handshaker/alts_shared_resource.cc +3 -3
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +46 -36
- data/src/core/tsi/alts/handshaker/alts_tsi_utils.cc +4 -4
- data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +1 -1
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc +4 -4
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc +11 -3
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h +10 -0
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc +16 -8
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h +3 -0
- data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +18 -5
- data/src/core/tsi/fake_transport_security.cc +6 -5
- data/src/core/tsi/local_transport_security.cc +1 -1
- data/src/core/tsi/ssl/key_logging/ssl_key_logging.cc +5 -5
- data/src/core/tsi/ssl/key_logging/ssl_key_logging.h +1 -1
- data/src/core/tsi/ssl/session_cache/ssl_session_cache.cc +10 -10
- data/src/core/tsi/ssl/session_cache/ssl_session_openssl.cc +4 -4
- data/src/core/tsi/ssl_transport_security.cc +30 -30
- data/src/core/tsi/ssl_transport_security.h +1 -1
- data/src/core/tsi/ssl_transport_security_utils.cc +10 -10
- data/src/core/tsi/ssl_transport_security_utils.h +2 -2
- data/src/core/tsi/transport_security_grpc.cc +8 -0
- data/src/core/tsi/transport_security_grpc.h +15 -0
- data/src/core/util/alloc.cc +1 -1
- data/src/core/util/backoff.h +1 -1
- data/src/core/util/chunked_vector.h +4 -4
- data/src/core/util/crash.h +1 -1
- data/src/core/util/dual_ref_counted.h +2 -2
- data/src/core/util/event_log.cc +2 -2
- data/src/core/util/event_log.h +3 -3
- data/src/core/util/gcp_metadata_query.cc +7 -7
- data/src/core/util/gcp_metadata_query.h +2 -2
- data/src/core/util/glob.cc +2 -0
- data/src/core/util/grpc_check.cc +24 -0
- data/src/core/util/grpc_check.h +103 -0
- data/src/core/util/grpc_if_nametoindex_posix.cc +1 -1
- data/src/core/util/grpc_if_nametoindex_unsupported.cc +1 -1
- data/src/core/util/http_client/format_request.cc +1 -1
- data/src/core/util/http_client/httpcli.cc +6 -6
- data/src/core/util/http_client/httpcli.h +4 -4
- data/src/core/util/http_client/httpcli_security_connector.cc +4 -4
- data/src/core/util/http_client/parser.cc +4 -4
- data/src/core/util/json/json_channel_args.h +1 -1
- data/src/core/util/json/json_object_loader.h +6 -6
- data/src/core/util/json/json_reader.cc +2 -2
- data/src/core/util/json/json_reader.h +1 -1
- data/src/core/util/json/json_util.h +3 -3
- data/src/core/util/json/json_writer.cc +1 -1
- data/src/core/util/latent_see.cc +45 -24
- data/src/core/util/latent_see.h +199 -28
- data/src/core/util/linux/cpu.cc +1 -1
- data/src/core/util/load_file.cc +1 -1
- data/src/core/util/load_file.h +1 -1
- data/src/core/util/log.cc +3 -3
- data/src/core/util/lru_cache.h +4 -4
- data/src/core/util/matchers.h +1 -1
- data/src/core/util/memory_usage.h +17 -1
- data/src/core/util/mpscq.h +1 -1
- data/src/core/util/notification.h +1 -1
- data/src/core/util/posix/cpu.cc +1 -1
- data/src/core/util/posix/directory_reader.cc +3 -2
- data/src/core/util/posix/stat.cc +2 -2
- data/src/core/util/posix/sync.cc +24 -24
- data/src/core/util/posix/thd.cc +2 -2
- data/src/core/util/posix/tmpfile.cc +2 -2
- data/src/core/util/postmortem_emit.cc +52 -0
- data/src/core/util/postmortem_emit.h +30 -0
- data/src/core/util/ref_counted.h +2 -2
- data/src/core/util/ref_counted_ptr.h +6 -1
- data/src/core/util/ref_counted_string.h +1 -1
- data/src/core/util/single_set_ptr.h +3 -1
- data/src/core/util/status_helper.cc +8 -8
- data/src/core/util/status_helper.h +1 -1
- data/src/core/util/string.cc +2 -2
- data/src/core/util/sync_abseil.cc +1 -1
- data/src/core/util/table.h +1 -1
- data/src/core/util/time.cc +1 -1
- data/src/core/util/time_precise.cc +1 -1
- data/src/core/util/trie_lookup.h +170 -0
- data/src/core/util/unique_ptr_with_bitset.h +5 -5
- data/src/core/util/unique_type_name.h +1 -1
- data/src/core/util/upb_utils.h +6 -1
- data/src/core/util/validation_errors.cc +2 -2
- data/src/core/util/validation_errors.h +2 -3
- data/src/core/util/wait_for_single_owner.h +2 -2
- data/src/core/util/windows/directory_reader.cc +1 -1
- data/src/core/util/windows/stat.cc +2 -2
- data/src/core/util/windows/thd.cc +2 -2
- data/src/core/util/windows/time.cc +1 -1
- data/src/core/util/work_serializer.cc +3 -3
- data/src/core/util/work_serializer.h +2 -2
- data/src/core/xds/grpc/certificate_provider_store.cc +2 -2
- data/src/core/xds/grpc/certificate_provider_store.h +2 -2
- data/src/core/xds/grpc/file_watcher_certificate_provider_factory.cc +3 -3
- data/src/core/xds/grpc/file_watcher_certificate_provider_factory.h +1 -1
- data/src/core/xds/grpc/xds_audit_logger_registry.cc +3 -3
- data/src/core/xds/grpc/xds_audit_logger_registry.h +1 -1
- data/src/core/xds/grpc/xds_bootstrap_grpc.cc +7 -7
- data/src/core/xds/grpc/xds_bootstrap_grpc.h +8 -3
- data/src/core/xds/grpc/xds_certificate_provider.cc +4 -4
- data/src/core/xds/grpc/xds_certificate_provider.h +2 -2
- data/src/core/xds/grpc/xds_client_grpc.cc +39 -20
- data/src/core/xds/grpc/xds_client_grpc.h +6 -3
- data/src/core/xds/grpc/xds_cluster.cc +2 -2
- data/src/core/xds/grpc/xds_cluster.h +1 -1
- data/src/core/xds/grpc/xds_cluster_parser.cc +7 -7
- data/src/core/xds/grpc/xds_cluster_parser.h +1 -1
- data/src/core/xds/grpc/xds_cluster_specifier_plugin.cc +4 -4
- data/src/core/xds/grpc/xds_cluster_specifier_plugin.h +1 -1
- data/src/core/xds/grpc/xds_common_types.cc +1 -1
- data/src/core/xds/grpc/xds_common_types.h +1 -1
- data/src/core/xds/grpc/xds_common_types_parser.cc +5 -5
- data/src/core/xds/grpc/xds_endpoint.h +2 -2
- data/src/core/xds/grpc/xds_endpoint_parser.cc +7 -7
- data/src/core/xds/grpc/xds_endpoint_parser.h +1 -1
- data/src/core/xds/grpc/xds_health_status.cc +1 -1
- data/src/core/xds/grpc/xds_health_status.h +1 -1
- data/src/core/xds/grpc/xds_http_fault_filter.cc +4 -4
- data/src/core/xds/grpc/xds_http_fault_filter.h +2 -2
- data/src/core/xds/grpc/xds_http_filter.h +3 -3
- data/src/core/xds/grpc/xds_http_filter_registry.cc +4 -3
- data/src/core/xds/grpc/xds_http_filter_registry.h +2 -2
- data/src/core/xds/grpc/xds_http_gcp_authn_filter.cc +3 -3
- data/src/core/xds/grpc/xds_http_gcp_authn_filter.h +2 -2
- data/src/core/xds/grpc/xds_http_rbac_filter.cc +4 -4
- data/src/core/xds/grpc/xds_http_rbac_filter.h +2 -2
- data/src/core/xds/grpc/xds_http_stateful_session_filter.cc +3 -3
- data/src/core/xds/grpc/xds_http_stateful_session_filter.h +2 -2
- data/src/core/xds/grpc/xds_lb_policy_registry.cc +1 -1
- data/src/core/xds/grpc/xds_lb_policy_registry.h +1 -1
- data/src/core/xds/grpc/xds_listener.cc +2 -2
- data/src/core/xds/grpc/xds_listener_parser.cc +9 -9
- data/src/core/xds/grpc/xds_listener_parser.h +1 -1
- data/src/core/xds/grpc/xds_matcher.cc +277 -0
- data/src/core/xds/grpc/xds_matcher.h +432 -0
- data/src/core/xds/grpc/xds_matcher_action.cc +47 -0
- data/src/core/xds/grpc/xds_matcher_action.h +48 -0
- data/src/core/xds/grpc/xds_matcher_context.cc +29 -0
- data/src/core/xds/grpc/xds_matcher_context.h +46 -0
- data/src/core/xds/grpc/xds_matcher_input.cc +79 -0
- data/src/core/xds/grpc/xds_matcher_input.h +105 -0
- data/src/core/xds/grpc/xds_matcher_parse.cc +356 -0
- data/src/core/xds/grpc/xds_matcher_parse.h +39 -0
- data/src/core/xds/grpc/xds_metadata.cc +4 -3
- data/src/core/xds/grpc/xds_metadata.h +3 -3
- data/src/core/xds/grpc/xds_metadata_parser.cc +2 -2
- data/src/core/xds/grpc/xds_route_config.cc +3 -3
- data/src/core/xds/grpc/xds_route_config_parser.cc +14 -14
- data/src/core/xds/grpc/xds_route_config_parser.h +1 -1
- data/src/core/xds/grpc/xds_routing.cc +6 -6
- data/src/core/xds/grpc/xds_routing.h +2 -2
- data/src/core/xds/grpc/xds_server_grpc.cc +2 -2
- data/src/core/xds/grpc/xds_transport_grpc.cc +11 -11
- data/src/core/xds/grpc/xds_transport_grpc.h +2 -2
- data/src/core/xds/xds_client/lrs_client.cc +9 -9
- data/src/core/xds/xds_client/lrs_client.h +4 -4
- data/src/core/xds/xds_client/xds_api.h +1 -1
- data/src/core/xds/xds_client/xds_backend_metric_propagation.cc +1 -1
- data/src/core/xds/xds_client/xds_backend_metric_propagation.h +1 -1
- data/src/core/xds/xds_client/xds_client.cc +17 -17
- data/src/core/xds/xds_client/xds_client.h +5 -5
- data/src/core/xds/xds_client/xds_locality.h +2 -2
- data/src/core/xds/xds_client/xds_resource_type.h +2 -2
- data/src/core/xds/xds_client/xds_resource_type_impl.h +1 -1
- data/src/core/xds/xds_client/xds_transport.h +2 -2
- data/src/ruby/ext/grpc/extconf.rb +14 -12
- data/src/ruby/ext/grpc/rb_call.c +0 -1
- data/src/ruby/ext/grpc/rb_channel_args.c +0 -1
- data/src/ruby/ext/grpc/rb_channel_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_compression_options.c +0 -1
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +2 -2
- data/src/ruby/ext/grpc/rb_server_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +0 -1
- data/src/ruby/ext/grpc/rb_xds_server_credentials.c +0 -1
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/third_party/abseil-cpp/absl/container/internal/node_slot_policy.h +95 -0
- data/third_party/abseil-cpp/absl/container/node_hash_map.h +687 -0
- metadata +51 -6
|
@@ -19,49 +19,95 @@
|
|
|
19
19
|
#include "src/core/ext/transport/chttp2/transport/http2_client_transport.h"
|
|
20
20
|
|
|
21
21
|
#include <grpc/event_engine/event_engine.h>
|
|
22
|
+
#include <grpc/grpc.h>
|
|
22
23
|
#include <grpc/support/port_platform.h>
|
|
24
|
+
#include <limits.h>
|
|
23
25
|
|
|
26
|
+
#include <algorithm>
|
|
27
|
+
#include <cstddef>
|
|
24
28
|
#include <cstdint>
|
|
29
|
+
#include <iterator>
|
|
25
30
|
#include <memory>
|
|
26
31
|
#include <optional>
|
|
32
|
+
#include <string>
|
|
27
33
|
#include <utility>
|
|
34
|
+
#include <vector>
|
|
28
35
|
|
|
29
|
-
#include "absl/log/check.h"
|
|
30
|
-
#include "absl/log/log.h"
|
|
31
|
-
#include "absl/status/status.h"
|
|
32
36
|
#include "src/core/call/call_spine.h"
|
|
33
37
|
#include "src/core/call/message.h"
|
|
38
|
+
#include "src/core/call/metadata.h"
|
|
34
39
|
#include "src/core/call/metadata_batch.h"
|
|
40
|
+
#include "src/core/call/metadata_info.h"
|
|
41
|
+
#include "src/core/channelz/channelz.h"
|
|
42
|
+
#include "src/core/ext/transport/chttp2/transport/flow_control.h"
|
|
43
|
+
#include "src/core/ext/transport/chttp2/transport/flow_control_manager.h"
|
|
35
44
|
#include "src/core/ext/transport/chttp2/transport/frame.h"
|
|
45
|
+
#include "src/core/ext/transport/chttp2/transport/goaway.h"
|
|
36
46
|
#include "src/core/ext/transport/chttp2/transport/header_assembler.h"
|
|
37
47
|
#include "src/core/ext/transport/chttp2/transport/http2_settings.h"
|
|
38
|
-
#include "src/core/ext/transport/chttp2/transport/
|
|
48
|
+
#include "src/core/ext/transport/chttp2/transport/http2_settings_promises.h"
|
|
39
49
|
#include "src/core/ext/transport/chttp2/transport/http2_status.h"
|
|
40
|
-
#include "src/core/ext/transport/chttp2/transport/
|
|
50
|
+
#include "src/core/ext/transport/chttp2/transport/http2_transport.h"
|
|
51
|
+
#include "src/core/ext/transport/chttp2/transport/http2_ztrace_collector.h"
|
|
52
|
+
#include "src/core/ext/transport/chttp2/transport/incoming_metadata_tracker.h"
|
|
53
|
+
#include "src/core/ext/transport/chttp2/transport/keepalive.h"
|
|
41
54
|
#include "src/core/ext/transport/chttp2/transport/message_assembler.h"
|
|
55
|
+
#include "src/core/ext/transport/chttp2/transport/ping_promise.h"
|
|
56
|
+
#include "src/core/ext/transport/chttp2/transport/stream.h"
|
|
57
|
+
#include "src/core/ext/transport/chttp2/transport/stream_data_queue.h"
|
|
42
58
|
#include "src/core/ext/transport/chttp2/transport/transport_common.h"
|
|
43
59
|
#include "src/core/lib/channel/channel_args.h"
|
|
44
|
-
#include "src/core/lib/
|
|
60
|
+
#include "src/core/lib/iomgr/exec_ctx.h"
|
|
61
|
+
#include "src/core/lib/promise/activity.h"
|
|
62
|
+
#include "src/core/lib/promise/context.h"
|
|
45
63
|
#include "src/core/lib/promise/for_each.h"
|
|
64
|
+
#include "src/core/lib/promise/if.h"
|
|
46
65
|
#include "src/core/lib/promise/loop.h"
|
|
47
66
|
#include "src/core/lib/promise/map.h"
|
|
48
67
|
#include "src/core/lib/promise/match_promise.h"
|
|
49
68
|
#include "src/core/lib/promise/party.h"
|
|
50
69
|
#include "src/core/lib/promise/poll.h"
|
|
51
70
|
#include "src/core/lib/promise/promise.h"
|
|
71
|
+
#include "src/core/lib/promise/race.h"
|
|
72
|
+
#include "src/core/lib/promise/sleep.h"
|
|
52
73
|
#include "src/core/lib/promise/try_seq.h"
|
|
53
74
|
#include "src/core/lib/resource_quota/arena.h"
|
|
75
|
+
#include "src/core/lib/resource_quota/resource_quota.h"
|
|
54
76
|
#include "src/core/lib/slice/slice.h"
|
|
55
77
|
#include "src/core/lib/slice/slice_buffer.h"
|
|
78
|
+
#include "src/core/lib/transport/connectivity_state.h"
|
|
56
79
|
#include "src/core/lib/transport/promise_endpoint.h"
|
|
57
80
|
#include "src/core/lib/transport/transport.h"
|
|
81
|
+
#include "src/core/util/debug_location.h"
|
|
82
|
+
#include "src/core/util/grpc_check.h"
|
|
83
|
+
#include "src/core/util/latent_see.h"
|
|
84
|
+
#include "src/core/util/orphanable.h"
|
|
58
85
|
#include "src/core/util/ref_counted_ptr.h"
|
|
59
86
|
#include "src/core/util/sync.h"
|
|
87
|
+
#include "src/core/util/time.h"
|
|
88
|
+
#include "absl/base/thread_annotations.h"
|
|
89
|
+
#include "absl/container/flat_hash_map.h"
|
|
90
|
+
#include "absl/log/log.h"
|
|
91
|
+
#include "absl/status/status.h"
|
|
92
|
+
#include "absl/strings/cord.h"
|
|
93
|
+
#include "absl/strings/str_cat.h"
|
|
94
|
+
#include "absl/strings/string_view.h"
|
|
95
|
+
#include "absl/types/span.h"
|
|
60
96
|
|
|
61
97
|
namespace grpc_core {
|
|
62
98
|
namespace http2 {
|
|
63
99
|
|
|
100
|
+
// TODO(akshitpatel)(tjagtap) [PH2][P2] : When settings frame increases incoming
|
|
101
|
+
// window size, our transport must make the streams that were blocked on stream
|
|
102
|
+
// flow control as writeable.
|
|
103
|
+
|
|
104
|
+
// As a gRPC server never initiates a stream, the last incoming stream id on
|
|
105
|
+
// the client side will always be 0.
|
|
106
|
+
constexpr uint32_t kLastIncomingStreamIdClient = 0;
|
|
107
|
+
|
|
64
108
|
using grpc_event_engine::experimental::EventEngine;
|
|
109
|
+
using StreamWritabilityUpdate =
|
|
110
|
+
StreamDataQueue<ClientMetadataHandle>::StreamWritabilityUpdate;
|
|
65
111
|
|
|
66
112
|
// Experimental : This is just the initial skeleton of class
|
|
67
113
|
// and it is functions. The code will be written iteratively.
|
|
@@ -70,6 +116,32 @@ using grpc_event_engine::experimental::EventEngine;
|
|
|
70
116
|
// TODO(tjagtap) : [PH2][P3] : Delete this comment when http2
|
|
71
117
|
// rollout begins
|
|
72
118
|
|
|
119
|
+
template <typename Factory>
|
|
120
|
+
void Http2ClientTransport::SpawnInfallible(RefCountedPtr<Party> party,
|
|
121
|
+
absl::string_view name,
|
|
122
|
+
Factory&& factory) {
|
|
123
|
+
party->Spawn(name, std::forward<Factory>(factory), [](Empty) {});
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
template <typename Factory>
|
|
127
|
+
void Http2ClientTransport::SpawnInfallibleTransportParty(absl::string_view name,
|
|
128
|
+
Factory&& factory) {
|
|
129
|
+
SpawnInfallible(general_party_, name, std::forward<Factory>(factory));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
template <typename Factory>
|
|
133
|
+
void Http2ClientTransport::SpawnGuardedTransportParty(absl::string_view name,
|
|
134
|
+
Factory&& factory) {
|
|
135
|
+
general_party_->Spawn(
|
|
136
|
+
name, std::forward<Factory>(factory),
|
|
137
|
+
[self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
|
|
138
|
+
if (!status.ok()) {
|
|
139
|
+
GRPC_UNUSED absl::Status error = self->HandleError(
|
|
140
|
+
/*stream_id=*/std::nullopt, ToHttpOkOrConnError(status));
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
73
145
|
void Http2ClientTransport::PerformOp(grpc_transport_op* op) {
|
|
74
146
|
// Notes : Refer : src/core/ext/transport/chaotic_good/client_transport.cc
|
|
75
147
|
// Functions : StartConnectivityWatch, StopConnectivityWatch, PerformOp
|
|
@@ -84,8 +156,9 @@ void Http2ClientTransport::PerformOp(grpc_transport_op* op) {
|
|
|
84
156
|
StopConnectivityWatch(op->stop_connectivity_watch);
|
|
85
157
|
did_stuff = true;
|
|
86
158
|
}
|
|
87
|
-
|
|
88
|
-
|
|
159
|
+
GRPC_CHECK(!op->set_accept_stream)
|
|
160
|
+
<< "Set_accept_stream not supported on clients";
|
|
161
|
+
GRPC_DCHECK(did_stuff) << "Unimplemented transport perform op ";
|
|
89
162
|
|
|
90
163
|
ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, absl::OkStatus());
|
|
91
164
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport PerformOp End";
|
|
@@ -110,90 +183,145 @@ void Http2ClientTransport::StopConnectivityWatch(
|
|
|
110
183
|
state_tracker_.RemoveWatcher(watcher);
|
|
111
184
|
}
|
|
112
185
|
|
|
186
|
+
void Http2ClientTransport::ReportDisconnection(
|
|
187
|
+
const absl::Status& status, StateWatcher::DisconnectInfo disconnect_info,
|
|
188
|
+
const char* reason) {
|
|
189
|
+
MutexLock lock(&transport_mutex_);
|
|
190
|
+
ReportDisconnectionLocked(status, disconnect_info, reason);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
void Http2ClientTransport::ReportDisconnectionLocked(
|
|
194
|
+
const absl::Status& status, StateWatcher::DisconnectInfo disconnect_info,
|
|
195
|
+
const char* reason) {
|
|
196
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ReportDisconnection: status="
|
|
197
|
+
<< status.ToString() << "; reason=" << reason;
|
|
198
|
+
state_tracker_.SetState(GRPC_CHANNEL_TRANSIENT_FAILURE, status, reason);
|
|
199
|
+
NotifyStateWatcherOnDisconnectLocked(status, disconnect_info);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
void Http2ClientTransport::StartWatch(RefCountedPtr<StateWatcher> watcher) {
|
|
203
|
+
MutexLock lock(&transport_mutex_);
|
|
204
|
+
GRPC_CHECK(watcher_ == nullptr);
|
|
205
|
+
watcher_ = std::move(watcher);
|
|
206
|
+
if (is_transport_closed_) {
|
|
207
|
+
// TODO(tjagtap) : [PH2][P2] : Provide better status message and
|
|
208
|
+
// disconnect info here.
|
|
209
|
+
NotifyStateWatcherOnDisconnectLocked(
|
|
210
|
+
absl::UnknownError("transport closed before watcher started"), {});
|
|
211
|
+
} else {
|
|
212
|
+
// TODO(tjagtap) : [PH2][P2] : Notify the state watcher of the current
|
|
213
|
+
// value of the peer's MAX_CONCURRENT_STREAMS setting.
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
void Http2ClientTransport::StopWatch(RefCountedPtr<StateWatcher> watcher) {
|
|
218
|
+
MutexLock lock(&transport_mutex_);
|
|
219
|
+
if (watcher_ == watcher) watcher_.reset();
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
void Http2ClientTransport::NotifyStateWatcherOnDisconnectLocked(
|
|
223
|
+
absl::Status status, StateWatcher::DisconnectInfo disconnect_info) {
|
|
224
|
+
if (watcher_ == nullptr) return;
|
|
225
|
+
event_engine_->Run([watcher = std::move(watcher_), status = std::move(status),
|
|
226
|
+
disconnect_info]() mutable {
|
|
227
|
+
ExecCtx exec_ctx;
|
|
228
|
+
watcher->OnDisconnect(std::move(status), disconnect_info);
|
|
229
|
+
watcher.reset(); // Before ExecCtx goes out of scope.
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
|
|
113
233
|
void Http2ClientTransport::Orphan() {
|
|
114
234
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Orphan Begin";
|
|
115
235
|
// Accessing general_party here is not advisable. It may so happen that
|
|
116
236
|
// the party is already freed/may free up any time. The only guarantee here
|
|
117
237
|
// is that the transport is still valid.
|
|
118
|
-
|
|
119
|
-
|
|
238
|
+
SourceDestructing();
|
|
239
|
+
MaybeSpawnCloseTransport(
|
|
240
|
+
ToHttpOkOrConnError(absl::UnavailableError("Orphaned")));
|
|
120
241
|
Unref();
|
|
121
242
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Orphan End";
|
|
122
243
|
}
|
|
123
244
|
|
|
124
|
-
void Http2ClientTransport::AbortWithError() {
|
|
125
|
-
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport AbortWithError Begin";
|
|
126
|
-
// TODO(tjagtap) : [PH2][P2] : Implement this function.
|
|
127
|
-
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport AbortWithError End";
|
|
128
|
-
}
|
|
129
|
-
|
|
130
245
|
///////////////////////////////////////////////////////////////////////////////
|
|
131
246
|
// Processing each type of frame
|
|
132
247
|
|
|
133
248
|
Http2Status Http2ClientTransport::ProcessHttp2DataFrame(Http2DataFrame frame) {
|
|
134
249
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-data
|
|
135
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
250
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
251
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame { stream_id="
|
|
252
|
+
<< frame.stream_id << ", end_stream=" << frame.end_stream
|
|
253
|
+
<< ", payload=" << MaybeTruncatePayload(frame.payload)
|
|
254
|
+
<< ", payload length=" << frame.payload.Length() << "}";
|
|
140
255
|
|
|
141
256
|
// TODO(akshitpatel) : [PH2][P3] : Investigate if we should do this even if
|
|
142
257
|
// the function returns a non-ok status?
|
|
143
|
-
ping_manager_
|
|
258
|
+
ping_manager_->ReceivedDataFrame();
|
|
144
259
|
|
|
145
260
|
// Lookup stream
|
|
146
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
261
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
262
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame LookupStream";
|
|
147
263
|
RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
|
|
264
|
+
|
|
265
|
+
ValueOrHttp2Status<chttp2::FlowControlAction> flow_control_action =
|
|
266
|
+
ProcessIncomingDataFrameFlowControl(current_frame_header_, flow_control_,
|
|
267
|
+
stream);
|
|
268
|
+
if (!flow_control_action.IsOk()) {
|
|
269
|
+
return ValueOrHttp2Status<chttp2::FlowControlAction>::TakeStatus(
|
|
270
|
+
std::move(flow_control_action));
|
|
271
|
+
}
|
|
272
|
+
ActOnFlowControlAction(flow_control_action.value(), stream);
|
|
273
|
+
|
|
148
274
|
if (stream == nullptr) {
|
|
149
275
|
// TODO(tjagtap) : [PH2][P2] : Implement the correct behaviour later.
|
|
150
276
|
// RFC9113 : If a DATA frame is received whose stream is not in the "open"
|
|
151
277
|
// or "half-closed (local)" state, the recipient MUST respond with a stream
|
|
152
278
|
// error (Section 5.4.2) of type STREAM_CLOSED.
|
|
153
279
|
GRPC_HTTP2_CLIENT_DLOG
|
|
154
|
-
<< "
|
|
280
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame { stream_id="
|
|
155
281
|
<< frame.stream_id << "} Lookup Failed";
|
|
156
282
|
return Http2Status::Ok();
|
|
157
283
|
}
|
|
158
284
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
285
|
+
// TODO(akshitpatel) : [PH2][P3] : We should add a check to reset stream if
|
|
286
|
+
// the stream state is kIdle as well.
|
|
287
|
+
|
|
288
|
+
Http2Status stream_status = stream->CanStreamReceiveDataFrames();
|
|
289
|
+
if (!stream_status.IsOk()) {
|
|
290
|
+
return stream_status;
|
|
163
291
|
}
|
|
164
292
|
|
|
165
293
|
// Add frame to assembler
|
|
166
294
|
GRPC_HTTP2_CLIENT_DLOG
|
|
167
|
-
<< "
|
|
295
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame AppendNewDataFrame";
|
|
168
296
|
GrpcMessageAssembler& assembler = stream->assembler;
|
|
169
297
|
Http2Status status =
|
|
170
298
|
assembler.AppendNewDataFrame(frame.payload, frame.end_stream);
|
|
171
299
|
if (!status.IsOk()) {
|
|
172
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
173
|
-
|
|
300
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ProcessHttp2DataFrame "
|
|
301
|
+
"AppendNewDataFrame Failed";
|
|
174
302
|
return status;
|
|
175
303
|
}
|
|
176
304
|
|
|
177
305
|
// Pass the messages up the stack if it is ready.
|
|
178
306
|
while (true) {
|
|
179
307
|
GRPC_HTTP2_CLIENT_DLOG
|
|
180
|
-
<< "
|
|
308
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame ExtractMessage";
|
|
181
309
|
ValueOrHttp2Status<MessageHandle> result = assembler.ExtractMessage();
|
|
182
310
|
if (!result.IsOk()) {
|
|
183
311
|
GRPC_HTTP2_CLIENT_DLOG
|
|
184
|
-
<< "
|
|
312
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame ExtractMessage Failed";
|
|
185
313
|
return ValueOrHttp2Status<MessageHandle>::TakeStatus(std::move(result));
|
|
186
314
|
}
|
|
187
315
|
MessageHandle message = TakeValue(std::move(result));
|
|
188
316
|
if (message != nullptr) {
|
|
189
317
|
GRPC_HTTP2_CLIENT_DLOG
|
|
190
|
-
<< "
|
|
318
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame SpawnPushMessage "
|
|
191
319
|
<< message->DebugString();
|
|
192
320
|
stream->call.SpawnPushMessage(std::move(message));
|
|
193
321
|
continue;
|
|
194
322
|
}
|
|
195
323
|
GRPC_HTTP2_CLIENT_DLOG
|
|
196
|
-
<< "
|
|
324
|
+
<< "Http2ClientTransport ProcessHttp2DataFrame While Break";
|
|
197
325
|
break;
|
|
198
326
|
}
|
|
199
327
|
|
|
@@ -213,14 +341,16 @@ Http2Status Http2ClientTransport::ProcessHttp2HeaderFrame(
|
|
|
213
341
|
Http2HeaderFrame frame) {
|
|
214
342
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-headers
|
|
215
343
|
GRPC_HTTP2_CLIENT_DLOG
|
|
216
|
-
<< "
|
|
344
|
+
<< "Http2ClientTransport ProcessHttp2HeaderFrame Promise { stream_id="
|
|
217
345
|
<< frame.stream_id << ", end_headers=" << frame.end_headers
|
|
218
346
|
<< ", end_stream=" << frame.end_stream
|
|
219
|
-
<< ", payload=" << frame.payload
|
|
220
|
-
|
|
347
|
+
<< ", payload=" << MaybeTruncatePayload(frame.payload) << " }";
|
|
348
|
+
// State update MUST happen before processing the frame.
|
|
349
|
+
incoming_headers_.OnHeaderReceived(frame);
|
|
350
|
+
|
|
351
|
+
ping_manager_->ReceivedDataFrame();
|
|
221
352
|
|
|
222
|
-
RefCountedPtr<
|
|
223
|
-
LookupStream(frame.stream_id);
|
|
353
|
+
RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
|
|
224
354
|
if (stream == nullptr) {
|
|
225
355
|
// TODO(tjagtap) : [PH2][P3] : Implement this.
|
|
226
356
|
// RFC9113 : The identifier of a newly established stream MUST be
|
|
@@ -230,76 +360,82 @@ Http2Status Http2ClientTransport::ProcessHttp2HeaderFrame(
|
|
|
230
360
|
// receives an unexpected stream identifier MUST respond with a connection
|
|
231
361
|
// error (Section 5.4.1) of type PROTOCOL_ERROR.
|
|
232
362
|
GRPC_HTTP2_CLIENT_DLOG
|
|
233
|
-
<< "
|
|
363
|
+
<< "Http2ClientTransport ProcessHttp2HeaderFrame Promise { stream_id="
|
|
234
364
|
<< frame.stream_id << "} Lookup Failed";
|
|
235
|
-
return
|
|
365
|
+
return ParseAndDiscardHeaders(std::move(frame.payload), frame.end_headers,
|
|
366
|
+
/*stream=*/nullptr, Http2Status::Ok());
|
|
236
367
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
std::
|
|
368
|
+
|
|
369
|
+
if (stream->IsStreamHalfClosedRemote()) {
|
|
370
|
+
return ParseAndDiscardHeaders(
|
|
371
|
+
std::move(frame.payload), frame.end_headers, stream,
|
|
372
|
+
Http2Status::Http2StreamError(
|
|
373
|
+
Http2ErrorCode::kStreamClosed,
|
|
374
|
+
std::string(RFC9113::kHalfClosedRemoteState)));
|
|
241
375
|
}
|
|
242
376
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
"by upto 1 trailing metadata");
|
|
377
|
+
if (incoming_headers_.ClientReceivedDuplicateMetadata(
|
|
378
|
+
stream->did_receive_initial_metadata,
|
|
379
|
+
stream->did_receive_trailing_metadata)) {
|
|
380
|
+
return ParseAndDiscardHeaders(
|
|
381
|
+
std::move(frame.payload), frame.end_headers, stream,
|
|
382
|
+
Http2Status::Http2StreamError(
|
|
383
|
+
Http2ErrorCode::kInternalError,
|
|
384
|
+
std::string(GrpcErrors::kTooManyMetadata)));
|
|
252
385
|
}
|
|
253
386
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
387
|
+
Http2Status append_result = stream->header_assembler.AppendHeaderFrame(frame);
|
|
388
|
+
if (!append_result.IsOk()) {
|
|
389
|
+
// Frame payload is not consumed if AppendHeaderFrame returns a non-OK
|
|
390
|
+
// status. We need to process it to keep our in consistent state.
|
|
391
|
+
return ParseAndDiscardHeaders(std::move(frame.payload), frame.end_headers,
|
|
392
|
+
stream, std::move(append_result));
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
Http2Status status = ProcessMetadata(stream);
|
|
396
|
+
if (!status.IsOk()) {
|
|
397
|
+
// Frame payload has been moved to the HeaderAssembler. So calling
|
|
398
|
+
// ParseAndDiscardHeaders with an empty buffer.
|
|
399
|
+
return ParseAndDiscardHeaders(SliceBuffer(), frame.end_headers, stream,
|
|
400
|
+
std::move(status));
|
|
260
401
|
}
|
|
261
|
-
|
|
402
|
+
|
|
403
|
+
// Frame payload has either been processed or moved to the HeaderAssembler.
|
|
404
|
+
return Http2Status::Ok();
|
|
262
405
|
}
|
|
263
406
|
|
|
264
407
|
Http2Status Http2ClientTransport::ProcessMetadata(
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
408
|
+
RefCountedPtr<Stream> stream) {
|
|
409
|
+
HeaderAssembler& assembler = stream->header_assembler;
|
|
410
|
+
CallHandler call = stream->call;
|
|
411
|
+
|
|
412
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ProcessMetadata";
|
|
268
413
|
if (assembler.IsReady()) {
|
|
269
|
-
ValueOrHttp2Status<
|
|
270
|
-
assembler.ReadMetadata(parser_, !
|
|
414
|
+
ValueOrHttp2Status<ServerMetadataHandle> read_result =
|
|
415
|
+
assembler.ReadMetadata(parser_, !incoming_headers_.HeaderHasEndStream(),
|
|
271
416
|
/*is_client=*/true,
|
|
272
417
|
/*max_header_list_size_soft_limit=*/
|
|
273
|
-
|
|
418
|
+
incoming_headers_.soft_limit(),
|
|
274
419
|
/*max_header_list_size_hard_limit=*/
|
|
275
|
-
settings_
|
|
420
|
+
settings_->acked().max_header_list_size());
|
|
276
421
|
if (read_result.IsOk()) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (incoming_header_end_stream_) {
|
|
422
|
+
ServerMetadataHandle metadata = TakeValue(std::move(read_result));
|
|
423
|
+
if (incoming_headers_.HeaderHasEndStream()) {
|
|
280
424
|
// TODO(tjagtap) : [PH2][P1] : Is this the right way to differentiate
|
|
281
425
|
// between initial and trailing metadata?
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
CloseStream(stream_id, absl::OkStatus(),
|
|
287
|
-
CloseStreamArgs{
|
|
288
|
-
/*close_reads=*/true,
|
|
289
|
-
/*close_writes=*/true,
|
|
290
|
-
/*send_rst_stream=*/false,
|
|
291
|
-
/*should_not_push_trailers=*/true,
|
|
292
|
-
});
|
|
293
|
-
|
|
426
|
+
stream->MarkHalfClosedRemote();
|
|
427
|
+
stream->did_receive_trailing_metadata = true;
|
|
428
|
+
BeginCloseStream(stream, /*reset_stream_error_code=*/std::nullopt,
|
|
429
|
+
std::move(metadata));
|
|
294
430
|
} else {
|
|
295
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
296
|
-
|
|
297
|
-
|
|
431
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ProcessMetadata "
|
|
432
|
+
"SpawnPushServerInitialMetadata";
|
|
433
|
+
stream->did_receive_initial_metadata = true;
|
|
298
434
|
call.SpawnPushServerInitialMetadata(std::move(metadata));
|
|
299
435
|
}
|
|
300
436
|
return Http2Status::Ok();
|
|
301
437
|
}
|
|
302
|
-
GRPC_HTTP2_CLIENT_DLOG << "
|
|
438
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ProcessMetadata Failed";
|
|
303
439
|
return ValueOrHttp2Status<Arena::PoolPtr<grpc_metadata_batch>>::TakeStatus(
|
|
304
440
|
std::move(read_result));
|
|
305
441
|
}
|
|
@@ -310,19 +446,19 @@ Http2Status Http2ClientTransport::ProcessHttp2RstStreamFrame(
|
|
|
310
446
|
Http2RstStreamFrame frame) {
|
|
311
447
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-rst_stream
|
|
312
448
|
GRPC_HTTP2_CLIENT_DLOG
|
|
313
|
-
<< "
|
|
449
|
+
<< "Http2ClientTransport ProcessHttp2RstStreamFrame { stream_id="
|
|
314
450
|
<< frame.stream_id << ", error_code=" << frame.error_code << " }";
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
451
|
+
|
|
452
|
+
Http2ErrorCode error_code = FrameErrorCodeToHttp2ErrorCode(frame.error_code);
|
|
453
|
+
absl::Status status = absl::Status(ErrorCodeToAbslStatusCode(error_code),
|
|
454
|
+
"Reset stream frame received.");
|
|
455
|
+
RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
|
|
456
|
+
if (stream != nullptr) {
|
|
457
|
+
stream->MarkHalfClosedRemote();
|
|
458
|
+
BeginCloseStream(stream, /*reset_stream_error_code=*/std::nullopt,
|
|
459
|
+
CancelledServerMetadataFromStatus(status));
|
|
460
|
+
}
|
|
461
|
+
|
|
326
462
|
// In case of stream error, we do not want the Read Loop to be broken. Hence
|
|
327
463
|
// returning an ok status.
|
|
328
464
|
return Http2Status::Ok();
|
|
@@ -332,30 +468,34 @@ Http2Status Http2ClientTransport::ProcessHttp2SettingsFrame(
|
|
|
332
468
|
Http2SettingsFrame frame) {
|
|
333
469
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-settings
|
|
334
470
|
|
|
335
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
<< "}";
|
|
339
|
-
|
|
340
|
-
// The connector code needs us to run this
|
|
341
|
-
if (on_receive_settings_ != nullptr) {
|
|
342
|
-
ExecCtx::Run(DEBUG_LOCATION, on_receive_settings_, absl::OkStatus());
|
|
343
|
-
on_receive_settings_ = nullptr;
|
|
344
|
-
}
|
|
471
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
472
|
+
<< "Http2ClientTransport ProcessHttp2SettingsFrame { ack=" << frame.ack
|
|
473
|
+
<< ", settings length=" << frame.settings.size() << "}";
|
|
345
474
|
|
|
346
475
|
if (!frame.ack) {
|
|
347
|
-
// Check if the received settings have legal values
|
|
348
476
|
Http2Status status = ValidateSettingsValues(frame.settings);
|
|
349
477
|
if (!status.IsOk()) {
|
|
350
478
|
return status;
|
|
351
479
|
}
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
480
|
+
settings_->BufferPeerSettings(std::move(frame.settings));
|
|
481
|
+
SpawnGuardedTransportParty("SettingsAck", TriggerWriteCycle());
|
|
482
|
+
if (GPR_UNLIKELY(!settings_->IsFirstPeerSettingsApplied())) {
|
|
483
|
+
// Apply the first settings before we read any other frames.
|
|
484
|
+
reader_state_.SetPauseReadLoop();
|
|
485
|
+
}
|
|
355
486
|
} else {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
487
|
+
if (settings_->OnSettingsAckReceived()) {
|
|
488
|
+
parser_.hpack_table()->SetMaxBytes(
|
|
489
|
+
settings_->acked().header_table_size());
|
|
490
|
+
ActOnFlowControlAction(flow_control_.SetAckedInitialWindow(
|
|
491
|
+
settings_->acked().initial_window_size()),
|
|
492
|
+
/*stream=*/nullptr);
|
|
493
|
+
} else {
|
|
494
|
+
// TODO(tjagtap) [PH2][P4] : The RFC does not say anything about what
|
|
495
|
+
// should happen if we receive an unsolicited SETTINGS ACK. Decide if we
|
|
496
|
+
// want to respond with any error or just proceed.
|
|
497
|
+
LOG(ERROR) << "Settings ack received without sending settings";
|
|
498
|
+
}
|
|
359
499
|
}
|
|
360
500
|
|
|
361
501
|
return Http2Status::Ok();
|
|
@@ -363,7 +503,7 @@ Http2Status Http2ClientTransport::ProcessHttp2SettingsFrame(
|
|
|
363
503
|
|
|
364
504
|
auto Http2ClientTransport::ProcessHttp2PingFrame(Http2PingFrame frame) {
|
|
365
505
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-ping
|
|
366
|
-
GRPC_HTTP2_CLIENT_DLOG << "
|
|
506
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ProcessHttp2PingFrame { ack="
|
|
367
507
|
<< frame.ack << ", opaque=" << frame.opaque << " }";
|
|
368
508
|
return AssertResultType<Http2Status>(If(
|
|
369
509
|
frame.ack,
|
|
@@ -372,37 +512,114 @@ auto Http2ClientTransport::ProcessHttp2PingFrame(Http2PingFrame frame) {
|
|
|
372
512
|
return self->AckPing(opaque);
|
|
373
513
|
},
|
|
374
514
|
[self = RefAsSubclass<Http2ClientTransport>(), opaque = frame.opaque]() {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
515
|
+
return If(
|
|
516
|
+
self->test_only_ack_pings_,
|
|
517
|
+
[self, opaque]() {
|
|
518
|
+
// TODO(akshitpatel) : [PH2][P2] : Have a counter to track number
|
|
519
|
+
// of pending induced frames (Ping/Settings Ack). This is to
|
|
520
|
+
// ensure that if write is taking a long time, we can stop reads
|
|
521
|
+
// and prioritize writes. RFC9113: PING responses SHOULD be given
|
|
522
|
+
// higher priority than any other frame.
|
|
523
|
+
self->ping_manager_->AddPendingPingAck(opaque);
|
|
524
|
+
// TODO(akshitpatel) : [PH2][P2] : This is done assuming that the
|
|
525
|
+
// other ProcessFrame promises may return stream or connection
|
|
526
|
+
// failures. If this does not turn out to be true, consider
|
|
527
|
+
// returning absl::Status here.
|
|
528
|
+
return Map(self->TriggerWriteCycle(), [](absl::Status status) {
|
|
529
|
+
return ToHttpOkOrConnError(status);
|
|
530
|
+
});
|
|
531
|
+
},
|
|
532
|
+
[]() {
|
|
533
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
534
|
+
<< "Http2ClientTransport ProcessHttp2PingFrame "
|
|
535
|
+
"test_only_ack_pings_ is false. Ignoring the ping "
|
|
536
|
+
"request.";
|
|
537
|
+
return Immediate(Http2Status::Ok());
|
|
538
|
+
});
|
|
392
539
|
}));
|
|
393
540
|
}
|
|
394
541
|
|
|
395
542
|
Http2Status Http2ClientTransport::ProcessHttp2GoawayFrame(
|
|
396
543
|
Http2GoawayFrame frame) {
|
|
397
544
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-goaway
|
|
398
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
545
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
546
|
+
<< "Http2ClientTransport ProcessHttp2GoawayFrame Promise { "
|
|
547
|
+
"last_stream_id="
|
|
548
|
+
<< frame.last_stream_id << ", error_code=" << frame.error_code
|
|
549
|
+
<< ", debug_data=" << frame.debug_data.as_string_view() << "}";
|
|
550
|
+
LOG_IF(ERROR,
|
|
551
|
+
frame.error_code != static_cast<uint32_t>(Http2ErrorCode::kNoError))
|
|
552
|
+
<< "Received GOAWAY frame with error code: " << frame.error_code
|
|
553
|
+
<< " and debug data: " << frame.debug_data.as_string_view();
|
|
554
|
+
|
|
555
|
+
uint32_t last_stream_id = 0;
|
|
556
|
+
absl::Status status(ErrorCodeToAbslStatusCode(
|
|
557
|
+
FrameErrorCodeToHttp2ErrorCode(frame.error_code)),
|
|
558
|
+
frame.debug_data.as_string_view());
|
|
559
|
+
if (frame.error_code == static_cast<uint32_t>(Http2ErrorCode::kNoError) &&
|
|
560
|
+
frame.last_stream_id == RFC9113::kMaxStreamId31Bit) {
|
|
561
|
+
const uint32_t next_stream_id = PeekNextStreamId();
|
|
562
|
+
last_stream_id = (next_stream_id > 1) ? next_stream_id - 2 : 0;
|
|
563
|
+
} else {
|
|
564
|
+
last_stream_id = frame.last_stream_id;
|
|
565
|
+
}
|
|
566
|
+
SetMaxAllowedStreamId(last_stream_id);
|
|
567
|
+
|
|
568
|
+
bool close_transport = false;
|
|
569
|
+
{
|
|
570
|
+
MutexLock lock(&transport_mutex_);
|
|
571
|
+
if (CanCloseTransportLocked()) {
|
|
572
|
+
close_transport = true;
|
|
573
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ProcessHttp2GoawayFrame "
|
|
574
|
+
"stream_list_ is empty";
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
StateWatcher::DisconnectInfo disconnect_info;
|
|
579
|
+
disconnect_info.reason = Transport::StateWatcher::kGoaway;
|
|
580
|
+
disconnect_info.http2_error_code =
|
|
581
|
+
static_cast<Http2ErrorCode>(frame.error_code);
|
|
582
|
+
|
|
583
|
+
// Throttle keepalive time if the server sends a GOAWAY with error code
|
|
584
|
+
// ENHANCE_YOUR_CALM and debug data equal to "too_many_pings". This will
|
|
585
|
+
// apply to any new transport created on by any subchannel of this channel.
|
|
586
|
+
if (GPR_UNLIKELY(frame.error_code == static_cast<uint32_t>(
|
|
587
|
+
Http2ErrorCode::kEnhanceYourCalm) &&
|
|
588
|
+
frame.debug_data == "too_many_pings")) {
|
|
589
|
+
LOG(ERROR) << ": Received a GOAWAY with error code ENHANCE_YOUR_CALM and "
|
|
590
|
+
"debug data equal to \"too_many_pings\". Current keepalive "
|
|
591
|
+
"time (before throttling): "
|
|
592
|
+
<< keepalive_time_.ToString();
|
|
593
|
+
constexpr int max_keepalive_time_millis =
|
|
594
|
+
INT_MAX / KEEPALIVE_TIME_BACKOFF_MULTIPLIER;
|
|
595
|
+
uint64_t throttled_keepalive_time =
|
|
596
|
+
keepalive_time_.millis() > max_keepalive_time_millis
|
|
597
|
+
? INT_MAX
|
|
598
|
+
: keepalive_time_.millis() * KEEPALIVE_TIME_BACKOFF_MULTIPLIER;
|
|
599
|
+
if (!IsTransportStateWatcherEnabled()) {
|
|
600
|
+
status.SetPayload(kKeepaliveThrottlingKey,
|
|
601
|
+
absl::Cord(std::to_string(throttled_keepalive_time)));
|
|
602
|
+
}
|
|
603
|
+
disconnect_info.keepalive_time =
|
|
604
|
+
Duration::Milliseconds(throttled_keepalive_time);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
if (close_transport) {
|
|
608
|
+
// TODO(akshitpatel) : [PH2][P3] : Ideally the error here should be
|
|
609
|
+
// kNoError. However, Http2Status does not support kNoError. We should
|
|
610
|
+
// revisit this and update the error code.
|
|
611
|
+
MaybeSpawnCloseTransport(Http2Status::Http2ConnectionError(
|
|
612
|
+
FrameErrorCodeToHttp2ErrorCode((
|
|
613
|
+
frame.error_code ==
|
|
614
|
+
Http2ErrorCodeToFrameErrorCode(Http2ErrorCode::kNoError)
|
|
615
|
+
? Http2ErrorCodeToFrameErrorCode(Http2ErrorCode::kInternalError)
|
|
616
|
+
: frame.error_code)),
|
|
617
|
+
std::string(frame.debug_data.as_string_view())));
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// lie: use transient failure from the transport to indicate goaway has been
|
|
621
|
+
// received.
|
|
622
|
+
ReportDisconnection(status, disconnect_info, "got_goaway");
|
|
406
623
|
return Http2Status::Ok();
|
|
407
624
|
}
|
|
408
625
|
|
|
@@ -410,12 +627,31 @@ Http2Status Http2ClientTransport::ProcessHttp2WindowUpdateFrame(
|
|
|
410
627
|
Http2WindowUpdateFrame frame) {
|
|
411
628
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-window_update
|
|
412
629
|
GRPC_HTTP2_CLIENT_DLOG
|
|
413
|
-
<< "
|
|
414
|
-
// TODO(tjagtap) : [PH2][P2] : Implement this.
|
|
415
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
416
|
-
<< "Http2Transport ProcessHttp2WindowUpdateFrame Promise { "
|
|
630
|
+
<< "Http2ClientTransport ProcessHttp2WindowUpdateFrame Promise { "
|
|
417
631
|
" stream_id="
|
|
418
632
|
<< frame.stream_id << ", increment=" << frame.increment << "}";
|
|
633
|
+
|
|
634
|
+
RefCountedPtr<Stream> stream = nullptr;
|
|
635
|
+
if (frame.stream_id != 0) {
|
|
636
|
+
stream = LookupStream(frame.stream_id);
|
|
637
|
+
}
|
|
638
|
+
if (stream != nullptr) {
|
|
639
|
+
StreamWritabilityUpdate update =
|
|
640
|
+
stream->ReceivedFlowControlWindowUpdate(frame.increment);
|
|
641
|
+
if (update.became_writable) {
|
|
642
|
+
absl::Status status = writable_stream_list_.EnqueueWrapper(
|
|
643
|
+
stream, update.priority, AreTransportFlowControlTokensAvailable());
|
|
644
|
+
if (!status.ok()) {
|
|
645
|
+
return ToHttpOkOrConnError(status);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const bool should_trigger_write =
|
|
651
|
+
ProcessIncomingWindowUpdateFrameFlowControl(frame, flow_control_, stream);
|
|
652
|
+
if (should_trigger_write) {
|
|
653
|
+
SpawnGuardedTransportParty("TransportTokensAvailable", TriggerWriteCycle());
|
|
654
|
+
}
|
|
419
655
|
return Http2Status::Ok();
|
|
420
656
|
}
|
|
421
657
|
|
|
@@ -423,11 +659,14 @@ Http2Status Http2ClientTransport::ProcessHttp2ContinuationFrame(
|
|
|
423
659
|
Http2ContinuationFrame frame) {
|
|
424
660
|
// https://www.rfc-editor.org/rfc/rfc9113.html#name-continuation
|
|
425
661
|
GRPC_HTTP2_CLIENT_DLOG
|
|
426
|
-
<< "
|
|
662
|
+
<< "Http2ClientTransport ProcessHttp2ContinuationFrame Promise { "
|
|
427
663
|
"stream_id="
|
|
428
664
|
<< frame.stream_id << ", end_headers=" << frame.end_headers
|
|
429
|
-
<< ", payload=" << frame.payload
|
|
430
|
-
|
|
665
|
+
<< ", payload=" << MaybeTruncatePayload(frame.payload) << " }";
|
|
666
|
+
|
|
667
|
+
// State update MUST happen before processing the frame.
|
|
668
|
+
incoming_headers_.OnContinuationReceived(frame);
|
|
669
|
+
|
|
431
670
|
RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
|
|
432
671
|
if (stream == nullptr) {
|
|
433
672
|
// TODO(tjagtap) : [PH2][P3] : Implement this.
|
|
@@ -437,34 +676,45 @@ Http2Status Http2ClientTransport::ProcessHttp2ContinuationFrame(
|
|
|
437
676
|
// frame and streams that are reserved using PUSH_PROMISE. An endpoint that
|
|
438
677
|
// receives an unexpected stream identifier MUST respond with a connection
|
|
439
678
|
// error (Section 5.4.1) of type PROTOCOL_ERROR.
|
|
440
|
-
return
|
|
679
|
+
return ParseAndDiscardHeaders(std::move(frame.payload), frame.end_headers,
|
|
680
|
+
nullptr, Http2Status::Ok());
|
|
441
681
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
std::
|
|
682
|
+
|
|
683
|
+
if (stream->IsStreamHalfClosedRemote()) {
|
|
684
|
+
return ParseAndDiscardHeaders(
|
|
685
|
+
std::move(frame.payload), frame.end_headers, stream,
|
|
686
|
+
Http2Status::Http2StreamError(
|
|
687
|
+
Http2ErrorCode::kStreamClosed,
|
|
688
|
+
std::string(RFC9113::kHalfClosedRemoteState)));
|
|
446
689
|
}
|
|
447
690
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
if (
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
691
|
+
Http2Status append_result =
|
|
692
|
+
stream->header_assembler.AppendContinuationFrame(frame);
|
|
693
|
+
if (!append_result.IsOk()) {
|
|
694
|
+
// Frame payload is not consumed if AppendContinuationFrame returns a
|
|
695
|
+
// non-OK status. We need to process it to keep our in consistent state.
|
|
696
|
+
return ParseAndDiscardHeaders(std::move(frame.payload), frame.end_headers,
|
|
697
|
+
stream, std::move(append_result));
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
Http2Status status = ProcessMetadata(stream);
|
|
701
|
+
if (!status.IsOk()) {
|
|
702
|
+
// Frame payload is consumed by HeaderAssembler. So passing an empty
|
|
703
|
+
// SliceBuffer to ParseAndDiscardHeaders.
|
|
704
|
+
return ParseAndDiscardHeaders(SliceBuffer(), frame.end_headers, stream,
|
|
705
|
+
std::move(status));
|
|
454
706
|
}
|
|
455
|
-
|
|
707
|
+
|
|
708
|
+
// Frame payload has either been processed or moved to the HeaderAssembler.
|
|
709
|
+
return Http2Status::Ok();
|
|
456
710
|
}
|
|
457
711
|
|
|
458
712
|
Http2Status Http2ClientTransport::ProcessHttp2SecurityFrame(
|
|
459
713
|
Http2SecurityFrame frame) {
|
|
460
|
-
GRPC_HTTP2_CLIENT_DLOG << "
|
|
461
|
-
"
|
|
462
|
-
<< frame.payload.
|
|
463
|
-
if (
|
|
464
|
-
settings_.local().allow_security_frame()) &&
|
|
465
|
-
settings_.peer().allow_security_frame()) {
|
|
466
|
-
// TODO(tjagtap) : [PH2][P4] : Evaluate when to accept the frame and when to
|
|
467
|
-
// reject it. Compare it with the requirement and with CHTTP2.
|
|
714
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ProcessHttp2SecurityFrame "
|
|
715
|
+
"{ payload.Length="
|
|
716
|
+
<< frame.payload.Length() << " }";
|
|
717
|
+
if (settings_->IsSecurityFrameExpected()) {
|
|
468
718
|
// TODO(tjagtap) : [PH2][P3] : Add handling of Security frame
|
|
469
719
|
// Just the frame.payload needs to be passed to the endpoint_ object.
|
|
470
720
|
// Refer usage of TransportFramingEndpointExtension.
|
|
@@ -508,7 +758,7 @@ auto Http2ClientTransport::ProcessOneFrame(Http2Frame frame) {
|
|
|
508
758
|
return self->ProcessHttp2SecurityFrame(std::move(frame));
|
|
509
759
|
},
|
|
510
760
|
[](GRPC_UNUSED Http2UnknownFrame frame) {
|
|
511
|
-
//
|
|
761
|
+
// RFC9113: Implementations MUST ignore and discard frames of
|
|
512
762
|
// unknown types.
|
|
513
763
|
return Http2Status::Ok();
|
|
514
764
|
},
|
|
@@ -519,8 +769,64 @@ auto Http2ClientTransport::ProcessOneFrame(Http2Frame frame) {
|
|
|
519
769
|
}));
|
|
520
770
|
}
|
|
521
771
|
|
|
772
|
+
Http2Status Http2ClientTransport::ParseAndDiscardHeaders(
|
|
773
|
+
SliceBuffer&& buffer, const bool is_end_headers,
|
|
774
|
+
const RefCountedPtr<Stream> stream, Http2Status&& original_status,
|
|
775
|
+
DebugLocation whence) {
|
|
776
|
+
const bool is_initial_metadata = !incoming_headers_.HeaderHasEndStream();
|
|
777
|
+
const uint32_t incoming_stream_id = incoming_headers_.GetStreamId();
|
|
778
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
779
|
+
<< "Http2ClientTransport ParseAndDiscardHeaders buffer "
|
|
780
|
+
"size: "
|
|
781
|
+
<< buffer.Length() << " is_initial_metadata: " << is_initial_metadata
|
|
782
|
+
<< " is_end_headers: " << is_end_headers
|
|
783
|
+
<< " incoming_stream_id: " << incoming_stream_id
|
|
784
|
+
<< " stream_id: " << (stream == nullptr ? 0 : stream->GetStreamId())
|
|
785
|
+
<< " original_status: " << original_status.DebugString()
|
|
786
|
+
<< " whence: " << whence.file() << ":" << whence.line();
|
|
787
|
+
|
|
788
|
+
return http2::ParseAndDiscardHeaders(
|
|
789
|
+
parser_, std::move(buffer),
|
|
790
|
+
HeaderAssembler::ParseHeaderArgs{
|
|
791
|
+
/*is_initial_metadata=*/is_initial_metadata,
|
|
792
|
+
/*is_end_headers=*/is_end_headers,
|
|
793
|
+
/*is_client=*/true,
|
|
794
|
+
/*max_header_list_size_soft_limit=*/
|
|
795
|
+
incoming_headers_.soft_limit(),
|
|
796
|
+
/*max_header_list_size_hard_limit=*/
|
|
797
|
+
settings_->acked().max_header_list_size(),
|
|
798
|
+
/*stream_id=*/incoming_stream_id,
|
|
799
|
+
},
|
|
800
|
+
stream, std::move(original_status));
|
|
801
|
+
}
|
|
802
|
+
|
|
522
803
|
///////////////////////////////////////////////////////////////////////////////
|
|
523
804
|
// Read Related Promises and Promise Factories
|
|
805
|
+
auto Http2ClientTransport::EndpointReadSlice(const size_t num_bytes) {
|
|
806
|
+
return Map(
|
|
807
|
+
endpoint_.ReadSlice(num_bytes),
|
|
808
|
+
[self = RefAsSubclass<Http2ClientTransport>(),
|
|
809
|
+
num_bytes](absl::StatusOr<Slice> status) {
|
|
810
|
+
if (status.ok()) {
|
|
811
|
+
self->keepalive_manager_->GotData();
|
|
812
|
+
self->ztrace_collector_->Append(PromiseEndpointReadTrace{num_bytes});
|
|
813
|
+
}
|
|
814
|
+
return status;
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
auto Http2ClientTransport::EndpointRead(const size_t num_bytes) {
|
|
819
|
+
return Map(
|
|
820
|
+
endpoint_.Read(num_bytes),
|
|
821
|
+
[self = RefAsSubclass<Http2ClientTransport>(),
|
|
822
|
+
num_bytes](absl::StatusOr<SliceBuffer> status) {
|
|
823
|
+
if (status.ok()) {
|
|
824
|
+
self->keepalive_manager_->GotData();
|
|
825
|
+
self->ztrace_collector_->Append(PromiseEndpointReadTrace{num_bytes});
|
|
826
|
+
}
|
|
827
|
+
return status;
|
|
828
|
+
});
|
|
829
|
+
}
|
|
524
830
|
|
|
525
831
|
auto Http2ClientTransport::ReadAndProcessOneFrame() {
|
|
526
832
|
GRPC_HTTP2_CLIENT_DLOG
|
|
@@ -539,13 +845,21 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
|
|
|
539
845
|
// Validate the incoming frame as per the current state of the transport
|
|
540
846
|
[self = RefAsSubclass<Http2ClientTransport>()](Http2FrameHeader header) {
|
|
541
847
|
Http2Status status = ValidateFrameHeader(
|
|
542
|
-
/*max_frame_size_setting*/ self->settings_
|
|
543
|
-
|
|
544
|
-
/*
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
848
|
+
/*max_frame_size_setting*/ self->settings_->acked()
|
|
849
|
+
.max_frame_size(),
|
|
850
|
+
/*incoming_header_in_progress*/
|
|
851
|
+
self->incoming_headers_.IsWaitingForContinuationFrame(),
|
|
852
|
+
/*incoming_header_stream_id*/
|
|
853
|
+
self->incoming_headers_.GetStreamId(),
|
|
854
|
+
/*current_frame_header*/ header,
|
|
855
|
+
/*last_stream_id=*/self->GetLastStreamId(),
|
|
856
|
+
/*is_client=*/true, /*is_first_settings_processed=*/
|
|
857
|
+
self->settings_->IsFirstPeerSettingsApplied());
|
|
858
|
+
|
|
859
|
+
if (GPR_UNLIKELY(!status.IsOk())) {
|
|
860
|
+
GRPC_DCHECK(status.GetType() ==
|
|
861
|
+
Http2Status::Http2ErrorType::kConnectionError);
|
|
862
|
+
return self->HandleError(std::nullopt, std::move(status));
|
|
549
863
|
}
|
|
550
864
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport ReadAndProcessOneFrame "
|
|
551
865
|
"Validated Frame Header:"
|
|
@@ -565,11 +879,12 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
|
|
|
565
879
|
SliceBuffer payload) -> absl::StatusOr<Http2Frame> {
|
|
566
880
|
GRPC_HTTP2_CLIENT_DLOG
|
|
567
881
|
<< "Http2ClientTransport ReadAndProcessOneFrame ParseFramePayload "
|
|
568
|
-
<< payload
|
|
882
|
+
<< MaybeTruncatePayload(payload);
|
|
569
883
|
ValueOrHttp2Status<Http2Frame> frame =
|
|
570
884
|
ParseFramePayload(self->current_frame_header_, std::move(payload));
|
|
571
885
|
if (!frame.IsOk()) {
|
|
572
886
|
return self->HandleError(
|
|
887
|
+
self->current_frame_header_.stream_id,
|
|
573
888
|
ValueOrHttp2Status<Http2Frame>::TakeStatus(std::move(frame)));
|
|
574
889
|
}
|
|
575
890
|
return TakeValue(std::move(frame));
|
|
@@ -578,14 +893,18 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
|
|
|
578
893
|
GRPC_UNUSED Http2Frame frame) {
|
|
579
894
|
GRPC_HTTP2_CLIENT_DLOG
|
|
580
895
|
<< "Http2ClientTransport ReadAndProcessOneFrame ProcessOneFrame";
|
|
581
|
-
return AssertResultType<absl::Status>(
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
896
|
+
return AssertResultType<absl::Status>(Map(
|
|
897
|
+
self->ProcessOneFrame(std::move(frame)),
|
|
898
|
+
[self](Http2Status status) {
|
|
899
|
+
if (!status.IsOk()) {
|
|
900
|
+
return self->HandleError(self->current_frame_header_.stream_id,
|
|
901
|
+
std::move(status));
|
|
902
|
+
}
|
|
903
|
+
return absl::OkStatus();
|
|
904
|
+
}));
|
|
905
|
+
},
|
|
906
|
+
[self = RefAsSubclass<Http2ClientTransport>()]() -> Poll<absl::Status> {
|
|
907
|
+
return self->reader_state_.MaybePauseReadLoop();
|
|
589
908
|
}));
|
|
590
909
|
}
|
|
591
910
|
|
|
@@ -602,355 +921,778 @@ auto Http2ClientTransport::ReadLoop() {
|
|
|
602
921
|
}));
|
|
603
922
|
}
|
|
604
923
|
|
|
605
|
-
auto Http2ClientTransport::OnReadLoopEnded() {
|
|
606
|
-
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport OnReadLoopEnded Factory";
|
|
607
|
-
return
|
|
608
|
-
[self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
|
|
609
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
610
|
-
<< "Http2ClientTransport OnReadLoopEnded Promise Status=" << status;
|
|
611
|
-
GRPC_UNUSED absl::Status error =
|
|
612
|
-
self->HandleError(Http2Status::AbslConnectionError(
|
|
613
|
-
status.code(), std::string(status.message())));
|
|
614
|
-
};
|
|
615
|
-
}
|
|
616
|
-
|
|
617
924
|
///////////////////////////////////////////////////////////////////////////////
|
|
618
|
-
//
|
|
619
|
-
|
|
620
|
-
auto Http2ClientTransport::WriteFromQueue() {
|
|
621
|
-
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteFromQueue Factory";
|
|
622
|
-
return TrySeq(
|
|
623
|
-
outgoing_frames_.NextBatch(128),
|
|
624
|
-
[self = RefAsSubclass<Http2ClientTransport>()](
|
|
625
|
-
std::vector<Http2Frame> frames) {
|
|
626
|
-
SliceBuffer output_buf;
|
|
627
|
-
if (self->is_first_write_) {
|
|
628
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
629
|
-
<< "Http2ClientTransport Write GRPC_CHTTP2_CLIENT_CONNECT_STRING";
|
|
630
|
-
output_buf.Append(Slice(grpc_slice_from_copied_string(
|
|
631
|
-
GRPC_CHTTP2_CLIENT_CONNECT_STRING)));
|
|
632
|
-
self->is_first_write_ = false;
|
|
633
|
-
}
|
|
634
|
-
Serialize(absl::Span<Http2Frame>(frames), output_buf);
|
|
635
|
-
uint64_t buffer_length = output_buf.Length();
|
|
636
|
-
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteFromQueue Promise";
|
|
637
|
-
return If(
|
|
638
|
-
buffer_length > 0,
|
|
639
|
-
[self, output_buffer = std::move(output_buf)]() mutable {
|
|
640
|
-
self->bytes_sent_in_last_write_ = true;
|
|
641
|
-
return self->endpoint_.Write(std::move(output_buffer),
|
|
642
|
-
PromiseEndpoint::WriteArgs{});
|
|
643
|
-
},
|
|
644
|
-
[] { return absl::OkStatus(); });
|
|
645
|
-
});
|
|
646
|
-
}
|
|
925
|
+
// Flow Control for the Transport
|
|
647
926
|
|
|
648
|
-
auto Http2ClientTransport::
|
|
649
|
-
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport
|
|
927
|
+
auto Http2ClientTransport::FlowControlPeriodicUpdateLoop() {
|
|
928
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport PeriodicUpdateLoop Factory";
|
|
650
929
|
return AssertResultType<absl::Status>(
|
|
651
930
|
Loop([self = RefAsSubclass<Http2ClientTransport>()]() {
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
self->bytes_sent_in_last_write_ = false;
|
|
931
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
932
|
+
<< "Http2ClientTransport FlowControlPeriodicUpdateLoop Loop";
|
|
655
933
|
return TrySeq(
|
|
656
|
-
// TODO(
|
|
657
|
-
//
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
// the frames and figures out the types of frames needed (this may
|
|
661
|
-
// anyways be needed to check that we do not send frames for closed
|
|
662
|
-
// streams) or we have flags to indicate the types of frame that are
|
|
663
|
-
// enqueued.
|
|
664
|
-
self->WriteFromQueue(), [self] { return self->MaybeSendPing(); },
|
|
665
|
-
[self] { return self->MaybeSendPingAcks(); },
|
|
666
|
-
[self]() -> LoopCtl<absl::Status> {
|
|
667
|
-
// If any Header/Data/WindowUpdate frame was sent in the last
|
|
668
|
-
// write, reset the ping clock.
|
|
669
|
-
if (self->bytes_sent_in_last_write_) {
|
|
670
|
-
self->ping_manager_.ResetPingClock(/*is_client=*/true);
|
|
671
|
-
}
|
|
934
|
+
// TODO(tjagtap) [PH2][P2][BDP] Remove this static sleep when the
|
|
935
|
+
// BDP code is done.
|
|
936
|
+
Sleep(chttp2::kFlowControlPeriodicUpdateTimer),
|
|
937
|
+
[self]() -> Poll<absl::Status> {
|
|
672
938
|
GRPC_HTTP2_CLIENT_DLOG
|
|
673
|
-
<< "Http2ClientTransport
|
|
674
|
-
|
|
675
|
-
|
|
939
|
+
<< "Http2ClientTransport FlowControl PeriodicUpdate()";
|
|
940
|
+
chttp2::FlowControlAction action =
|
|
941
|
+
self->flow_control_.PeriodicUpdate();
|
|
942
|
+
bool is_action_empty = action == chttp2::FlowControlAction();
|
|
943
|
+
// This may trigger a write cycle
|
|
944
|
+
self->ActOnFlowControlAction(action, nullptr);
|
|
945
|
+
if (is_action_empty) {
|
|
946
|
+
// TODO(tjagtap) [PH2][P2][BDP] Remove this when the BDP code is
|
|
947
|
+
// done. We must continue to do PeriodicUpdate once BDP is in
|
|
948
|
+
// place.
|
|
949
|
+
MutexLock lock(&self->transport_mutex_);
|
|
950
|
+
if (self->GetActiveStreamCountLocked() == 0) {
|
|
951
|
+
self->AddPeriodicUpdatePromiseWaker();
|
|
952
|
+
return Pending{};
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
return absl::OkStatus();
|
|
956
|
+
},
|
|
957
|
+
[self]() -> LoopCtl<absl::Status> { return Continue{}; });
|
|
676
958
|
}));
|
|
677
959
|
}
|
|
678
960
|
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
961
|
+
// Equivalent to grpc_chttp2_act_on_flowctl_action in chttp2_transport.cc
|
|
962
|
+
void Http2ClientTransport::ActOnFlowControlAction(
|
|
963
|
+
const chttp2::FlowControlAction& action, RefCountedPtr<Stream> stream) {
|
|
964
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::ActOnFlowControlAction"
|
|
965
|
+
<< action.DebugString();
|
|
966
|
+
if (action.send_stream_update() != kNoActionNeeded) {
|
|
967
|
+
if (GPR_LIKELY(stream != nullptr)) {
|
|
968
|
+
GRPC_DCHECK_GT(stream->GetStreamId(), 0u);
|
|
969
|
+
if (stream->CanSendWindowUpdateFrames()) {
|
|
970
|
+
window_update_list_.insert(stream->GetStreamId());
|
|
683
971
|
GRPC_HTTP2_CLIENT_DLOG
|
|
684
|
-
<< "Http2ClientTransport
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
972
|
+
<< "Http2ClientTransport::ActOnFlowControlAction "
|
|
973
|
+
"added stream "
|
|
974
|
+
<< stream->GetStreamId() << " to window_update_list_";
|
|
975
|
+
}
|
|
976
|
+
} else {
|
|
977
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
978
|
+
<< "Http2ClientTransport::ActOnFlowControlAction stream is null";
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
ActOnFlowControlActionSettings(
|
|
983
|
+
action, settings_->mutable_local(),
|
|
984
|
+
enable_preferred_rx_crypto_frame_advertisement_);
|
|
985
|
+
|
|
986
|
+
if (action.AnyUpdateImmediately()) {
|
|
987
|
+
// Prioritize sending flow control updates over reading data. If we
|
|
988
|
+
// continue reading while urgent flow control updates are pending, we might
|
|
989
|
+
// exhaust the flow control window. This prevents us from sending window
|
|
990
|
+
// updates to the peer, causing the peer to block unnecessarily while
|
|
991
|
+
// waiting for flow control tokens.
|
|
992
|
+
reader_state_.SetPauseReadLoop();
|
|
993
|
+
SpawnGuardedTransportParty("SendControlFrames", TriggerWriteCycle());
|
|
994
|
+
GRPC_HTTP2_CLIENT_DLOG << "Update Immediately : "
|
|
995
|
+
<< action.ImmediateUpdateReasons();
|
|
996
|
+
}
|
|
690
997
|
}
|
|
691
998
|
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
//
|
|
700
|
-
//
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
999
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1000
|
+
// Write Related Promises and Promise Factories
|
|
1001
|
+
|
|
1002
|
+
auto Http2ClientTransport::ProcessAndWriteControlFrames() {
|
|
1003
|
+
SliceBuffer output_buf;
|
|
1004
|
+
if (is_first_write_) {
|
|
1005
|
+
// RFC9113: That is, the connection preface starts with the string
|
|
1006
|
+
// "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
|
|
1007
|
+
// This sequence MUST be followed by a SETTINGS frame, which MAY be empty.
|
|
1008
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteControlFrames "
|
|
1009
|
+
"GRPC_CHTTP2_CLIENT_CONNECT_STRING";
|
|
1010
|
+
output_buf.Append(
|
|
1011
|
+
Slice::FromCopiedString(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
|
|
1012
|
+
settings_->MaybeGetSettingsAndSettingsAckFrames(flow_control_, output_buf);
|
|
1013
|
+
// TODO(tjagtap) [PH2][P2][Server] : This will be opposite for server. We
|
|
1014
|
+
// must read before we write for the server. So the ReadLoop will be Spawned
|
|
1015
|
+
// just after the constructor, and the write loop should be spawned only
|
|
1016
|
+
// after the first SETTINGS frame is completely received.
|
|
1017
|
+
//
|
|
1018
|
+
// Because the client is expected to write before it reads, we spawn the
|
|
1019
|
+
// ReadLoop of the client only after the first write is queued.
|
|
1020
|
+
SpawnGuardedTransportParty("ReadLoop", UntilTransportClosed(ReadLoop()));
|
|
1021
|
+
is_first_write_ = false;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
// Order of Control Frames is important.
|
|
1025
|
+
// 1. GOAWAY - This is first because if this is the final GoAway, then we may
|
|
1026
|
+
// not need to send anything else to the peer.
|
|
1027
|
+
// 2. SETTINGS and SETTINGS ACK
|
|
1028
|
+
// 3. PING and PING acks.
|
|
1029
|
+
// 4. WINDOW_UPDATE
|
|
1030
|
+
// 5. Custom gRPC security frame
|
|
1031
|
+
|
|
1032
|
+
goaway_manager_.MaybeGetSerializedGoawayFrame(output_buf);
|
|
1033
|
+
http2::Http2ErrorCode apply_status =
|
|
1034
|
+
settings_->MaybeReportAndApplyBufferedPeerSettings(event_engine_.get());
|
|
1035
|
+
if (!goaway_manager_.IsImmediateGoAway() &&
|
|
1036
|
+
apply_status == http2::Http2ErrorCode::kNoError) {
|
|
1037
|
+
EnforceLatestIncomingSettings();
|
|
1038
|
+
settings_->MaybeGetSettingsAndSettingsAckFrames(flow_control_, output_buf);
|
|
1039
|
+
ping_manager_->MaybeGetSerializedPingFrames(output_buf,
|
|
1040
|
+
NextAllowedPingInterval());
|
|
1041
|
+
MaybeGetWindowUpdateFrames(output_buf);
|
|
1042
|
+
}
|
|
1043
|
+
const uint64_t buffer_length = output_buf.Length();
|
|
1044
|
+
ztrace_collector_->Append(PromiseEndpointWriteTrace{buffer_length});
|
|
1045
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport WriteControlFrames Size : "
|
|
1046
|
+
<< buffer_length;
|
|
1047
|
+
return AssertResultType<absl::Status>(
|
|
1048
|
+
If((buffer_length > 0 && apply_status == http2::Http2ErrorCode::kNoError),
|
|
1049
|
+
[self = RefAsSubclass<Http2ClientTransport>(),
|
|
1050
|
+
output_buf = std::move(output_buf)]() mutable {
|
|
1051
|
+
return self->endpoint_.Write(std::move(output_buf),
|
|
1052
|
+
GetWriteArgs(self->settings_->peer()));
|
|
1053
|
+
},
|
|
1054
|
+
[self = RefAsSubclass<Http2ClientTransport>(), apply_status]() {
|
|
1055
|
+
if (apply_status != http2::Http2ErrorCode::kNoError) {
|
|
1056
|
+
return self->HandleError(
|
|
1057
|
+
std::nullopt,
|
|
1058
|
+
Http2Status::Http2ConnectionError(
|
|
1059
|
+
apply_status, "Failed to apply incoming settings"));
|
|
1060
|
+
}
|
|
1061
|
+
return absl::OkStatus();
|
|
1062
|
+
}));
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
void Http2ClientTransport::NotifyControlFramesWriteDone() {
|
|
1066
|
+
// Notify Control modules that we have sent the frames.
|
|
1067
|
+
// All notifications are expected to be synchronous.
|
|
1068
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport NotifyControlFramesWriteDone";
|
|
1069
|
+
reader_state_.ResumeReadLoopIfPaused();
|
|
1070
|
+
ping_manager_->NotifyPingSent();
|
|
1071
|
+
goaway_manager_.NotifyGoawaySent();
|
|
1072
|
+
MaybeSpawnWaitForSettingsTimeout();
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
auto Http2ClientTransport::SerializeAndWrite(std::vector<Http2Frame>&& frames) {
|
|
1076
|
+
SliceBuffer output_buf;
|
|
1077
|
+
should_reset_ping_clock_ =
|
|
1078
|
+
Serialize(absl::Span<Http2Frame>(frames), output_buf)
|
|
1079
|
+
.should_reset_ping_clock;
|
|
1080
|
+
size_t output_buf_length = output_buf.Length();
|
|
1081
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport SerializeAndWrite Write "
|
|
1082
|
+
"output_buf.length() = "
|
|
1083
|
+
<< output_buf_length;
|
|
1084
|
+
return AssertResultType<absl::Status>(If(
|
|
1085
|
+
output_buf_length > 0,
|
|
1086
|
+
[self = RefAsSubclass<Http2ClientTransport>(),
|
|
1087
|
+
output_buf = std::move(output_buf)]() mutable {
|
|
1088
|
+
return self->endpoint_.Write(std::move(output_buf),
|
|
1089
|
+
GetWriteArgs(self->settings_->peer()));
|
|
1090
|
+
},
|
|
1091
|
+
[]() { return absl::OkStatus(); }));
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
absl::StatusOr<std::vector<Http2Frame>>
|
|
1095
|
+
Http2ClientTransport::DequeueStreamFrames(RefCountedPtr<Stream> stream) {
|
|
1096
|
+
// write_bytes_remaining_ is passed as an upper bound on the max
|
|
1097
|
+
// number of tokens that can be dequeued to prevent dequeuing huge
|
|
1098
|
+
// data frames when write_bytes_remaining_ is very low. As the
|
|
1099
|
+
// available transport tokens can only range from 0 to 2^31 - 1,
|
|
1100
|
+
// we are clamping the write_bytes_remaining_ to that range.
|
|
1101
|
+
const uint32_t tokens =
|
|
1102
|
+
GetMaxPermittedDequeue(flow_control_, stream->flow_control,
|
|
1103
|
+
write_bytes_remaining_, settings_->peer());
|
|
1104
|
+
const uint32_t stream_flow_control_tokens = static_cast<uint32_t>(
|
|
1105
|
+
GetStreamFlowControlTokens(stream->flow_control, settings_->peer()));
|
|
1106
|
+
stream->flow_control.ReportIfStalled(
|
|
1107
|
+
/*is_client=*/true, stream->GetStreamId(), settings_->peer());
|
|
1108
|
+
StreamDataQueue<ClientMetadataHandle>::DequeueResult result =
|
|
1109
|
+
stream->DequeueFrames(tokens, stream_flow_control_tokens,
|
|
1110
|
+
settings_->peer().max_frame_size(), encoder_);
|
|
1111
|
+
ProcessOutgoingDataFrameFlowControl(stream->flow_control,
|
|
1112
|
+
result.flow_control_tokens_consumed);
|
|
1113
|
+
if (result.is_writable) {
|
|
1114
|
+
// Stream is still writable. Enqueue it back to the writable
|
|
1115
|
+
// stream list.
|
|
1116
|
+
absl::Status status = writable_stream_list_.EnqueueWrapper(
|
|
1117
|
+
stream, result.priority, AreTransportFlowControlTokensAvailable());
|
|
1118
|
+
|
|
1119
|
+
if (GPR_UNLIKELY(!status.ok())) {
|
|
1120
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1121
|
+
<< "Http2ClientTransport DequeueStreamFrames Failed to "
|
|
1122
|
+
"enqueue stream "
|
|
1123
|
+
<< stream->GetStreamId() << " with status: " << status;
|
|
1124
|
+
// Close transport if we fail to enqueue stream.
|
|
1125
|
+
return HandleError(std::nullopt, ToHttpOkOrConnError(status));
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// If the stream is aborted before initial metadata is dequeued, we will
|
|
1130
|
+
// not dequeue any frames from the stream data queue (including RST_STREAM).
|
|
1131
|
+
// Because of this, we will add the stream to the stream_list only when
|
|
1132
|
+
// we are guaranteed to send initial metadata on the wire. If the above
|
|
1133
|
+
// mentioned scenario occurs, the stream ref will be dropped by the
|
|
1134
|
+
// multiplexer loop as the stream will never be writable again. Additionally,
|
|
1135
|
+
// the other two stream refs, CallHandler OnDone and OutboundLoop will be
|
|
1136
|
+
// dropped by Callv3 triggering cleaning up the stream object.
|
|
1137
|
+
if (result.InitialMetadataDequeued()) {
|
|
1138
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1139
|
+
<< "Http2ClientTransport DequeueStreamFrames InitialMetadataDequeued "
|
|
1140
|
+
"stream_id = "
|
|
1141
|
+
<< stream->GetStreamId();
|
|
1142
|
+
stream->SentInitialMetadata();
|
|
1143
|
+
// After this point, initial metadata is guaranteed to be sent out.
|
|
1144
|
+
AddToStreamList(stream);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (result.HalfCloseDequeued()) {
|
|
1148
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1149
|
+
<< "Http2ClientTransport DequeueStreamFrames HalfCloseDequeued "
|
|
1150
|
+
"stream_id = "
|
|
1151
|
+
<< stream->GetStreamId();
|
|
1152
|
+
stream->MarkHalfClosedLocal();
|
|
1153
|
+
CloseStream(
|
|
1154
|
+
stream,
|
|
1155
|
+
CloseStreamArgs{/*close_reads=*/stream->did_receive_trailing_metadata,
|
|
1156
|
+
/*close_writes=*/true});
|
|
1157
|
+
}
|
|
1158
|
+
if (result.ResetStreamDequeued()) {
|
|
1159
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1160
|
+
<< "Http2ClientTransport DequeueStreamFrames ResetStreamDequeued "
|
|
1161
|
+
"stream_id = "
|
|
1162
|
+
<< stream->GetStreamId();
|
|
1163
|
+
stream->MarkHalfClosedLocal();
|
|
1164
|
+
CloseStream(stream, CloseStreamArgs{/*close_reads=*/true,
|
|
1165
|
+
/*close_writes=*/true});
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
// Update the write_bytes_remaining_ based on the bytes consumed
|
|
1169
|
+
// in the current dequeue.
|
|
1170
|
+
write_bytes_remaining_ =
|
|
1171
|
+
(write_bytes_remaining_ >= result.total_bytes_consumed)
|
|
1172
|
+
? (write_bytes_remaining_ - result.total_bytes_consumed)
|
|
1173
|
+
: 0;
|
|
1174
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport DequeueStreamFrames "
|
|
1175
|
+
"write_bytes_remaining_ after dequeue = "
|
|
1176
|
+
<< write_bytes_remaining_ << " total_bytes_consumed = "
|
|
1177
|
+
<< result.total_bytes_consumed
|
|
1178
|
+
<< " stream_id = " << stream->GetStreamId()
|
|
1179
|
+
<< " is_writable = " << result.is_writable
|
|
1180
|
+
<< " stream_priority = "
|
|
1181
|
+
<< static_cast<uint8_t>(result.priority)
|
|
1182
|
+
<< " number of frames = " << result.frames.size();
|
|
1183
|
+
return std::move(result.frames);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
// This MultiplexerLoop promise is responsible for Multiplexing multiple gRPC
|
|
1187
|
+
// Requests (HTTP2 Streams) and writing them into one common endpoint.
|
|
1188
|
+
auto Http2ClientTransport::MultiplexerLoop() {
|
|
1189
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport MultiplexerLoop Factory";
|
|
1190
|
+
return AssertResultType<
|
|
1191
|
+
absl::Status>(Loop([self = RefAsSubclass<Http2ClientTransport>()]() {
|
|
1192
|
+
self->write_bytes_remaining_ = self->GetMaxWriteSize();
|
|
1193
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport MultiplexerLoop "
|
|
1194
|
+
<< " max_write_size_=" << self->GetMaxWriteSize();
|
|
706
1195
|
return TrySeq(
|
|
707
|
-
self->writable_stream_list_.
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
1196
|
+
self->writable_stream_list_.WaitForReady(
|
|
1197
|
+
self->AreTransportFlowControlTokensAvailable()),
|
|
1198
|
+
[self]() {
|
|
1199
|
+
// TODO(akshitpatel) : [PH2][P2] : Return an `important` tag from
|
|
1200
|
+
// WriteControlFrames() to indicate if we should do a separate write
|
|
1201
|
+
// for the queued control frames or send the queued frames with the
|
|
1202
|
+
// data frames(if any).
|
|
1203
|
+
return Map(
|
|
1204
|
+
self->ProcessAndWriteControlFrames(),
|
|
1205
|
+
[self](absl::Status status) {
|
|
1206
|
+
if (GPR_UNLIKELY(!status.ok())) {
|
|
1207
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1208
|
+
<< "Http2ClientTransport MultiplexerLoop Failed to "
|
|
1209
|
+
"write control frames with status: "
|
|
1210
|
+
<< status;
|
|
1211
|
+
return status;
|
|
1212
|
+
}
|
|
1213
|
+
self->NotifyControlFramesWriteDone();
|
|
1214
|
+
return absl::OkStatus();
|
|
1215
|
+
});
|
|
1216
|
+
},
|
|
1217
|
+
[self]() -> absl::StatusOr<std::vector<Http2Frame>> {
|
|
1218
|
+
std::vector<Http2Frame> frames;
|
|
1219
|
+
// Drain all the writable streams till we have written
|
|
1220
|
+
// max_write_size_ bytes of data or there is no more data to send. In
|
|
1221
|
+
// some cases, we may write more than max_write_size_ bytes(like
|
|
1222
|
+
// writing metadata).
|
|
1223
|
+
while (self->write_bytes_remaining_ > 0) {
|
|
1224
|
+
std::optional<RefCountedPtr<Stream>> optional_stream =
|
|
1225
|
+
self->writable_stream_list_.ImmediateNext(
|
|
1226
|
+
self->AreTransportFlowControlTokensAvailable());
|
|
1227
|
+
if (!optional_stream.has_value()) {
|
|
1228
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1229
|
+
<< "Http2ClientTransport MultiplexerLoop "
|
|
1230
|
+
"No writable streams available, write_bytes_remaining_ = "
|
|
1231
|
+
<< self->write_bytes_remaining_;
|
|
1232
|
+
break;
|
|
1233
|
+
}
|
|
1234
|
+
RefCountedPtr<Stream> stream = std::move(optional_stream.value());
|
|
1235
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1236
|
+
<< "Http2ClientTransport MultiplexerLoop "
|
|
1237
|
+
"Next writable stream id = "
|
|
1238
|
+
<< stream->GetStreamId()
|
|
1239
|
+
<< " is_closed_for_writes = " << stream->IsClosedForWrites();
|
|
1240
|
+
|
|
1241
|
+
if (stream->GetStreamId() == kInvalidStreamId) {
|
|
1242
|
+
GRPC_DCHECK(stream->IsStreamIdle());
|
|
1243
|
+
// TODO(akshitpatel) : [PH2][P5] : We will waste a stream id in
|
|
1244
|
+
// the rare scenario where the stream is aborted before it can be
|
|
1245
|
+
// written to. This is a possible area to optimize in future.
|
|
1246
|
+
absl::Status status = self->InitializeStream(stream);
|
|
1247
|
+
if (!status.ok()) {
|
|
1248
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1249
|
+
<< "Http2ClientTransport MultiplexerLoop "
|
|
1250
|
+
"Failed to assign stream id and add to stream list for "
|
|
1251
|
+
"stream: "
|
|
1252
|
+
<< stream.get() << " closing this stream.";
|
|
1253
|
+
self->BeginCloseStream(
|
|
1254
|
+
stream, /*reset_stream_error_code=*/std::nullopt,
|
|
1255
|
+
CancelledServerMetadataFromStatus(status));
|
|
1256
|
+
continue;
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
if (GPR_LIKELY(!stream->IsClosedForWrites())) {
|
|
1261
|
+
absl::StatusOr<std::vector<Http2Frame>> stream_frames =
|
|
1262
|
+
self->DequeueStreamFrames(stream);
|
|
1263
|
+
if (GPR_UNLIKELY(!stream_frames.ok())) {
|
|
1264
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1265
|
+
<< "Http2ClientTransport MultiplexerLoop "
|
|
1266
|
+
"Failed to dequeue stream frames with status: "
|
|
1267
|
+
<< stream_frames.status();
|
|
1268
|
+
return stream_frames.status();
|
|
1269
|
+
}
|
|
718
1270
|
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
self->settings_.peer().max_frame_size(), self->encoder_);
|
|
725
|
-
if (result.ok() && result->is_writable) {
|
|
726
|
-
// Stream is still writable. Enqueue it back to the writable stream
|
|
727
|
-
// list.
|
|
728
|
-
// TODO(akshitpatel) : [PH2][P3] : Plug transport_tokens when
|
|
729
|
-
// transport flow control is implemented.
|
|
730
|
-
absl::Status status = self->writable_stream_list_.Enqueue(
|
|
731
|
-
stream_id, WritableStreams::StreamPriority::kDefault);
|
|
732
|
-
|
|
733
|
-
if (GPR_UNLIKELY(!status.ok())) {
|
|
734
|
-
LOG(ERROR) << "Failed to enqueue stream " << stream_id
|
|
735
|
-
<< " with status: " << status;
|
|
736
|
-
// Close transport if we fail to enqueue stream.
|
|
737
|
-
return absl::InternalError("Failed to enqueue stream");
|
|
1271
|
+
frames.reserve(frames.size() + stream_frames.value().size());
|
|
1272
|
+
frames.insert(
|
|
1273
|
+
frames.end(),
|
|
1274
|
+
std::make_move_iterator(stream_frames.value().begin()),
|
|
1275
|
+
std::make_move_iterator(stream_frames.value().end()));
|
|
738
1276
|
}
|
|
739
|
-
} else if (GPR_UNLIKELY(!result.ok())) {
|
|
740
|
-
// Close the corresponding stream if we fail to dequeue frames from
|
|
741
|
-
// the stream queue.
|
|
742
|
-
LOG(ERROR) << "Failed to dequeue frames for stream " << stream_id
|
|
743
|
-
<< " with status: " << result.status();
|
|
744
|
-
absl::Status status =
|
|
745
|
-
self->HandleError(Http2Status::AbslStreamError(
|
|
746
|
-
absl::StatusCode::kInternal, "Failed to dequeue frames"));
|
|
747
|
-
return std::vector<Http2Frame>();
|
|
748
1277
|
}
|
|
1278
|
+
|
|
749
1279
|
GRPC_HTTP2_CLIENT_DLOG
|
|
750
|
-
<< "Http2ClientTransport
|
|
751
|
-
|
|
752
|
-
<<
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
return std::move(result->frames);
|
|
1280
|
+
<< "Http2ClientTransport MultiplexerLoop "
|
|
1281
|
+
"write_bytes_remaining_ after draining all writable streams = "
|
|
1282
|
+
<< self->write_bytes_remaining_;
|
|
1283
|
+
|
|
1284
|
+
return std::move(frames);
|
|
756
1285
|
},
|
|
757
1286
|
[self](std::vector<Http2Frame> frames) {
|
|
758
|
-
|
|
759
|
-
return Loop([self, frames = std::move(frames), idx = 0u]() mutable {
|
|
760
|
-
return If(
|
|
761
|
-
idx < frames.size(),
|
|
762
|
-
[self, &frames, &idx]() {
|
|
763
|
-
return Map(
|
|
764
|
-
// Enqueue to the MPSC queue could return pending. This
|
|
765
|
-
// induces backpressure for the sender. Only after writing
|
|
766
|
-
// to the MPSC queue we will loop back to read more
|
|
767
|
-
// streams.
|
|
768
|
-
self->EnqueueOutgoingFrame(std::move(frames[idx++])),
|
|
769
|
-
[](absl::Status status) -> LoopCtl<absl::Status> {
|
|
770
|
-
if (GPR_UNLIKELY(!status.ok())) {
|
|
771
|
-
return status;
|
|
772
|
-
}
|
|
773
|
-
return Continue{};
|
|
774
|
-
});
|
|
775
|
-
},
|
|
776
|
-
[]() -> LoopCtl<absl::Status> { return absl::OkStatus(); });
|
|
777
|
-
});
|
|
1287
|
+
return self->SerializeAndWrite(std::move(frames));
|
|
778
1288
|
},
|
|
779
|
-
[]() -> LoopCtl<absl::Status> {
|
|
780
|
-
|
|
1289
|
+
[self]() -> LoopCtl<absl::Status> {
|
|
1290
|
+
if (self->should_reset_ping_clock_) {
|
|
1291
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1292
|
+
<< "Http2ClientTransport MultiplexerLoop ResetPingClock";
|
|
1293
|
+
self->ping_manager_->ResetPingClock(/*is_client=*/true);
|
|
1294
|
+
self->should_reset_ping_clock_ = false;
|
|
1295
|
+
}
|
|
1296
|
+
return Continue();
|
|
1297
|
+
});
|
|
1298
|
+
}));
|
|
781
1299
|
}
|
|
782
1300
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1301
|
+
absl::Status Http2ClientTransport::InitializeStream(
|
|
1302
|
+
RefCountedPtr<Stream> stream) {
|
|
1303
|
+
absl::StatusOr<uint32_t> next_stream_id = NextStreamId();
|
|
1304
|
+
if (!next_stream_id.ok()) {
|
|
1305
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport InitializeStream "
|
|
1306
|
+
"Failed to get next stream id for stream: "
|
|
1307
|
+
<< stream.get();
|
|
1308
|
+
return std::move(next_stream_id).status();
|
|
1309
|
+
}
|
|
1310
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport InitializeStream "
|
|
1311
|
+
"Assigned stream id: "
|
|
1312
|
+
<< next_stream_id.value()
|
|
1313
|
+
<< " to stream: " << stream.get()
|
|
1314
|
+
<< ", allow_true_binary_metadata:"
|
|
1315
|
+
<< settings_->peer().allow_true_binary_metadata();
|
|
1316
|
+
stream->InitializeStream(next_stream_id.value(),
|
|
1317
|
+
settings_->peer().allow_true_binary_metadata(),
|
|
1318
|
+
settings_->acked().allow_true_binary_metadata());
|
|
1319
|
+
return absl::OkStatus();
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
void Http2ClientTransport::AddToStreamList(RefCountedPtr<Stream> stream) {
|
|
1323
|
+
bool should_wake_periodic_updates = false;
|
|
1324
|
+
{
|
|
1325
|
+
MutexLock lock(&transport_mutex_);
|
|
1326
|
+
GRPC_DCHECK(stream != nullptr) << "stream is null";
|
|
1327
|
+
GRPC_DCHECK_GT(stream->GetStreamId(), 0u) << "stream id is invalid";
|
|
787
1328
|
GRPC_HTTP2_CLIENT_DLOG
|
|
788
|
-
<< "Http2ClientTransport
|
|
789
|
-
<<
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1329
|
+
<< "Http2ClientTransport AddToStreamList for stream id: "
|
|
1330
|
+
<< stream->GetStreamId();
|
|
1331
|
+
stream_list_.emplace(stream->GetStreamId(), stream);
|
|
1332
|
+
// TODO(tjagtap) [PH2][P2][BDP] Remove this when the BDP code is done.
|
|
1333
|
+
if (GetActiveStreamCountLocked() == 1) {
|
|
1334
|
+
should_wake_periodic_updates = true;
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
// TODO(tjagtap) [PH2][P2][BDP] Remove this when the BDP code is done.
|
|
1338
|
+
if (should_wake_periodic_updates) {
|
|
1339
|
+
// Release the lock before you wake up another promise on the party.
|
|
1340
|
+
WakeupPeriodicUpdatePromise();
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
1345
|
+
// Settings and Window Update Management
|
|
1346
|
+
|
|
1347
|
+
void Http2ClientTransport::EnforceLatestIncomingSettings() {
|
|
1348
|
+
encoder_.SetMaxTableSize(settings_->peer().header_table_size());
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
auto Http2ClientTransport::WaitForSettingsTimeoutOnDone() {
|
|
1352
|
+
return [self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
|
|
1353
|
+
if (!status.ok()) {
|
|
1354
|
+
GRPC_UNUSED absl::Status result = self->HandleError(
|
|
1355
|
+
std::nullopt, Http2Status::Http2ConnectionError(
|
|
1356
|
+
Http2ErrorCode::kProtocolError,
|
|
1357
|
+
std::string(RFC9113::kSettingsTimeout)));
|
|
1358
|
+
}
|
|
793
1359
|
};
|
|
794
1360
|
}
|
|
795
1361
|
|
|
1362
|
+
void Http2ClientTransport::MaybeSpawnWaitForSettingsTimeout() {
|
|
1363
|
+
if (settings_->ShouldSpawnWaitForSettingsTimeout()) {
|
|
1364
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1365
|
+
<< "Http2ClientTransport::MaybeSpawnWaitForSettingsTimeout Spawning";
|
|
1366
|
+
general_party_->Spawn("WaitForSettingsTimeout",
|
|
1367
|
+
settings_->WaitForSettingsTimeout(),
|
|
1368
|
+
WaitForSettingsTimeoutOnDone());
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1372
|
+
void Http2ClientTransport::MaybeGetWindowUpdateFrames(SliceBuffer& output_buf) {
|
|
1373
|
+
std::vector<Http2Frame> frames;
|
|
1374
|
+
frames.reserve(window_update_list_.size() + 1);
|
|
1375
|
+
uint32_t window_size =
|
|
1376
|
+
flow_control_.DesiredAnnounceSize(/*writing_anyway=*/true);
|
|
1377
|
+
if (window_size > 0) {
|
|
1378
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1379
|
+
<< "Http2ClientTransport::MaybeGetWindowUpdateFrames Transport Window "
|
|
1380
|
+
"Update : "
|
|
1381
|
+
<< window_size;
|
|
1382
|
+
frames.emplace_back(Http2WindowUpdateFrame{/*stream_id=*/0, window_size});
|
|
1383
|
+
flow_control_.SentUpdate(window_size);
|
|
1384
|
+
}
|
|
1385
|
+
for (const uint32_t stream_id : window_update_list_) {
|
|
1386
|
+
RefCountedPtr<Stream> stream = LookupStream(stream_id);
|
|
1387
|
+
MaybeAddStreamWindowUpdateFrame(stream, frames);
|
|
1388
|
+
}
|
|
1389
|
+
window_update_list_.clear();
|
|
1390
|
+
if (!frames.empty()) {
|
|
1391
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1392
|
+
<< "Http2ClientTransport::MaybeGetWindowUpdateFrames Total Window "
|
|
1393
|
+
"Update Frames : "
|
|
1394
|
+
<< frames.size();
|
|
1395
|
+
Serialize(absl::Span<Http2Frame>(frames), output_buf);
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
|
|
796
1399
|
///////////////////////////////////////////////////////////////////////////////
|
|
797
1400
|
// Constructor Destructor
|
|
798
1401
|
|
|
799
1402
|
Http2ClientTransport::Http2ClientTransport(
|
|
800
1403
|
PromiseEndpoint endpoint, GRPC_UNUSED const ChannelArgs& channel_args,
|
|
801
1404
|
std::shared_ptr<EventEngine> event_engine,
|
|
802
|
-
|
|
803
|
-
:
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
1405
|
+
absl::AnyInvocable<void(absl::StatusOr<uint32_t>)> on_receive_settings)
|
|
1406
|
+
: channelz::DataSource(http2::CreateChannelzSocketNode(
|
|
1407
|
+
endpoint.GetEventEngineEndpoint(), channel_args)),
|
|
1408
|
+
event_engine_(std::move(event_engine)),
|
|
1409
|
+
endpoint_(std::move(endpoint)),
|
|
1410
|
+
settings_(MakeRefCounted<SettingsPromiseManager>(
|
|
1411
|
+
std::move(on_receive_settings))),
|
|
1412
|
+
next_stream_id_(/*Initial Stream ID*/ 1),
|
|
1413
|
+
should_reset_ping_clock_(false),
|
|
809
1414
|
is_first_write_(true),
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
keepalive_timeout_(std::max(
|
|
823
|
-
Duration::Zero(),
|
|
824
|
-
channel_args.GetDurationFromIntMillis(GRPC_ARG_KEEPALIVE_TIMEOUT_MS)
|
|
825
|
-
.value_or(keepalive_time_ == Duration::Infinity()
|
|
826
|
-
? Duration::Infinity()
|
|
827
|
-
: (Duration::Seconds(20))))),
|
|
828
|
-
ping_timeout_(std::max(
|
|
829
|
-
Duration::Zero(),
|
|
830
|
-
channel_args.GetDurationFromIntMillis(GRPC_ARG_PING_TIMEOUT_MS)
|
|
831
|
-
.value_or(keepalive_time_ == Duration::Infinity()
|
|
832
|
-
? Duration::Infinity()
|
|
833
|
-
: Duration::Minutes(1)))),
|
|
834
|
-
ping_manager_(channel_args, PingSystemInterfaceImpl::Make(this),
|
|
835
|
-
event_engine),
|
|
836
|
-
keepalive_manager_(
|
|
837
|
-
KeepAliveInterfaceImpl::Make(this),
|
|
838
|
-
((keepalive_timeout_ < ping_timeout_) ? keepalive_timeout_
|
|
839
|
-
: Duration::Infinity()),
|
|
840
|
-
keepalive_time_),
|
|
841
|
-
keepalive_permit_without_calls_(false) {
|
|
1415
|
+
max_write_size_(kMaxWriteSize),
|
|
1416
|
+
ping_manager_(std::nullopt),
|
|
1417
|
+
keepalive_manager_(std::nullopt),
|
|
1418
|
+
goaway_manager_(GoawayInterfaceImpl::Make(this)),
|
|
1419
|
+
memory_owner_(channel_args.GetObject<ResourceQuota>()
|
|
1420
|
+
->memory_quota()
|
|
1421
|
+
->CreateMemoryOwner()),
|
|
1422
|
+
flow_control_(
|
|
1423
|
+
"PH2_Client",
|
|
1424
|
+
channel_args.GetBool(GRPC_ARG_HTTP2_BDP_PROBE).value_or(true),
|
|
1425
|
+
&memory_owner_),
|
|
1426
|
+
ztrace_collector_(std::make_shared<PromiseHttp2ZTraceCollector>()) {
|
|
842
1427
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Constructor Begin";
|
|
843
|
-
|
|
844
|
-
InitLocalSettings(settings_.mutable_local(), /*is_client=*/true);
|
|
845
|
-
ReadSettingsFromChannelArgs(channel_args, settings_.mutable_local(),
|
|
846
|
-
/*is_client=*/true);
|
|
847
|
-
|
|
848
1428
|
// Initialize the general party and write party.
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
general_party_ = Party::Make(std::move(
|
|
1429
|
+
RefCountedPtr<Arena> party_arena = SimpleArenaAllocator(0)->MakeArena();
|
|
1430
|
+
party_arena->SetContext<EventEngine>(event_engine_.get());
|
|
1431
|
+
general_party_ = Party::Make(std::move(party_arena));
|
|
852
1432
|
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
general_party_->Spawn("StreamMultiplexerLoop", StreamMultiplexerLoop(),
|
|
857
|
-
OnStreamMultiplexerLoopEnded());
|
|
1433
|
+
InitLocalSettings(settings_->mutable_local(), /*is_client=*/true);
|
|
1434
|
+
TransportChannelArgs args;
|
|
1435
|
+
ReadChannelArgs(channel_args, args);
|
|
858
1436
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
// TODO(tjagtap) : [PH2][P2] Delete this hack once flow control is done.
|
|
863
|
-
// We are increasing the flow control window so that we can avoid sending
|
|
864
|
-
// WINDOW_UPDATE frames while flow control is under development. Once it is
|
|
865
|
-
// ready we should remove these lines.
|
|
866
|
-
// <DeleteAfterFlowControl>
|
|
867
|
-
Http2ErrorCode code = settings_.mutable_local().Apply(
|
|
868
|
-
Http2Settings::kInitialWindowSizeWireId,
|
|
869
|
-
(Http2Settings::max_initial_window_size() - 1));
|
|
870
|
-
DCHECK(code == Http2ErrorCode::kNoError);
|
|
871
|
-
// </DeleteAfterFlowControl>
|
|
872
|
-
|
|
873
|
-
const int max_hpack_table_size =
|
|
874
|
-
channel_args.GetInt(GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER).value_or(-1);
|
|
875
|
-
if (max_hpack_table_size >= 0) {
|
|
876
|
-
encoder_.SetMaxUsableSize(max_hpack_table_size);
|
|
877
|
-
}
|
|
1437
|
+
ping_manager_.emplace(channel_args, args.ping_timeout,
|
|
1438
|
+
PingSystemInterfaceImpl::Make(this), event_engine_);
|
|
878
1439
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
1440
|
+
// The keepalive loop is only spawned if the keepalive time is not infinity.
|
|
1441
|
+
keepalive_manager_.emplace(
|
|
1442
|
+
KeepAliveInterfaceImpl::Make(this),
|
|
1443
|
+
((args.keepalive_timeout < args.ping_timeout) ? args.keepalive_timeout
|
|
1444
|
+
: Duration::Infinity()),
|
|
1445
|
+
args.keepalive_time, general_party_.get());
|
|
882
1446
|
|
|
883
|
-
|
|
884
|
-
settings_.MaybeSendUpdate();
|
|
885
|
-
if (settings_frame.has_value()) {
|
|
886
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
887
|
-
<< "Http2ClientTransport Constructor Spawn SendFirstSettingsFrame";
|
|
888
|
-
general_party_->Spawn(
|
|
889
|
-
"SendFirstSettingsFrame",
|
|
890
|
-
[self = RefAsSubclass<Http2ClientTransport>(),
|
|
891
|
-
frame = std::move(*settings_frame)]() mutable {
|
|
892
|
-
return self->EnqueueOutgoingFrame(std::move(frame));
|
|
893
|
-
},
|
|
894
|
-
[](GRPC_UNUSED absl::Status status) {});
|
|
895
|
-
}
|
|
896
|
-
if (settings_.local().allow_security_frame()) {
|
|
1447
|
+
if (settings_->local().allow_security_frame()) {
|
|
897
1448
|
// TODO(tjagtap) : [PH2][P3] : Setup the plumbing to pass the security frame
|
|
898
1449
|
// to the endpoing via TransportFramingEndpointExtension.
|
|
899
1450
|
// Also decide if this plumbing is done here, or when the peer sends
|
|
900
1451
|
// allow_security_frame too.
|
|
901
1452
|
}
|
|
1453
|
+
|
|
1454
|
+
GRPC_DCHECK(ping_manager_.has_value());
|
|
1455
|
+
GRPC_DCHECK(keepalive_manager_.has_value());
|
|
1456
|
+
SourceConstructed();
|
|
902
1457
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Constructor End";
|
|
903
1458
|
}
|
|
904
1459
|
|
|
905
|
-
|
|
906
|
-
|
|
1460
|
+
void Http2ClientTransport::SpawnTransportLoops() {
|
|
1461
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::SpawnTransportLoops Begin";
|
|
1462
|
+
SpawnGuardedTransportParty(
|
|
1463
|
+
"FlowControlPeriodicUpdateLoop",
|
|
1464
|
+
UntilTransportClosed(FlowControlPeriodicUpdateLoop()));
|
|
1465
|
+
|
|
1466
|
+
SpawnGuardedTransportParty("FlushInitialFrames", TriggerWriteCycle());
|
|
1467
|
+
SpawnGuardedTransportParty("MultiplexerLoop",
|
|
1468
|
+
UntilTransportClosed(MultiplexerLoop()));
|
|
1469
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::SpawnTransportLoops End";
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
void Http2ClientTransport::ReadChannelArgs(const ChannelArgs& channel_args,
|
|
1473
|
+
TransportChannelArgs& args) {
|
|
1474
|
+
http2::ReadChannelArgs(channel_args, args, settings_->mutable_local(),
|
|
1475
|
+
flow_control_,
|
|
1476
|
+
/*is_client=*/true);
|
|
1477
|
+
|
|
1478
|
+
// Assign the channel args to the member variables.
|
|
1479
|
+
keepalive_time_ = args.keepalive_time;
|
|
1480
|
+
incoming_headers_.set_soft_limit(args.max_header_list_size_soft_limit);
|
|
1481
|
+
keepalive_permit_without_calls_ = args.keepalive_permit_without_calls;
|
|
1482
|
+
enable_preferred_rx_crypto_frame_advertisement_ =
|
|
1483
|
+
args.enable_preferred_rx_crypto_frame_advertisement;
|
|
1484
|
+
test_only_ack_pings_ = args.test_only_ack_pings;
|
|
1485
|
+
|
|
1486
|
+
if (args.initial_sequence_number > 0) {
|
|
1487
|
+
next_stream_id_ = args.initial_sequence_number;
|
|
1488
|
+
}
|
|
1489
|
+
|
|
1490
|
+
settings_->SetSettingsTimeout(args.settings_timeout);
|
|
1491
|
+
if (args.max_usable_hpack_table_size >= 0) {
|
|
1492
|
+
encoder_.SetMaxUsableSize(args.max_usable_hpack_table_size);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
// This function MUST be idempotent. This function MUST be called from the
|
|
1497
|
+
// transport party.
|
|
1498
|
+
void Http2ClientTransport::CloseStream(RefCountedPtr<Stream> stream,
|
|
907
1499
|
CloseStreamArgs args,
|
|
908
1500
|
DebugLocation whence) {
|
|
909
|
-
|
|
910
|
-
<< stream_id << " status=" << status
|
|
911
|
-
<< " location=" << whence.file() << ":"
|
|
912
|
-
<< whence.line();
|
|
1501
|
+
std::optional<Http2Status> close_transport_error;
|
|
913
1502
|
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1503
|
+
{
|
|
1504
|
+
// TODO(akshitpatel) : [PH2][P3] : Measure the impact of holding mutex
|
|
1505
|
+
// throughout this function.
|
|
1506
|
+
MutexLock lock(&transport_mutex_);
|
|
1507
|
+
GRPC_DCHECK(stream != nullptr) << "stream is null";
|
|
919
1508
|
GRPC_HTTP2_CLIENT_DLOG
|
|
920
|
-
<< "Http2ClientTransport::CloseStream for stream id: "
|
|
921
|
-
<< "
|
|
922
|
-
|
|
1509
|
+
<< "Http2ClientTransport::CloseStream for stream id: "
|
|
1510
|
+
<< stream->GetStreamId() << " close_reads=" << args.close_reads
|
|
1511
|
+
<< " close_writes=" << args.close_writes
|
|
1512
|
+
<< " incoming_headers_=" << incoming_headers_.DebugString()
|
|
1513
|
+
<< " location=" << whence.file() << ":" << whence.line();
|
|
1514
|
+
|
|
1515
|
+
if (args.close_writes) {
|
|
1516
|
+
stream->SetWriteClosed();
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
if (args.close_reads) {
|
|
1520
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1521
|
+
<< "Http2ClientTransport::CloseStream for stream id: "
|
|
1522
|
+
<< stream->GetStreamId() << " closing stream for reads.";
|
|
1523
|
+
// If the stream is closed while reading HEADER/CONTINUATION frames, we
|
|
1524
|
+
// should still parse the enqueued buffer to maintain HPACK state between
|
|
1525
|
+
// peers.
|
|
1526
|
+
if (incoming_headers_.IsWaitingForContinuationFrame()) {
|
|
1527
|
+
Http2Status result = http2::ParseAndDiscardHeaders(
|
|
1528
|
+
parser_, SliceBuffer(),
|
|
1529
|
+
HeaderAssembler::ParseHeaderArgs{
|
|
1530
|
+
/*is_initial_metadata=*/!incoming_headers_.HeaderHasEndStream(),
|
|
1531
|
+
/*is_end_headers=*/false,
|
|
1532
|
+
/*is_client=*/true,
|
|
1533
|
+
/*max_header_list_size_soft_limit=*/
|
|
1534
|
+
incoming_headers_.soft_limit(),
|
|
1535
|
+
/*max_header_list_size_hard_limit=*/
|
|
1536
|
+
settings_->acked().max_header_list_size(),
|
|
1537
|
+
/*stream_id=*/incoming_headers_.GetStreamId(),
|
|
1538
|
+
},
|
|
1539
|
+
stream, /*original_status=*/Http2Status::Ok());
|
|
1540
|
+
if (result.GetType() == Http2Status::Http2ErrorType::kConnectionError) {
|
|
1541
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1542
|
+
<< "Http2ClientTransport::CloseStream for stream id: "
|
|
1543
|
+
<< stream->GetStreamId()
|
|
1544
|
+
<< " failed to partially process header: "
|
|
1545
|
+
<< result.DebugString();
|
|
1546
|
+
close_transport_error.emplace(std::move(result));
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
stream_list_.erase(stream->GetStreamId());
|
|
1551
|
+
if (!close_transport_error.has_value() && CanCloseTransportLocked()) {
|
|
1552
|
+
// TODO(akshitpatel) : [PH2][P3] : Is kInternalError the right error
|
|
1553
|
+
// code to use here? IMO it should be kNoError.
|
|
1554
|
+
close_transport_error.emplace(Http2Status::Http2ConnectionError(
|
|
1555
|
+
Http2ErrorCode::kInternalError,
|
|
1556
|
+
std::string(RFC9113::kLastStreamClosed)));
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
923
1559
|
}
|
|
924
|
-
auto& stream = pair->second;
|
|
925
1560
|
|
|
926
|
-
if (
|
|
927
|
-
|
|
1561
|
+
if (close_transport_error.has_value()) {
|
|
1562
|
+
GRPC_UNUSED absl::Status status = HandleError(
|
|
1563
|
+
/*stream_id=*/std::nullopt, std::move(*close_transport_error));
|
|
928
1564
|
}
|
|
929
|
-
|
|
930
|
-
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
// This function is idempotent and MUST be called from the transport party.
|
|
1568
|
+
// All the scenarios that can lead to this function being called are:
|
|
1569
|
+
// 1. Reading a RST stream frame: In this case, the stream is immediately
|
|
1570
|
+
// closed for reads and writes and removed from the stream_list_.
|
|
1571
|
+
// 2. Reading a Trailing Metadata frame: There are two possible scenarios:
|
|
1572
|
+
// a. The stream is closed for writes: Close the stream for reads and writes
|
|
1573
|
+
// and remove the stream from the stream_list_.
|
|
1574
|
+
// b. The stream is NOT closed for writes: Stream is kept open for reads and
|
|
1575
|
+
// writes. CallHandler OnDone will trigger sending a half close frame. If
|
|
1576
|
+
// before the multiplexer loop triggers sending a half close a RST stream
|
|
1577
|
+
// is read, the stream is closed for reads and writes immediately and the
|
|
1578
|
+
// half close is discarded. If no RST stream is read, the stream is closed
|
|
1579
|
+
// for reads and writes upon sending the half close frame from the
|
|
1580
|
+
// multiplexer loop.
|
|
1581
|
+
// 3. Hitting error condition in the transport: In this case, RST stream is
|
|
1582
|
+
// enqueued and the stream is closed for reads immediately. This implies we
|
|
1583
|
+
// reduce the number of active streams inline. When multiplexer loop
|
|
1584
|
+
// processes the RST stream frame, the stream ref will dropped. The other
|
|
1585
|
+
// stream ref will be dropped when CallHandler's OnDone is executed causing
|
|
1586
|
+
// the stream to be destroyed. CallHandlers OnDone also tries to enqueue a
|
|
1587
|
+
// RST stream frame. This is a no-op at this point.
|
|
1588
|
+
// 4. Application abort: In this case, CallHandler OnDone will enqueue RST
|
|
1589
|
+
// stream frame to the stream data queue. The multiplexer loop will send the
|
|
1590
|
+
// reset stream frame and close the stream from reads and writes.
|
|
1591
|
+
// 5. Transport close: This takes up the same path as case 3.
|
|
1592
|
+
// In all the above cases, trailing metadata is pushed to the call spine.
|
|
1593
|
+
// Note: The stream ref is held in atmost 3 places:
|
|
1594
|
+
// 1. stream_list_ : This is released when the stream is closed for reads.
|
|
1595
|
+
// 2. CallHandler OnDone : This is released when Trailing Metadata is pushed to
|
|
1596
|
+
// the call spine.
|
|
1597
|
+
// 3. List of writable streams : This is released after the final frame is
|
|
1598
|
+
// dequeued from the StreamDataQueue.
|
|
1599
|
+
void Http2ClientTransport::BeginCloseStream(
|
|
1600
|
+
RefCountedPtr<Stream> stream,
|
|
1601
|
+
std::optional<uint32_t> reset_stream_error_code,
|
|
1602
|
+
ServerMetadataHandle&& metadata, DebugLocation whence) {
|
|
1603
|
+
if (stream == nullptr) {
|
|
1604
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::BeginCloseStream stream "
|
|
1605
|
+
"is null reset_stream_error_code="
|
|
1606
|
+
<< (reset_stream_error_code.has_value()
|
|
1607
|
+
? absl::StrCat(*reset_stream_error_code)
|
|
1608
|
+
: "nullopt")
|
|
1609
|
+
<< " metadata=" << metadata->DebugString();
|
|
1610
|
+
return;
|
|
931
1611
|
}
|
|
932
1612
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
1613
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1614
|
+
<< "Http2ClientTransport::BeginCloseStream for stream id: "
|
|
1615
|
+
<< stream->GetStreamId() << " error_code="
|
|
1616
|
+
<< (reset_stream_error_code.has_value()
|
|
1617
|
+
? absl::StrCat(*reset_stream_error_code)
|
|
1618
|
+
: "nullopt")
|
|
1619
|
+
<< " ServerMetadata=" << metadata->DebugString()
|
|
1620
|
+
<< " location=" << whence.file() << ":" << whence.line();
|
|
1621
|
+
|
|
1622
|
+
bool close_reads = false;
|
|
1623
|
+
bool close_writes = false;
|
|
1624
|
+
if (metadata->get(GrpcCallWasCancelled())) {
|
|
1625
|
+
if (!reset_stream_error_code) {
|
|
1626
|
+
// Callers taking this path:
|
|
1627
|
+
// 1. Reading a RST stream frame (will not send any frame out).
|
|
1628
|
+
// 2. Closing a stream before initial metadata is sent.
|
|
1629
|
+
close_reads = true;
|
|
1630
|
+
close_writes = true;
|
|
1631
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1632
|
+
<< "Http2ClientTransport::BeginCloseStream for stream id: "
|
|
1633
|
+
<< stream->GetStreamId() << " close_reads= " << close_reads
|
|
1634
|
+
<< " close_writes= " << close_writes;
|
|
1635
|
+
} else {
|
|
1636
|
+
// Callers taking this path:
|
|
1637
|
+
// 1. Processing Error in transport (will send reset stream from here).
|
|
1638
|
+
absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
|
|
1639
|
+
stream->EnqueueResetStream(reset_stream_error_code.value());
|
|
1640
|
+
GRPC_HTTP2_CLIENT_DLOG << "Enqueued ResetStream with error code="
|
|
1641
|
+
<< reset_stream_error_code.value()
|
|
1642
|
+
<< " status=" << enqueue_result.status();
|
|
1643
|
+
if (enqueue_result.ok()) {
|
|
1644
|
+
GRPC_UNUSED absl::Status status =
|
|
1645
|
+
MaybeAddStreamToWritableStreamList(stream, enqueue_result.value());
|
|
1646
|
+
}
|
|
1647
|
+
close_reads = true;
|
|
1648
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1649
|
+
<< "Http2ClientTransport::BeginCloseStream for stream id: "
|
|
1650
|
+
<< stream->GetStreamId() << " close_reads= " << close_reads
|
|
1651
|
+
<< " close_writes= " << close_writes;
|
|
939
1652
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1653
|
+
} else {
|
|
1654
|
+
// Callers taking this path:
|
|
1655
|
+
// 1. Reading Trailing Metadata (MAY send half close from OnDone).
|
|
1656
|
+
if (stream->IsClosedForWrites()) {
|
|
1657
|
+
close_reads = true;
|
|
1658
|
+
close_writes = true;
|
|
1659
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1660
|
+
<< "Http2ClientTransport::BeginCloseStream for stream id: "
|
|
1661
|
+
<< stream->GetStreamId() << " close_reads= " << close_reads
|
|
1662
|
+
<< " close_writes= " << close_writes;
|
|
944
1663
|
}
|
|
945
|
-
stream_list_.erase(stream_id);
|
|
946
1664
|
}
|
|
1665
|
+
|
|
1666
|
+
if (close_reads || close_writes) {
|
|
1667
|
+
CloseStream(stream, CloseStreamArgs{close_reads, close_writes}, whence);
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
// If the call was cancelled, the stream MUST be closed for reads.
|
|
1671
|
+
GRPC_DCHECK(metadata->get(GrpcCallWasCancelled()) ? close_reads : true);
|
|
1672
|
+
|
|
1673
|
+
// This maybe called multiple times while closing a stream. In CallV3, the
|
|
1674
|
+
// flow for pushing server trailing metadata is idempotent. However, there is
|
|
1675
|
+
// a subtle difference. When we push server trailing metadata with a cancelled
|
|
1676
|
+
// status PushServerTrailingMetadata is spawned inline on the Call party
|
|
1677
|
+
// whereas for the non-cancelled status, PushServerTrailingMetadata is
|
|
1678
|
+
// spawned in the server_to_client spawn serializer. Because of this, in
|
|
1679
|
+
// case when the server pushes trailing metadata (non-cancelled) followed by a
|
|
1680
|
+
// RST stream with cancelled status, it is possible that the cancelled
|
|
1681
|
+
// trailing metadata (for RST stream) is processed before. This would result
|
|
1682
|
+
// in losing the actual status/message pushed by the server.
|
|
1683
|
+
// To address this, we push the server trailing metadata to the stream only
|
|
1684
|
+
// if it is not pushed already.
|
|
1685
|
+
stream->MaybePushServerTrailingMetadata(std::move(metadata));
|
|
947
1686
|
}
|
|
948
1687
|
|
|
949
1688
|
void Http2ClientTransport::CloseTransport() {
|
|
950
1689
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::CloseTransport";
|
|
951
1690
|
|
|
952
|
-
|
|
953
|
-
|
|
1691
|
+
transport_closed_latch_.Set();
|
|
1692
|
+
settings_->HandleTransportShutdown(event_engine_.get());
|
|
1693
|
+
|
|
1694
|
+
MutexLock lock(&transport_mutex_);
|
|
1695
|
+
// This is the only place where the general_party_ is reset.
|
|
954
1696
|
general_party_.reset();
|
|
955
1697
|
}
|
|
956
1698
|
|
|
@@ -976,16 +1718,15 @@ void Http2ClientTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
|
|
|
976
1718
|
absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>> stream_list =
|
|
977
1719
|
std::move(stream_list_);
|
|
978
1720
|
stream_list_.clear();
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1721
|
+
ReportDisconnectionLocked(
|
|
1722
|
+
http2_status.GetAbslConnectionError(), {},
|
|
1723
|
+
absl::StrCat("Transport closed: ", http2_status.DebugString()).c_str());
|
|
982
1724
|
lock.Release();
|
|
983
1725
|
|
|
984
|
-
|
|
985
|
-
"CloseTransport",
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
http2_status = std::move(http2_status)]() mutable {
|
|
1726
|
+
SpawnInfallibleTransportParty(
|
|
1727
|
+
"CloseTransport", [self = RefAsSubclass<Http2ClientTransport>(),
|
|
1728
|
+
stream_list = std::move(stream_list),
|
|
1729
|
+
http2_status = std::move(http2_status)]() mutable {
|
|
989
1730
|
GRPC_HTTP2_CLIENT_DLOG
|
|
990
1731
|
<< "Http2ClientTransport::CloseTransport Cleaning up call stacks";
|
|
991
1732
|
// Clean up the call stacks for all active streams.
|
|
@@ -995,37 +1736,132 @@ void Http2ClientTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
|
|
|
995
1736
|
// fail. Also, as this is running on the transport
|
|
996
1737
|
// party, there would not be concurrent access to the stream.
|
|
997
1738
|
auto& stream = pair.second;
|
|
998
|
-
|
|
999
|
-
|
|
1739
|
+
self->BeginCloseStream(stream,
|
|
1740
|
+
Http2ErrorCodeToFrameErrorCode(
|
|
1741
|
+
http2_status.GetConnectionErrorCode()),
|
|
1742
|
+
CancelledServerMetadataFromStatus(
|
|
1743
|
+
http2_status.GetAbslConnectionError()));
|
|
1000
1744
|
}
|
|
1001
1745
|
|
|
1002
1746
|
// RFC9113 : A GOAWAY frame might not immediately precede closing of
|
|
1003
1747
|
// the connection; a receiver of a GOAWAY that has no more use for the
|
|
1004
1748
|
// connection SHOULD still send a GOAWAY frame before terminating the
|
|
1005
1749
|
// connection.
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
self->
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1750
|
+
return Map(
|
|
1751
|
+
// TODO(akshitpatel) : [PH2][P4] : This is creating a copy of
|
|
1752
|
+
// the debug data. Verify if this is causing a performance
|
|
1753
|
+
// issue.
|
|
1754
|
+
Race(AssertResultType<absl::Status>(
|
|
1755
|
+
self->goaway_manager_.RequestGoaway(
|
|
1756
|
+
http2_status.GetConnectionErrorCode(),
|
|
1757
|
+
/*debug_data=*/
|
|
1758
|
+
Slice::FromCopiedString(
|
|
1759
|
+
http2_status.GetAbslConnectionError().message()),
|
|
1760
|
+
kLastIncomingStreamIdClient, /*immediate=*/true)),
|
|
1761
|
+
// Failsafe to close the transport if goaway is not
|
|
1762
|
+
// sent within kGoawaySendTimeoutSeconds seconds.
|
|
1763
|
+
Sleep(Duration::Seconds(kGoawaySendTimeoutSeconds))),
|
|
1764
|
+
[self](auto) mutable {
|
|
1765
|
+
self->CloseTransport();
|
|
1766
|
+
return Empty{};
|
|
1767
|
+
});
|
|
1768
|
+
;
|
|
1769
|
+
});
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
bool Http2ClientTransport::CanCloseTransportLocked() const {
|
|
1773
|
+
// If there are no more streams and next stream id is greater than the
|
|
1774
|
+
// max allowed stream id, then no more streams can be created and it is
|
|
1775
|
+
// safe to close the transport.
|
|
1776
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::CanCloseTransportLocked "
|
|
1777
|
+
"GetActiveStreamCountLocked="
|
|
1778
|
+
<< GetActiveStreamCountLocked()
|
|
1779
|
+
<< " PeekNextStreamId=" << PeekNextStreamId()
|
|
1780
|
+
<< " GetMaxAllowedStreamId="
|
|
1781
|
+
<< GetMaxAllowedStreamId();
|
|
1782
|
+
return GetActiveStreamCountLocked() == 0 &&
|
|
1783
|
+
PeekNextStreamId() > GetMaxAllowedStreamId();
|
|
1016
1784
|
}
|
|
1017
1785
|
|
|
1018
1786
|
Http2ClientTransport::~Http2ClientTransport() {
|
|
1019
1787
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Destructor Begin";
|
|
1020
|
-
|
|
1788
|
+
GRPC_DCHECK(stream_list_.empty());
|
|
1789
|
+
GRPC_DCHECK(general_party_ == nullptr);
|
|
1790
|
+
memory_owner_.Reset();
|
|
1021
1791
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport Destructor End";
|
|
1022
1792
|
}
|
|
1023
1793
|
|
|
1794
|
+
void Http2ClientTransport::SpawnAddChannelzData(RefCountedPtr<Party> party,
|
|
1795
|
+
channelz::DataSink sink) {
|
|
1796
|
+
SpawnInfallible(
|
|
1797
|
+
std::move(party), "AddData",
|
|
1798
|
+
[self = RefAsSubclass<Http2ClientTransport>(),
|
|
1799
|
+
sink = std::move(sink)]() mutable {
|
|
1800
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::AddData Promise";
|
|
1801
|
+
sink.AddData(
|
|
1802
|
+
"Http2ClientTransport",
|
|
1803
|
+
channelz::PropertyList()
|
|
1804
|
+
.Set("keepalive_time", self->keepalive_time_)
|
|
1805
|
+
.Set("keepalive_permit_without_calls",
|
|
1806
|
+
self->keepalive_permit_without_calls_)
|
|
1807
|
+
.Set("settings", self->settings_->ChannelzProperties())
|
|
1808
|
+
.Set("flow_control",
|
|
1809
|
+
self->flow_control_.stats().ChannelzProperties()));
|
|
1810
|
+
self->general_party_->ExportToChannelz("Http2ClientTransport Party",
|
|
1811
|
+
sink);
|
|
1812
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::AddData End";
|
|
1813
|
+
return Empty{};
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
void Http2ClientTransport::AddData(channelz::DataSink sink) {
|
|
1818
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::AddData Begin";
|
|
1819
|
+
|
|
1820
|
+
event_engine_->Run([self = RefAsSubclass<Http2ClientTransport>(),
|
|
1821
|
+
sink = std::move(sink)]() mutable {
|
|
1822
|
+
bool is_party_null = false;
|
|
1823
|
+
{
|
|
1824
|
+
// Apart from CloseTransport, this is the only place where a lock is taken
|
|
1825
|
+
// to access general_party_. All other access to general_party_ happens
|
|
1826
|
+
// on the general party itself and hence do not race with CloseTransport.
|
|
1827
|
+
// TODO(akshitpatel) : [PH2][P4] : Check if a new mutex is needed to
|
|
1828
|
+
// protect general_party_. Curently transport_mutex_ can is used in
|
|
1829
|
+
// these places:
|
|
1830
|
+
// 1. In promises running on the transport party
|
|
1831
|
+
// 2. In AddData promise
|
|
1832
|
+
// 3. In Orphan function.
|
|
1833
|
+
// 4. Stream creation (this will be removed soon).
|
|
1834
|
+
// Given that #1 is already serialized (guaranteed by party), #2 is on
|
|
1835
|
+
// demand and #3 happens once for the lifetime of the transport while
|
|
1836
|
+
// closing the transport, the contention should be minimal.
|
|
1837
|
+
MutexLock lock(&self->transport_mutex_);
|
|
1838
|
+
// TODO(akshitpatel) : [PH2][P2] : There is still a potential for a race
|
|
1839
|
+
// here where the general_party_ is reset between the lock being
|
|
1840
|
+
// released and the spawn. We cannot just do a spawn inside the mutex as
|
|
1841
|
+
// that may result in deadlock.
|
|
1842
|
+
// Potential fix to hold a ref to the party inside the mutex and do a
|
|
1843
|
+
// spawn outside the mutex. The only side effect is that this introduces
|
|
1844
|
+
// an additional ref to the party other the transport's copy.
|
|
1845
|
+
if (GPR_UNLIKELY(self->general_party_ == nullptr)) {
|
|
1846
|
+
is_party_null = true;
|
|
1847
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1848
|
+
<< "Http2ClientTransport::AddData general_party_ is "
|
|
1849
|
+
"null. Transport is closed.";
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
ExecCtx exec_ctx;
|
|
1854
|
+
if (!is_party_null) {
|
|
1855
|
+
self->SpawnAddChannelzData(self->general_party_, std::move(sink));
|
|
1856
|
+
}
|
|
1857
|
+
self.reset(); // Cleanup with exec_ctx in scope
|
|
1858
|
+
});
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1024
1861
|
///////////////////////////////////////////////////////////////////////////////
|
|
1025
1862
|
// Stream Related Operations
|
|
1026
1863
|
|
|
1027
|
-
RefCountedPtr<
|
|
1028
|
-
uint32_t stream_id) {
|
|
1864
|
+
RefCountedPtr<Stream> Http2ClientTransport::LookupStream(uint32_t stream_id) {
|
|
1029
1865
|
MutexLock lock(&transport_mutex_);
|
|
1030
1866
|
auto it = stream_list_.find(stream_id);
|
|
1031
1867
|
if (it == stream_list_.end()) {
|
|
@@ -1037,134 +1873,146 @@ RefCountedPtr<Http2ClientTransport::Stream> Http2ClientTransport::LookupStream(
|
|
|
1037
1873
|
return it->second;
|
|
1038
1874
|
}
|
|
1039
1875
|
|
|
1040
|
-
bool Http2ClientTransport::
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
// TODO(akshitpatel) : [PH2][P1] : Probably do not need this lock. This
|
|
1046
|
-
// function is always called under the stream_id_mutex_. The issue is the
|
|
1047
|
-
// OnDone needs to be synchronous and hence InterActivityMutex might not be
|
|
1048
|
-
// an option to protect the stream_list_.
|
|
1049
|
-
MutexLock lock(&transport_mutex_);
|
|
1050
|
-
const bool on_done_added =
|
|
1051
|
-
call_handler.OnDone([self = RefAsSubclass<Http2ClientTransport>(),
|
|
1052
|
-
stream_id](bool cancelled) {
|
|
1876
|
+
bool Http2ClientTransport::SetOnDone(CallHandler call_handler,
|
|
1877
|
+
RefCountedPtr<Stream> stream) {
|
|
1878
|
+
return call_handler.OnDone(
|
|
1879
|
+
[self = RefAsSubclass<Http2ClientTransport>(), stream,
|
|
1880
|
+
stream_id = stream->GetStreamId()](bool cancelled) {
|
|
1053
1881
|
GRPC_HTTP2_CLIENT_DLOG << "PH2: Client call " << self.get()
|
|
1054
1882
|
<< " id=" << stream_id
|
|
1055
1883
|
<< " done: cancelled=" << cancelled;
|
|
1884
|
+
absl::StatusOr<StreamWritabilityUpdate> enqueue_result;
|
|
1885
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1886
|
+
<< "PH2: Client call " << self.get() << " id=" << stream_id
|
|
1887
|
+
<< " done: stream=" << stream.get() << " cancelled=" << cancelled;
|
|
1056
1888
|
if (cancelled) {
|
|
1057
|
-
//
|
|
1058
|
-
//
|
|
1059
|
-
//
|
|
1060
|
-
//
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1889
|
+
// In most of the cases, EnqueueResetStream would be a no-op as
|
|
1890
|
+
// BeginCloseStream would have already enqueued the reset stream.
|
|
1891
|
+
// Currently only Aborts from application will actually enqueue
|
|
1892
|
+
// the reset stream here.
|
|
1893
|
+
enqueue_result = stream->EnqueueResetStream(
|
|
1894
|
+
static_cast<uint32_t>(Http2ErrorCode::kCancel));
|
|
1895
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1896
|
+
<< "Enqueued ResetStream with error code="
|
|
1897
|
+
<< static_cast<uint32_t>(Http2ErrorCode::kCancel)
|
|
1898
|
+
<< " status=" << enqueue_result.status();
|
|
1899
|
+
} else {
|
|
1900
|
+
enqueue_result = stream->EnqueueHalfClosed();
|
|
1901
|
+
GRPC_HTTP2_CLIENT_DLOG << "Enqueued HalfClosed with result="
|
|
1902
|
+
<< enqueue_result.status();
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
if (enqueue_result.ok()) {
|
|
1906
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1907
|
+
<< "Http2ClientTransport::SetOnDone "
|
|
1908
|
+
"MaybeAddStreamToWritableStreamList for stream= "
|
|
1909
|
+
<< stream->GetStreamId() << " enqueue_result={became_writable="
|
|
1910
|
+
<< enqueue_result.value().became_writable << ", priority="
|
|
1911
|
+
<< static_cast<uint8_t>(enqueue_result.value().priority) << "}";
|
|
1912
|
+
GRPC_UNUSED absl::Status status =
|
|
1913
|
+
self->MaybeAddStreamToWritableStreamList(stream,
|
|
1914
|
+
enqueue_result.value());
|
|
1074
1915
|
}
|
|
1075
1916
|
});
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
std::optional<RefCountedPtr<Stream>> Http2ClientTransport::MakeStream(
|
|
1920
|
+
CallHandler call_handler) {
|
|
1921
|
+
// https://datatracker.ietf.org/doc/html/rfc9113#name-stream-identifiers
|
|
1922
|
+
RefCountedPtr<Stream> stream;
|
|
1923
|
+
{
|
|
1924
|
+
// TODO(akshitpatel) : [PH2][P3] : Remove this mutex once settings is in
|
|
1925
|
+
// place.
|
|
1926
|
+
MutexLock lock(&transport_mutex_);
|
|
1927
|
+
stream = MakeRefCounted<Stream>(call_handler, flow_control_);
|
|
1928
|
+
}
|
|
1929
|
+
const bool on_done_added = SetOnDone(call_handler, stream);
|
|
1930
|
+
if (!on_done_added) return std::nullopt;
|
|
1931
|
+
return stream;
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
uint32_t Http2ClientTransport::GetMaxAllowedStreamId() const {
|
|
1935
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport GetMaxAllowedStreamId "
|
|
1936
|
+
<< max_allowed_stream_id_;
|
|
1937
|
+
return max_allowed_stream_id_;
|
|
1938
|
+
}
|
|
1939
|
+
|
|
1940
|
+
void Http2ClientTransport::SetMaxAllowedStreamId(
|
|
1941
|
+
const uint32_t max_allowed_stream_id) {
|
|
1942
|
+
const uint32_t old_max_allowed_stream_id = GetMaxAllowedStreamId();
|
|
1943
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport SetMaxAllowedStreamId "
|
|
1944
|
+
<< " max_allowed_stream_id: " << max_allowed_stream_id
|
|
1945
|
+
<< " old_allowed_max_stream_id: "
|
|
1946
|
+
<< old_max_allowed_stream_id;
|
|
1947
|
+
// RFC9113 : Endpoints MUST NOT increase the value they send in the last
|
|
1948
|
+
// stream identifier, since the peers might already have retried unprocessed
|
|
1949
|
+
// requests on another connection.
|
|
1950
|
+
if (GPR_LIKELY(max_allowed_stream_id <= old_max_allowed_stream_id)) {
|
|
1951
|
+
max_allowed_stream_id_ = max_allowed_stream_id;
|
|
1952
|
+
} else {
|
|
1953
|
+
LOG_IF(ERROR, max_allowed_stream_id > old_max_allowed_stream_id)
|
|
1954
|
+
<< "Endpoints MUST NOT increase the value they send in the last "
|
|
1955
|
+
"stream "
|
|
1956
|
+
"identifier";
|
|
1957
|
+
GRPC_DCHECK_LE(max_allowed_stream_id, old_max_allowed_stream_id)
|
|
1958
|
+
<< "Endpoints MUST NOT increase the value they send in the last "
|
|
1959
|
+
"stream "
|
|
1960
|
+
"identifier";
|
|
1961
|
+
}
|
|
1080
1962
|
}
|
|
1081
1963
|
|
|
1082
1964
|
///////////////////////////////////////////////////////////////////////////////
|
|
1083
1965
|
// Call Spine related operations
|
|
1084
1966
|
|
|
1085
|
-
auto Http2ClientTransport::CallOutboundLoop(
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
ClientMetadataHandle metadata) {
|
|
1967
|
+
auto Http2ClientTransport::CallOutboundLoop(CallHandler call_handler,
|
|
1968
|
+
RefCountedPtr<Stream> stream,
|
|
1969
|
+
ClientMetadataHandle metadata) {
|
|
1089
1970
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport CallOutboundLoop";
|
|
1971
|
+
GRPC_DCHECK(stream != nullptr);
|
|
1090
1972
|
|
|
1091
1973
|
auto send_message = [self = RefAsSubclass<Http2ClientTransport>(),
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
"Enqueued Message";
|
|
1102
|
-
return self->MaybeAddStreamToWritableStreamList(
|
|
1103
|
-
stream_id, became_writable);
|
|
1104
|
-
});
|
|
1105
|
-
},
|
|
1106
|
-
[]() {
|
|
1107
|
-
// This will trigger Call stack cleanup.
|
|
1108
|
-
return absl::InternalError("Stream not found while sending message");
|
|
1109
|
-
});
|
|
1974
|
+
stream](MessageHandle&& message) mutable {
|
|
1975
|
+
return TrySeq(stream->EnqueueMessage(std::move(message)),
|
|
1976
|
+
[self, stream](const StreamWritabilityUpdate result) mutable {
|
|
1977
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
1978
|
+
<< "Http2ClientTransport CallOutboundLoop "
|
|
1979
|
+
"Enqueued Message";
|
|
1980
|
+
return self->MaybeAddStreamToWritableStreamList(
|
|
1981
|
+
std::move(stream), result);
|
|
1982
|
+
});
|
|
1110
1983
|
};
|
|
1111
1984
|
|
|
1112
1985
|
auto send_initial_metadata = [self = RefAsSubclass<Http2ClientTransport>(),
|
|
1113
|
-
|
|
1986
|
+
stream,
|
|
1114
1987
|
metadata = std::move(metadata)]() mutable {
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
[self, stream, metadata = std::move(metadata), stream_id]() mutable {
|
|
1119
|
-
return TrySeq(
|
|
1120
|
-
stream->EnqueueInitialMetadata(std::move(metadata)),
|
|
1121
|
-
[self, stream_id](bool became_writable) {
|
|
1122
|
-
GRPC_HTTP2_CLIENT_DLOG
|
|
1123
|
-
<< "Http2ClientTransport CallOutboundLoop "
|
|
1124
|
-
"Enqueued Initial Metadata";
|
|
1125
|
-
return self->MaybeAddStreamToWritableStreamList(
|
|
1126
|
-
stream_id, became_writable);
|
|
1127
|
-
},
|
|
1128
|
-
[stream] {
|
|
1129
|
-
// TODO(akshitpatel) : [PH2][P2] : Think how to handle stream
|
|
1130
|
-
// states.
|
|
1131
|
-
stream->SentInitialMetadata();
|
|
1132
|
-
return absl::OkStatus();
|
|
1133
|
-
});
|
|
1988
|
+
return TrySeq(
|
|
1989
|
+
[stream, metadata = std::move(metadata)]() mutable {
|
|
1990
|
+
return stream->EnqueueInitialMetadata(std::move(metadata));
|
|
1134
1991
|
},
|
|
1135
|
-
[]() {
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1992
|
+
[self, stream](const StreamWritabilityUpdate result) mutable {
|
|
1993
|
+
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport CallOutboundLoop "
|
|
1994
|
+
"Enqueued Initial Metadata";
|
|
1995
|
+
return self->MaybeAddStreamToWritableStreamList(std::move(stream),
|
|
1996
|
+
result);
|
|
1139
1997
|
});
|
|
1140
1998
|
};
|
|
1141
1999
|
|
|
1142
2000
|
auto send_half_closed = [self = RefAsSubclass<Http2ClientTransport>(),
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
"Enqueued Half Closed";
|
|
1153
|
-
return self->MaybeAddStreamToWritableStreamList(
|
|
1154
|
-
stream_id, became_writable);
|
|
1155
|
-
});
|
|
1156
|
-
},
|
|
1157
|
-
[]() {
|
|
1158
|
-
// This will trigger Call stack cleanup.
|
|
1159
|
-
return absl::InternalError(
|
|
1160
|
-
"Stream not found while sending half closed");
|
|
1161
|
-
});
|
|
2001
|
+
stream]() mutable {
|
|
2002
|
+
return TrySeq([stream]() { return stream->EnqueueHalfClosed(); },
|
|
2003
|
+
[self, stream](const StreamWritabilityUpdate result) mutable {
|
|
2004
|
+
GRPC_HTTP2_CLIENT_DLOG
|
|
2005
|
+
<< "Http2ClientTransport CallOutboundLoop "
|
|
2006
|
+
"Enqueued Half Closed";
|
|
2007
|
+
return self->MaybeAddStreamToWritableStreamList(
|
|
2008
|
+
std::move(stream), result);
|
|
2009
|
+
});
|
|
1162
2010
|
};
|
|
1163
2011
|
return GRPC_LATENT_SEE_PROMISE(
|
|
1164
2012
|
"Ph2CallOutboundLoop",
|
|
1165
2013
|
TrySeq(
|
|
1166
2014
|
send_initial_metadata(),
|
|
1167
|
-
[call_handler, send_message
|
|
2015
|
+
[call_handler, send_message]() {
|
|
1168
2016
|
// The lock will be released once the promise is constructed from
|
|
1169
2017
|
// this factory. ForEach will be polled after the lock is
|
|
1170
2018
|
// released.
|
|
@@ -1189,43 +2037,38 @@ void Http2ClientTransport::StartCall(CallHandler call_handler) {
|
|
|
1189
2037
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport StartCall Begin";
|
|
1190
2038
|
call_handler.SpawnGuarded(
|
|
1191
2039
|
"OutboundLoop",
|
|
1192
|
-
TrySeq(
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
std::move(std::get<1>(args))),
|
|
1225
|
-
[](absl::Status status) { return status; });
|
|
1226
|
-
},
|
|
1227
|
-
[]() { return absl::InternalError("Failed to make stream"); });
|
|
1228
|
-
}));
|
|
2040
|
+
TrySeq(call_handler.PullClientInitialMetadata(),
|
|
2041
|
+
[self = RefAsSubclass<Http2ClientTransport>(),
|
|
2042
|
+
call_handler](ClientMetadataHandle metadata) mutable {
|
|
2043
|
+
// For a gRPC Client, we only need to check the
|
|
2044
|
+
// MAX_CONCURRENT_STREAMS setting compliance at the time of
|
|
2045
|
+
// sending (that is write path). A gRPC Client will never
|
|
2046
|
+
// receive a stream initiated by a server, so we dont have to
|
|
2047
|
+
// check MAX_CONCURRENT_STREAMS compliance on the Read-Path.
|
|
2048
|
+
//
|
|
2049
|
+
// TODO(tjagtap) : [PH2][P1] Check for MAX_CONCURRENT_STREAMS
|
|
2050
|
+
// sent by peer before making a stream. Decide behaviour if we
|
|
2051
|
+
// are crossing this threshold.
|
|
2052
|
+
//
|
|
2053
|
+
// TODO(tjagtap) : [PH2][P1] : For a server we will have to do
|
|
2054
|
+
// this for incoming streams only. If a server receives more
|
|
2055
|
+
// streams from a client than is allowed by the clients settings,
|
|
2056
|
+
// whether or not we should fail is debatable.
|
|
2057
|
+
std::optional<RefCountedPtr<Stream>> stream =
|
|
2058
|
+
self->MakeStream(call_handler);
|
|
2059
|
+
return If(
|
|
2060
|
+
stream.has_value(),
|
|
2061
|
+
[self, call_handler, stream,
|
|
2062
|
+
initial_metadata = std::move(metadata)]() mutable {
|
|
2063
|
+
return Map(
|
|
2064
|
+
self->CallOutboundLoop(call_handler, stream.value(),
|
|
2065
|
+
std::move(initial_metadata)),
|
|
2066
|
+
[](absl::Status status) { return status; });
|
|
2067
|
+
},
|
|
2068
|
+
[]() {
|
|
2069
|
+
return absl::InternalError("Failed to make stream");
|
|
2070
|
+
});
|
|
2071
|
+
}));
|
|
1229
2072
|
GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport StartCall End";
|
|
1230
2073
|
}
|
|
1231
2074
|
|